diff --git a/README.markdown b/README.markdown index 2f9384a..ed3cca0 100644 --- a/README.markdown +++ b/README.markdown @@ -33,7 +33,7 @@ From command line: Infos ----- -Kanboard v1.0.19 +Kanboard v1.0.21 Yunohost forum thread: @@ -42,8 +42,8 @@ Kanboard and SSOwat Kanboard use SSOwat for user authentification (it means it use the user that the web server (nginx) sent him throught SSOwat), but can't list all user of the system. If you wish to add a user, just log in with that user into Kanboard so the software knows him and displays it. -Dev infos ---------- +Developper infos +---------------- Update package: diff --git a/conf/config.php b/conf/config.php index 21c5bf7..32a11a9 100644 --- a/conf/config.php +++ b/conf/config.php @@ -4,13 +4,13 @@ define('DEBUG', false); // Debug file path -define('DEBUG_FILE', __DIR__.'/data/debug.log'); +define('DEBUG_FILE', __DIR__.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'debug.log'); // Plugins directory -define('PLUGINS_DIR', 'data/plugins'); +define('PLUGINS_DIR', 'plugins'); -// Folder for uploaded files, don't forget the trailing slash -define('FILES_DIR', 'data/files/'); +// Folder for uploaded files +define('FILES_DIR', 'data'.DIRECTORY_SEPARATOR.'files'); // E-mail address for the "From" header (notifications) define('MAIL_FROM', 'yuno_email'); @@ -146,7 +146,7 @@ define('GITHUB_OAUTH_AUTHORIZE_URL', 'https://github.com/login/oauth/authorize') // Github oauth2 token url define('GITHUB_OAUTH_TOKEN_URL', 'https://github.com/login/oauth/access_token'); -// Github API url (don't forget the slash at the end) +// Github API url (don't forget the trailing slash) define('GITHUB_API_URL', 'https://api.github.com/'); // Enable/disable Gitlab authentication @@ -164,7 +164,7 @@ define('GITLAB_OAUTH_AUTHORIZE_URL', 'https://gitlab.com/oauth/authorize'); // Gitlab oauth2 token url define('GITLAB_OAUTH_TOKEN_URL', 'https://gitlab.com/oauth/token'); -// Gitlab API url endpoint (don't forget the slash at the end) +// Gitlab API url endpoint (don't forget the trailing slash) define('GITLAB_API_URL', 'https://gitlab.com/api/v3/'); // Enable/disable the reverse proxy authentication diff --git a/sources/ChangeLog b/sources/ChangeLog index 87bb379..56bbcdf 100644 --- a/sources/ChangeLog +++ b/sources/ChangeLog @@ -1,11 +1,50 @@ +Version 1.0.21 +-------------- + +Breaking changes: + +* Projects with duplicate name are now allowed: + For Postgres and Mysql the unique constraint is removed by database migration + However Sqlite does not support alter table, only new databases will have the unique constraint removed + +New features: + +* New automatic action: Assign a category based on a link +* Added Bosnian translation + +Improvements: + +* Dropdown menu entry are now clickable outside of the html link +* Improve error handling of plugins +* Use PHP7 function random_bytes() to generate tokens if available +* CSV task export show the assignee name in addition to the assignee username +* Add new hooks for plugins +* Remove workaround for "INSERT ON DUPLICATE KEY UPDATE..." + +Internal code refactoring: + +* Rewrite of session management +* Move some classes to a new namespace Kanboard\Core\Http + +Bug fixes: + +* Loading cs_CZ locale display the wrong language in datetime picker +* Datepicker is closed unexpectedly on blur event +* Fix bug in daily project summary CSV export +* Fix PHP error when adding a new user with email notification enabled +* Add missing template for activity stream to show event "file.create" +* Fix wrong value for PLUGINS_DIR in config.default.php +* Make CSV export compatible with PHP 5.3 +* Avoid Safari to append .html at the end of downloaded files + Version 1.0.20 -------------- Breaking changes: -- Add namespace Kanboard (update your plugins) -- Move Mailgun, Sendgrid, Postmark, Slack, Hipchat and Jabber to plugins -- ReverseProxy authentication check for each request that the username match the user session +* Add namespace Kanboard (update your plugins) +* Move Mailgun, Sendgrid, Postmark, Slack, Hipchat and Jabber to plugins +* ReverseProxy authentication check for each request that the username match the user session New features: diff --git a/sources/app/Action/Base.php b/sources/app/Action/Base.php index 4d2d6da..81e2ccc 100644 --- a/sources/app/Action/Base.php +++ b/sources/app/Action/Base.php @@ -241,7 +241,7 @@ abstract class Base extends \Kanboard\Core\Base } if (DEBUG) { - $this->container['logger']->debug(get_called_class().' => '.($result ? 'true' : 'false')); + $this->logger->debug(get_called_class().' => '.($result ? 'true' : 'false')); } return $result; diff --git a/sources/app/Action/TaskAssignCategoryLink.php b/sources/app/Action/TaskAssignCategoryLink.php new file mode 100644 index 0000000..3d00e8d --- /dev/null +++ b/sources/app/Action/TaskAssignCategoryLink.php @@ -0,0 +1,90 @@ + t('Category'), + 'link_id' => t('Link type'), + ); + } + + /** + * Get the required parameter for the event + * + * @access public + * @return string[] + */ + public function getEventRequiredParameters() + { + return array( + 'task_id', + 'link_id', + ); + } + + /** + * Execute the action (change the category) + * + * @access public + * @param array $data Event data dictionary + * @return bool True if the action was executed or false when not executed + */ + public function doAction(array $data) + { + $values = array( + 'id' => $data['task_id'], + 'category_id' => isset($data['category_id']) ? $data['category_id'] : $this->getParam('category_id'), + ); + + return $this->taskModification->update($values); + } + + /** + * Check if the event data meet the action condition + * + * @access public + * @param array $data Event data dictionary + * @return bool + */ + public function hasRequiredCondition(array $data) + { + if ($data['link_id'] == $this->getParam('link_id')) { + $task = $this->taskFinder->getById($data['task_id']); + return empty($task['category_id']); + } + + return false; + } +} diff --git a/sources/app/Api/Auth.php b/sources/app/Api/Auth.php index b3627e4..a084d6e 100644 --- a/sources/app/Api/Auth.php +++ b/sources/app/Api/Auth.php @@ -28,7 +28,7 @@ class Auth extends Base if ($username !== 'jsonrpc' && ! $this->authentication->hasCaptcha($username) && $this->authentication->authenticate($username, $password)) { $this->checkProcedurePermission(true, $method); - $this->userSession->refresh($this->user->getByUsername($username)); + $this->userSession->initialize($this->user->getByUsername($username)); } elseif ($username === 'jsonrpc' && $password === $this->config->get('api_token')) { $this->checkProcedurePermission(false, $method); } else { diff --git a/sources/app/Api/Me.php b/sources/app/Api/Me.php index 2c332a8..2c4161f 100644 --- a/sources/app/Api/Me.php +++ b/sources/app/Api/Me.php @@ -14,7 +14,7 @@ class Me extends Base { public function getMe() { - return $this->session['user']; + return $this->sessionStorage->user; } public function getMyDashboard() diff --git a/sources/app/Auth/Database.php b/sources/app/Auth/Database.php index 91b17a5..c2041d4 100644 --- a/sources/app/Auth/Database.php +++ b/sources/app/Auth/Database.php @@ -39,7 +39,7 @@ class Database extends Base ->findOne(); if (is_array($user) && password_verify($password, $user['password'])) { - $this->userSession->refresh($user); + $this->userSession->initialize($user); $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id'])); return true; } diff --git a/sources/app/Auth/Github.php b/sources/app/Auth/Github.php index b89dc5b..4777152 100644 --- a/sources/app/Auth/Github.php +++ b/sources/app/Auth/Github.php @@ -39,7 +39,7 @@ class Github extends Base $user = $this->user->getByGithubId($github_id); if (! empty($user)) { - $this->userSession->refresh($user); + $this->userSession->initialize($user); $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id'])); return true; } diff --git a/sources/app/Auth/Gitlab.php b/sources/app/Auth/Gitlab.php index a59bc1f..698b59c 100644 --- a/sources/app/Auth/Gitlab.php +++ b/sources/app/Auth/Gitlab.php @@ -39,7 +39,7 @@ class Gitlab extends Base $user = $this->user->getByGitlabId($gitlab_id); if (! empty($user)) { - $this->userSession->refresh($user); + $this->userSession->initialize($user); $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id'])); return true; } diff --git a/sources/app/Auth/Google.php b/sources/app/Auth/Google.php index 32bcb4b..6c1bc3c 100644 --- a/sources/app/Auth/Google.php +++ b/sources/app/Auth/Google.php @@ -40,7 +40,7 @@ class Google extends Base $user = $this->user->getByGoogleId($google_id); if (! empty($user)) { - $this->userSession->refresh($user); + $this->userSession->initialize($user); $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id'])); return true; } diff --git a/sources/app/Auth/Ldap.php b/sources/app/Auth/Ldap.php index c252be1..3d361aa 100644 --- a/sources/app/Auth/Ldap.php +++ b/sources/app/Auth/Ldap.php @@ -237,7 +237,7 @@ class Ldap extends Base } // We open the session - $this->userSession->refresh($user); + $this->userSession->initialize($user); $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id'])); return true; diff --git a/sources/app/Auth/RememberMe.php b/sources/app/Auth/RememberMe.php index 0290e36..0a567cb 100644 --- a/sources/app/Auth/RememberMe.php +++ b/sources/app/Auth/RememberMe.php @@ -3,9 +3,9 @@ namespace Kanboard\Auth; use Kanboard\Core\Base; -use Kanboard\Core\Request; +use Kanboard\Core\Http\Request; use Kanboard\Event\AuthEvent; -use Kanboard\Core\Security; +use Kanboard\Core\Security\Token; /** * RememberMe model @@ -101,10 +101,10 @@ class RememberMe extends Base ); // Create the session - $this->userSession->refresh($this->user->getById($record['user_id'])); + $this->userSession->initialize($this->user->getById($record['user_id'])); // Do not ask 2FA for remember me session - $this->session['2fa_validated'] = true; + $this->sessionStorage->postAuth['validated'] = true; $this->container['dispatcher']->dispatch( 'auth.success', @@ -165,8 +165,8 @@ class RememberMe extends Base */ public function create($user_id, $ip, $user_agent) { - $token = hash('sha256', $user_id.$user_agent.$ip.Security::generateToken()); - $sequence = Security::generateToken(); + $token = hash('sha256', $user_id.$user_agent.$ip.Token::getToken()); + $sequence = Token::getToken(); $expiration = time() + self::EXPIRATION; $this->cleanup($user_id); @@ -216,7 +216,7 @@ class RememberMe extends Base */ public function update($token) { - $new_sequence = Security::generateToken(); + $new_sequence = Token::getToken(); $this->db ->table(self::TABLE) diff --git a/sources/app/Auth/ReverseProxy.php b/sources/app/Auth/ReverseProxy.php index 1910ad3..d119ca9 100644 --- a/sources/app/Auth/ReverseProxy.php +++ b/sources/app/Auth/ReverseProxy.php @@ -48,7 +48,7 @@ class ReverseProxy extends Base $user = $this->user->getByUsername($login); } - $this->userSession->refresh($user); + $this->userSession->initialize($user); $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id'])); return true; diff --git a/sources/app/Controller/Action.php b/sources/app/Controller/Action.php index 37d1c24..ad13606 100644 --- a/sources/app/Controller/Action.php +++ b/sources/app/Controller/Action.php @@ -119,9 +119,9 @@ class Action extends Base if ($valid) { if ($this->action->create($values) !== false) { - $this->session->flash(t('Your automatic action have been created successfully.')); + $this->flash->success(t('Your automatic action have been created successfully.')); } else { - $this->session->flashError(t('Unable to create your automatic action.')); + $this->flash->failure(t('Unable to create your automatic action.')); } } @@ -158,9 +158,9 @@ class Action extends Base $action = $this->action->getById($this->request->getIntegerParam('action_id')); if (! empty($action) && $this->action->remove($action['id'])) { - $this->session->flash(t('Action removed successfully.')); + $this->flash->success(t('Action removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this action.')); + $this->flash->failure(t('Unable to remove this action.')); } $this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id']))); diff --git a/sources/app/Controller/Auth.php b/sources/app/Controller/Auth.php index 95ad8d9..b90e756 100644 --- a/sources/app/Controller/Auth.php +++ b/sources/app/Controller/Auth.php @@ -43,9 +43,11 @@ class Auth extends Base list($valid, $errors) = $this->authentication->validateForm($values); if ($valid) { - if (! empty($this->session['login_redirect']) && ! filter_var($this->session['login_redirect'], FILTER_VALIDATE_URL)) { - $redirect = $this->session['login_redirect']; - unset($this->session['login_redirect']); + if (isset($this->sessionStorage->redirectAfterLogin) + && ! empty($this->sessionStorage->redirectAfterLogin) + && ! filter_var($this->sessionStorage->redirectAfterLogin, FILTER_VALIDATE_URL)) { + $redirect = $this->sessionStorage->redirectAfterLogin; + unset($this->sessionStorage->redirectAfterLogin); $this->response->redirect($redirect); } @@ -63,7 +65,7 @@ class Auth extends Base public function logout() { $this->authentication->backend('rememberMe')->destroy($this->userSession->getId()); - $this->session->close(); + $this->sessionManager->close(); $this->response->redirect($this->helper->url->to('auth', 'login')); } @@ -78,7 +80,7 @@ class Auth extends Base $builder = new CaptchaBuilder; $builder->build(); - $this->session['captcha'] = $builder->getPhrase(); + $this->sessionStorage->captcha = $builder->getPhrase(); $builder->output(); } } diff --git a/sources/app/Controller/Base.php b/sources/app/Controller/Base.php index a955b12..8630f00 100644 --- a/sources/app/Controller/Base.php +++ b/sources/app/Controller/Base.php @@ -3,9 +3,6 @@ namespace Kanboard\Controller; use Pimple\Container; -use Kanboard\Core\Security; -use Kanboard\Core\Request; -use Kanboard\Core\Response; use Symfony\Component\EventDispatcher\Event; /** @@ -16,22 +13,6 @@ use Symfony\Component\EventDispatcher\Event; */ abstract class Base extends \Kanboard\Core\Base { - /** - * Request instance - * - * @accesss protected - * @var \Kanboard\Core\Request - */ - protected $request; - - /** - * Response instance - * - * @accesss protected - * @var \Kanboard\Core\Response - */ - protected $response; - /** * Constructor * @@ -41,11 +22,9 @@ abstract class Base extends \Kanboard\Core\Base public function __construct(Container $container) { $this->container = $container; - $this->request = new Request; - $this->response = new Response; if (DEBUG) { - $this->container['logger']->debug('START_REQUEST='.$_SERVER['REQUEST_URI']); + $this->logger->debug('START_REQUEST='.$_SERVER['REQUEST_URI']); } } @@ -57,14 +36,14 @@ abstract class Base extends \Kanboard\Core\Base public function __destruct() { if (DEBUG) { - foreach ($this->container['db']->getLogMessages() as $message) { - $this->container['logger']->debug($message); + foreach ($this->db->getLogMessages() as $message) { + $this->logger->debug($message); } - $this->container['logger']->debug('SQL_QUERIES={nb}', array('nb' => $this->container['db']->nbQueries)); - $this->container['logger']->debug('RENDERING={time}', array('time' => microtime(true) - @$_SERVER['REQUEST_TIME_FLOAT'])); - $this->container['logger']->debug('MEMORY='.$this->helper->text->bytes(memory_get_usage())); - $this->container['logger']->debug('END_REQUEST='.$_SERVER['REQUEST_URI']); + $this->logger->debug('SQL_QUERIES={nb}', array('nb' => $this->container['db']->nbQueries)); + $this->logger->debug('RENDERING={time}', array('time' => microtime(true) - @$_SERVER['REQUEST_TIME_FLOAT'])); + $this->logger->debug('MEMORY='.$this->helper->text->bytes(memory_get_usage())); + $this->logger->debug('END_REQUEST='.$_SERVER['REQUEST_URI']); } } @@ -97,8 +76,7 @@ abstract class Base extends \Kanboard\Core\Base */ public function beforeAction($controller, $action) { - // Start the session - $this->session->open($this->helper->url->dir()); + $this->sessionManager->open(); $this->sendHeaders($action); $this->container['dispatcher']->dispatch('session.bootstrap', new Event); @@ -107,7 +85,7 @@ abstract class Base extends \Kanboard\Core\Base $this->handle2FA($controller, $action); $this->handleAuthorization($controller, $action); - $this->session['has_subtask_inprogress'] = $this->subtask->hasSubtaskInProgress($this->userSession->getId()); + $this->sessionStorage->hasSubtaskInProgress = $this->subtask->hasSubtaskInProgress($this->userSession->getId()); } } @@ -123,7 +101,7 @@ abstract class Base extends \Kanboard\Core\Base $this->response->text('Not Authorized', 401); } - $this->session['login_redirect'] = $this->request->getUri(); + $this->sessionStorage->redirectAfterLogin = $this->request->getUri(); $this->response->redirect($this->helper->url->to('auth', 'login')); } } @@ -201,7 +179,7 @@ abstract class Base extends \Kanboard\Core\Base */ protected function checkCSRFParam() { - if (! Security::validateCSRFToken($this->request->getStringParam('csrf_token'))) { + if (! $this->token->validateCSRFToken($this->request->getStringParam('csrf_token'))) { $this->forbidden(); } } @@ -290,7 +268,7 @@ abstract class Base extends \Kanboard\Core\Base $project = $this->project->getById($project_id); if (empty($project)) { - $this->session->flashError(t('Project not found.')); + $this->flash->failure(t('Project not found.')); $this->response->redirect($this->helper->url->to('project', 'index')); } diff --git a/sources/app/Controller/Board.php b/sources/app/Controller/Board.php index 2d75db8..7442ff2 100644 --- a/sources/app/Controller/Board.php +++ b/sources/app/Controller/Board.php @@ -242,9 +242,9 @@ class Board extends Base list($valid, ) = $this->taskValidator->validateAssigneeModification($values); if ($valid && $this->taskModification->update($values)) { - $this->session->flash(t('Task updated successfully.')); + $this->flash->success(t('Task updated successfully.')); } else { - $this->session->flashError(t('Unable to update your task.')); + $this->flash->failure(t('Unable to update your task.')); } $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $values['project_id']))); @@ -279,9 +279,9 @@ class Board extends Base list($valid, ) = $this->taskValidator->validateCategoryModification($values); if ($valid && $this->taskModification->update($values)) { - $this->session->flash(t('Task updated successfully.')); + $this->flash->success(t('Task updated successfully.')); } else { - $this->session->flashError(t('Unable to update your task.')); + $this->flash->failure(t('Unable to update your task.')); } $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $values['project_id']))); diff --git a/sources/app/Controller/Category.php b/sources/app/Controller/Category.php index 4aefd9f..9864348 100644 --- a/sources/app/Controller/Category.php +++ b/sources/app/Controller/Category.php @@ -22,7 +22,7 @@ class Category extends Base $category = $this->category->getById($this->request->getIntegerParam('category_id')); if (empty($category)) { - $this->session->flashError(t('Category not found.')); + $this->flash->failure(t('Category not found.')); $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project_id))); } @@ -61,10 +61,10 @@ class Category extends Base if ($valid) { if ($this->category->create($values)) { - $this->session->flash(t('Your category have been created successfully.')); + $this->flash->success(t('Your category have been created successfully.')); $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id']))); } else { - $this->session->flashError(t('Unable to create your category.')); + $this->flash->failure(t('Unable to create your category.')); } } @@ -103,10 +103,10 @@ class Category extends Base if ($valid) { if ($this->category->update($values)) { - $this->session->flash(t('Your category have been updated successfully.')); + $this->flash->success(t('Your category have been updated successfully.')); $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id']))); } else { - $this->session->flashError(t('Unable to update your category.')); + $this->flash->failure(t('Unable to update your category.')); } } @@ -142,9 +142,9 @@ class Category extends Base $category = $this->getCategory($project['id']); if ($this->category->remove($category['id'])) { - $this->session->flash(t('Category removed successfully.')); + $this->flash->success(t('Category removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this category.')); + $this->flash->failure(t('Unable to remove this category.')); } $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id']))); diff --git a/sources/app/Controller/Column.php b/sources/app/Controller/Column.php index d28fb29..b484fe1 100644 --- a/sources/app/Controller/Column.php +++ b/sources/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']))); diff --git a/sources/app/Controller/Comment.php b/sources/app/Controller/Comment.php index d6cbbf1..54339e4 100644 --- a/sources/app/Controller/Comment.php +++ b/sources/app/Controller/Comment.php @@ -82,9 +82,9 @@ class Comment extends Base if ($valid) { if ($this->comment->create($values)) { - $this->session->flash(t('Comment added successfully.')); + $this->flash->success(t('Comment added successfully.')); } else { - $this->session->flashError(t('Unable to create your comment.')); + $this->flash->failure(t('Unable to create your comment.')); } if ($ajax) { @@ -131,9 +131,9 @@ class Comment extends Base if ($valid) { if ($this->comment->update($values)) { - $this->session->flash(t('Comment updated successfully.')); + $this->flash->success(t('Comment updated successfully.')); } else { - $this->session->flashError(t('Unable to update your comment.')); + $this->flash->failure(t('Unable to update your comment.')); } $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comment-'.$comment['id'])); @@ -171,9 +171,9 @@ class Comment extends Base $comment = $this->getComment(); if ($this->comment->remove($comment['id'])) { - $this->session->flash(t('Comment removed successfully.')); + $this->flash->success(t('Comment removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this comment.')); + $this->flash->failure(t('Unable to remove this comment.')); } $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments')); diff --git a/sources/app/Controller/Config.php b/sources/app/Controller/Config.php index 47b844e..4980614 100644 --- a/sources/app/Controller/Config.php +++ b/sources/app/Controller/Config.php @@ -53,9 +53,9 @@ class Config extends Base if ($this->config->save($values)) { $this->config->reload(); - $this->session->flash(t('Settings saved successfully.')); + $this->flash->success(t('Settings saved successfully.')); } else { - $this->session->flashError(t('Unable to save your settings.')); + $this->flash->failure(t('Unable to save your settings.')); } $this->response->redirect($this->helper->url->to('config', $redirect)); @@ -210,7 +210,7 @@ class Config extends Base { $this->checkCSRFParam(); $this->config->optimizeDatabase(); - $this->session->flash(t('Database optimization done.')); + $this->flash->success(t('Database optimization done.')); $this->response->redirect($this->helper->url->to('config', 'index')); } @@ -226,7 +226,7 @@ class Config extends Base $this->checkCSRFParam(); $this->config->regenerateToken($type.'_token'); - $this->session->flash(t('Token regenerated.')); + $this->flash->success(t('Token regenerated.')); $this->response->redirect($this->helper->url->to('config', $type)); } } diff --git a/sources/app/Controller/Currency.php b/sources/app/Controller/Currency.php index 9d6b024..118b2c4 100644 --- a/sources/app/Controller/Currency.php +++ b/sources/app/Controller/Currency.php @@ -55,10 +55,10 @@ class Currency extends Base if ($valid) { if ($this->currency->create($values['currency'], $values['rate'])) { - $this->session->flash(t('The currency rate have been added successfully.')); + $this->flash->success(t('The currency rate have been added successfully.')); $this->response->redirect($this->helper->url->to('currency', 'index')); } else { - $this->session->flashError(t('Unable to add this currency rate.')); + $this->flash->failure(t('Unable to add this currency rate.')); } } @@ -76,9 +76,9 @@ class Currency extends Base if ($this->config->save($values)) { $this->config->reload(); - $this->session->flash(t('Settings saved successfully.')); + $this->flash->success(t('Settings saved successfully.')); } else { - $this->session->flashError(t('Unable to save your settings.')); + $this->flash->failure(t('Unable to save your settings.')); } $this->response->redirect($this->helper->url->to('currency', 'index')); diff --git a/sources/app/Controller/Customfilter.php b/sources/app/Controller/Customfilter.php index a152c66..d686310 100644 --- a/sources/app/Controller/Customfilter.php +++ b/sources/app/Controller/Customfilter.php @@ -44,10 +44,10 @@ class Customfilter extends Base if ($valid) { if ($this->customFilter->create($values)) { - $this->session->flash(t('Your custom filter have been created successfully.')); + $this->flash->success(t('Your custom filter have been created successfully.')); $this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id']))); } else { - $this->session->flashError(t('Unable to create your custom filter.')); + $this->flash->failure(t('Unable to create your custom filter.')); } } @@ -68,9 +68,9 @@ class Customfilter extends Base $this->checkPermission($project, $filter); if ($this->customFilter->remove($filter['id'])) { - $this->session->flash(t('Custom filter removed successfully.')); + $this->flash->success(t('Custom filter removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this custom filter.')); + $this->flash->failure(t('Unable to remove this custom filter.')); } $this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id']))); @@ -123,10 +123,10 @@ class Customfilter extends Base if ($valid) { if ($this->customFilter->update($values)) { - $this->session->flash(t('Your custom filter have been updated successfully.')); + $this->flash->success(t('Your custom filter have been updated successfully.')); $this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id']))); } else { - $this->session->flashError(t('Unable to update custom filter.')); + $this->flash->failure(t('Unable to update custom filter.')); } } diff --git a/sources/app/Controller/Export.php b/sources/app/Controller/Export.php index cdedcb8..c39f58a 100644 --- a/sources/app/Controller/Export.php +++ b/sources/app/Controller/Export.php @@ -70,7 +70,7 @@ class Export extends Base */ public function summary() { - $this->common('ProjectDailyColumnStats', 'getAggregatedMetrics', t('Summary'), 'summary', t('Daily project summary export')); + $this->common('projectDailyColumnStats', 'getAggregatedMetrics', t('Summary'), 'summary', t('Daily project summary export')); } /** diff --git a/sources/app/Controller/File.php b/sources/app/Controller/File.php index 4d771e2..b46f7d1 100644 --- a/sources/app/Controller/File.php +++ b/sources/app/Controller/File.php @@ -22,7 +22,7 @@ class File extends Base $task = $this->getTask(); if ($this->request->isPost() && $this->file->uploadScreenshot($task['project_id'], $task['id'], $this->request->getValue('screenshot')) !== false) { - $this->session->flash(t('Screenshot uploaded successfully.')); + $this->flash->success(t('Screenshot uploaded successfully.')); if ($this->request->getStringParam('redirect') === 'board') { $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id']))); @@ -62,7 +62,7 @@ class File extends Base $task = $this->getTask(); if (! $this->file->uploadFiles($task['project_id'], $task['id'], 'files')) { - $this->session->flashError(t('Unable to upload the file.')); + $this->flash->failure(t('Unable to upload the file.')); } $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))); @@ -166,9 +166,9 @@ class File extends Base $file = $this->file->getById($this->request->getIntegerParam('file_id')); if ($file['task_id'] == $task['id'] && $this->file->remove($file['id'])) { - $this->session->flash(t('File removed successfully.')); + $this->flash->success(t('File removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this file.')); + $this->flash->failure(t('Unable to remove this file.')); } $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))); diff --git a/sources/app/Controller/Gantt.php b/sources/app/Controller/Gantt.php index 24d94f0..bd3d92f 100644 --- a/sources/app/Controller/Gantt.php +++ b/sources/app/Controller/Gantt.php @@ -135,10 +135,10 @@ class Gantt extends Base $task_id = $this->taskCreation->create($values); if ($task_id !== false) { - $this->session->flash(t('Task created successfully.')); + $this->flash->success(t('Task created successfully.')); $this->response->redirect($this->helper->url->to('gantt', 'project', array('project_id' => $project['id']))); } else { - $this->session->flashError(t('Unable to create your task.')); + $this->flash->failure(t('Unable to create your task.')); } } diff --git a/sources/app/Controller/Link.php b/sources/app/Controller/Link.php index 0eb3d67..c7f1823 100644 --- a/sources/app/Controller/Link.php +++ b/sources/app/Controller/Link.php @@ -71,10 +71,10 @@ class Link extends Base if ($valid) { if ($this->link->create($values['label'], $values['opposite_label']) !== false) { - $this->session->flash(t('Link added successfully.')); + $this->flash->success(t('Link added successfully.')); $this->response->redirect($this->helper->url->to('link', 'index')); } else { - $this->session->flashError(t('Unable to create your link.')); + $this->flash->failure(t('Unable to create your link.')); } } @@ -112,10 +112,10 @@ class Link extends Base if ($valid) { if ($this->link->update($values)) { - $this->session->flash(t('Link updated successfully.')); + $this->flash->success(t('Link updated successfully.')); $this->response->redirect($this->helper->url->to('link', 'index')); } else { - $this->session->flashError(t('Unable to update your link.')); + $this->flash->failure(t('Unable to update your link.')); } } @@ -148,9 +148,9 @@ class Link extends Base $link = $this->getLink(); if ($this->link->remove($link['id'])) { - $this->session->flash(t('Link removed successfully.')); + $this->flash->success(t('Link removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this link.')); + $this->flash->failure(t('Unable to remove this link.')); } $this->response->redirect($this->helper->url->to('link', 'index')); diff --git a/sources/app/Controller/Oauth.php b/sources/app/Controller/Oauth.php index 8c701cf..3954614 100644 --- a/sources/app/Controller/Oauth.php +++ b/sources/app/Controller/Oauth.php @@ -51,9 +51,9 @@ class Oauth extends Base $this->checkCSRFParam(); if ($this->authentication->backend($backend)->unlink($this->userSession->getId())) { - $this->session->flash(t('Your external account is not linked anymore to your profile.')); + $this->flash->success(t('Your external account is not linked anymore to your profile.')); } else { - $this->session->flashError(t('Unable to unlink your external account.')); + $this->flash->failure(t('Unable to unlink your external account.')); } $this->response->redirect($this->helper->url->to('user', 'external', array('user_id' => $this->userSession->getId()))); @@ -99,9 +99,9 @@ class Oauth extends Base private function link($backend, $profile) { if (empty($profile)) { - $this->session->flashError(t('External authentication failed')); + $this->flash->failure(t('External authentication failed')); } else { - $this->session->flash(t('Your external account is linked to your profile successfully.')); + $this->flash->success(t('Your external account is linked to your profile successfully.')); $this->authentication->backend($backend)->updateUser($this->userSession->getId(), $profile); } diff --git a/sources/app/Controller/Project.php b/sources/app/Controller/Project.php index f30d70e..2d9c25d 100644 --- a/sources/app/Controller/Project.php +++ b/sources/app/Controller/Project.php @@ -70,9 +70,9 @@ class Project extends Base $this->checkCSRFParam(); if ($this->project->{$switch.'PublicAccess'}($project['id'])) { - $this->session->flash(t('Project updated successfully.')); + $this->flash->success(t('Project updated successfully.')); } else { - $this->session->flashError(t('Unable to update this project.')); + $this->flash->failure(t('Unable to update this project.')); } $this->response->redirect($this->helper->url->to('project', 'share', array('project_id' => $project['id']))); @@ -95,7 +95,7 @@ class Project extends Base if ($this->request->isPost()) { $this->projectMetadata->save($project['id'], $this->request->getValues()); - $this->session->flash(t('Project updated successfully.')); + $this->flash->success(t('Project updated successfully.')); $this->response->redirect($this->helper->url->to('project', 'integrations', array('project_id' => $project['id']))); } @@ -120,7 +120,7 @@ class Project extends Base if ($this->request->isPost()) { $values = $this->request->getValues(); $this->projectNotification->saveSettings($project['id'], $values); - $this->session->flash(t('Project updated successfully.')); + $this->flash->success(t('Project updated successfully.')); $this->response->redirect($this->helper->url->to('project', 'notifications', array('project_id' => $project['id']))); } @@ -173,10 +173,10 @@ class Project extends Base if ($valid) { if ($this->project->update($values)) { - $this->session->flash(t('Project updated successfully.')); + $this->flash->success(t('Project updated successfully.')); $this->response->redirect($this->helper->url->to('project', 'edit', array('project_id' => $project['id']))); } else { - $this->session->flashError(t('Unable to update this project.')); + $this->flash->failure(t('Unable to update this project.')); } } @@ -212,9 +212,9 @@ class Project extends Base if ($valid) { if ($this->project->update($values)) { - $this->session->flash(t('Project updated successfully.')); + $this->flash->success(t('Project updated successfully.')); } else { - $this->session->flashError(t('Unable to update this project.')); + $this->flash->failure(t('Unable to update this project.')); } } @@ -233,9 +233,9 @@ class Project extends Base if ($valid) { if ($this->projectPermission->addMember($values['project_id'], $values['user_id'])) { - $this->session->flash(t('Project updated successfully.')); + $this->flash->success(t('Project updated successfully.')); } else { - $this->session->flashError(t('Unable to update this project.')); + $this->flash->failure(t('Unable to update this project.')); } } @@ -261,9 +261,9 @@ class Project extends Base if ($valid) { if ($this->projectPermission->changeRole($values['project_id'], $values['user_id'], $values['is_owner'])) { - $this->session->flash(t('Project updated successfully.')); + $this->flash->success(t('Project updated successfully.')); } else { - $this->session->flashError(t('Unable to update this project.')); + $this->flash->failure(t('Unable to update this project.')); } } @@ -288,9 +288,9 @@ class Project extends Base if ($valid) { if ($this->projectPermission->revokeMember($values['project_id'], $values['user_id'])) { - $this->session->flash(t('Project updated successfully.')); + $this->flash->success(t('Project updated successfully.')); } else { - $this->session->flashError(t('Unable to update this project.')); + $this->flash->failure(t('Unable to update this project.')); } } @@ -310,9 +310,9 @@ class Project extends Base $this->checkCSRFParam(); if ($this->project->remove($project['id'])) { - $this->session->flash(t('Project removed successfully.')); + $this->flash->success(t('Project removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this project.')); + $this->flash->failure(t('Unable to remove this project.')); } $this->response->redirect($this->helper->url->to('project', 'index')); @@ -338,9 +338,9 @@ class Project extends Base if ($this->request->getStringParam('duplicate') === 'yes') { $values = array_keys($this->request->getValues()); if ($this->projectDuplication->duplicate($project['id'], $values) !== false) { - $this->session->flash(t('Project cloned successfully.')); + $this->flash->success(t('Project cloned successfully.')); } else { - $this->session->flashError(t('Unable to clone this project.')); + $this->flash->failure(t('Unable to clone this project.')); } $this->response->redirect($this->helper->url->to('project', 'index')); @@ -365,9 +365,9 @@ class Project extends Base $this->checkCSRFParam(); if ($this->project->disable($project['id'])) { - $this->session->flash(t('Project disabled successfully.')); + $this->flash->success(t('Project disabled successfully.')); } else { - $this->session->flashError(t('Unable to disable this project.')); + $this->flash->failure(t('Unable to disable this project.')); } $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id']))); @@ -392,9 +392,9 @@ class Project extends Base $this->checkCSRFParam(); if ($this->project->enable($project['id'])) { - $this->session->flash(t('Project activated successfully.')); + $this->flash->success(t('Project activated successfully.')); } else { - $this->session->flashError(t('Unable to activate this project.')); + $this->flash->failure(t('Unable to activate this project.')); } $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id']))); @@ -438,11 +438,11 @@ class Project extends Base $project_id = $this->project->create($values, $this->userSession->getId(), true); if ($project_id > 0) { - $this->session->flash(t('Your project have been created successfully.')); + $this->flash->success(t('Your project have been created successfully.')); $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id))); } - $this->session->flashError(t('Unable to create your project.')); + $this->flash->failure(t('Unable to create your project.')); } $this->create($values, $errors); diff --git a/sources/app/Controller/Subtask.php b/sources/app/Controller/Subtask.php index 4ef3e74..30ddc37 100644 --- a/sources/app/Controller/Subtask.php +++ b/sources/app/Controller/Subtask.php @@ -67,9 +67,9 @@ class Subtask extends Base if ($valid) { if ($this->subtask->create($values)) { - $this->session->flash(t('Sub-task added successfully.')); + $this->flash->success(t('Sub-task added successfully.')); } else { - $this->session->flashError(t('Unable to create your sub-task.')); + $this->flash->failure(t('Unable to create your sub-task.')); } if (isset($values['another_subtask']) && $values['another_subtask'] == 1) { @@ -117,9 +117,9 @@ class Subtask extends Base if ($valid) { if ($this->subtask->update($values)) { - $this->session->flash(t('Sub-task updated successfully.')); + $this->flash->success(t('Sub-task updated successfully.')); } else { - $this->session->flashError(t('Unable to update your sub-task.')); + $this->flash->failure(t('Unable to update your sub-task.')); } $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks')); @@ -156,9 +156,9 @@ class Subtask extends Base $subtask = $this->getSubtask(); if ($this->subtask->remove($subtask['id'])) { - $this->session->flash(t('Sub-task removed successfully.')); + $this->flash->success(t('Sub-task removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this sub-task.')); + $this->flash->failure(t('Unable to remove this sub-task.')); } $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks')); @@ -178,7 +178,7 @@ class Subtask extends Base $this->subtask->toggleStatus($subtask['id']); if ($redirect === 'board') { - $this->session['has_subtask_inprogress'] = $this->subtask->hasSubtaskInProgress($this->userSession->getId()); + $this->sessionStorage->hasSubtaskInProgress = $this->subtask->hasSubtaskInProgress($this->userSession->getId()); $this->response->html($this->template->render('board/tooltip_subtasks', array( 'subtasks' => $this->subtask->getAll($task['id']), diff --git a/sources/app/Controller/Swimlane.php b/sources/app/Controller/Swimlane.php index 0b29f59..5229621 100644 --- a/sources/app/Controller/Swimlane.php +++ b/sources/app/Controller/Swimlane.php @@ -24,7 +24,7 @@ class Swimlane extends Base $swimlane = $this->swimlane->getById($this->request->getIntegerParam('swimlane_id')); if (empty($swimlane)) { - $this->session->flashError(t('Swimlane not found.')); + $this->flash->failure(t('Swimlane not found.')); $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project_id))); } @@ -64,10 +64,10 @@ class Swimlane extends Base if ($valid) { if ($this->swimlane->create($values)) { - $this->session->flash(t('Your swimlane have been created successfully.')); + $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->session->flashError(t('Unable to create your swimlane.')); + $this->flash->failure(t('Unable to create your swimlane.')); } } @@ -88,10 +88,10 @@ class Swimlane extends Base if ($valid) { if ($this->swimlane->updateDefault($values)) { - $this->session->flash(t('The default swimlane have been updated successfully.')); + $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']))); } else { - $this->session->flashError(t('Unable to update this swimlane.')); + $this->flash->failure(t('Unable to update this swimlane.')); } } @@ -130,10 +130,10 @@ class Swimlane extends Base if ($valid) { if ($this->swimlane->update($values)) { - $this->session->flash(t('Swimlane updated successfully.')); + $this->flash->success(t('Swimlane updated successfully.')); $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } else { - $this->session->flashError(t('Unable to update this swimlane.')); + $this->flash->failure(t('Unable to update this swimlane.')); } } @@ -169,9 +169,9 @@ class Swimlane extends Base $swimlane_id = $this->request->getIntegerParam('swimlane_id'); if ($this->swimlane->remove($project['id'], $swimlane_id)) { - $this->session->flash(t('Swimlane removed successfully.')); + $this->flash->success(t('Swimlane removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this swimlane.')); + $this->flash->failure(t('Unable to remove this swimlane.')); } $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); @@ -189,9 +189,9 @@ class Swimlane extends Base $swimlane_id = $this->request->getIntegerParam('swimlane_id'); if ($this->swimlane->disable($project['id'], $swimlane_id)) { - $this->session->flash(t('Swimlane updated successfully.')); + $this->flash->success(t('Swimlane updated successfully.')); } else { - $this->session->flashError(t('Unable to update this swimlane.')); + $this->flash->failure(t('Unable to update this swimlane.')); } $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); @@ -209,9 +209,9 @@ class Swimlane extends Base $swimlane_id = $this->request->getIntegerParam('swimlane_id'); if ($this->swimlane->enable($project['id'], $swimlane_id)) { - $this->session->flash(t('Swimlane updated successfully.')); + $this->flash->success(t('Swimlane updated successfully.')); } else { - $this->session->flashError(t('Unable to update this swimlane.')); + $this->flash->failure(t('Unable to update this swimlane.')); } $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); diff --git a/sources/app/Controller/Task.php b/sources/app/Controller/Task.php index 894802d..e71b201 100644 --- a/sources/app/Controller/Task.php +++ b/sources/app/Controller/Task.php @@ -159,9 +159,9 @@ class Task extends Base $this->checkCSRFParam(); if ($this->task->remove($task['id'])) { - $this->session->flash(t('Task removed successfully.')); + $this->flash->success(t('Task removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this task.')); + $this->flash->failure(t('Unable to remove this task.')); } $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id']))); diff --git a/sources/app/Controller/TaskImport.php b/sources/app/Controller/TaskImport.php index 0e9d216..f09c14c 100644 --- a/sources/app/Controller/TaskImport.php +++ b/sources/app/Controller/TaskImport.php @@ -52,9 +52,9 @@ class TaskImport extends Base $csv->read($filename, array($this->taskImport, 'import')); if ($this->taskImport->counter > 0) { - $this->session->flash(t('%d task(s) have been imported successfully.', $this->taskImport->counter)); + $this->flash->success(t('%d task(s) have been imported successfully.', $this->taskImport->counter)); } else { - $this->session->flashError(t('Nothing have been imported!')); + $this->flash->failure(t('Nothing have been imported!')); } $this->response->redirect($this->helper->url->to('taskImport', 'step1', array('project_id' => $project['id']))); diff --git a/sources/app/Controller/Taskcreation.php b/sources/app/Controller/Taskcreation.php index e47cd1b..cffa9d7 100644 --- a/sources/app/Controller/Taskcreation.php +++ b/sources/app/Controller/Taskcreation.php @@ -59,10 +59,10 @@ class Taskcreation extends Base list($valid, $errors) = $this->taskValidator->validateCreation($values); if ($valid && $this->taskCreation->create($values)) { - $this->session->flash(t('Task created successfully.')); + $this->flash->success(t('Task created successfully.')); $this->afterSave($project, $values); } else { - $this->session->flashError(t('Unable to create your task.')); + $this->flash->failure(t('Unable to create your task.')); } $this->create($values, $errors); diff --git a/sources/app/Controller/Taskduplication.php b/sources/app/Controller/Taskduplication.php index 79f498f..9cd684e 100644 --- a/sources/app/Controller/Taskduplication.php +++ b/sources/app/Controller/Taskduplication.php @@ -24,10 +24,10 @@ class Taskduplication extends Base $task_id = $this->taskDuplication->duplicate($task['id']); if ($task_id > 0) { - $this->session->flash(t('Task created successfully.')); + $this->flash->success(t('Task created successfully.')); $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task_id))); } else { - $this->session->flashError(t('Unable to create this task.')); + $this->flash->failure(t('Unable to create this task.')); $this->response->redirect($this->helper->url->to('taskduplication', 'duplicate', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } } @@ -56,11 +56,11 @@ class Taskduplication extends Base $values['column_id'], $values['category_id'], $values['owner_id'])) { - $this->session->flash(t('Task updated successfully.')); + $this->flash->success(t('Task updated successfully.')); $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task['id']))); } - $this->session->flashError(t('Unable to update your task.')); + $this->flash->failure(t('Unable to update your task.')); } $this->chooseDestination($task, 'task_duplication/move'); @@ -86,12 +86,12 @@ class Taskduplication extends Base ); if ($task_id > 0) { - $this->session->flash(t('Task created successfully.')); + $this->flash->success(t('Task created successfully.')); $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task_id))); } } - $this->session->flashError(t('Unable to create your task.')); + $this->flash->failure(t('Unable to create your task.')); } $this->chooseDestination($task, 'task_duplication/copy'); diff --git a/sources/app/Controller/Tasklink.php b/sources/app/Controller/Tasklink.php index 587769e..068bf16 100644 --- a/sources/app/Controller/Tasklink.php +++ b/sources/app/Controller/Tasklink.php @@ -73,7 +73,7 @@ class Tasklink extends Base if ($valid) { if ($this->taskLink->create($values['task_id'], $values['opposite_task_id'], $values['link_id'])) { - $this->session->flash(t('Link added successfully.')); + $this->flash->success(t('Link added successfully.')); if ($ajax) { $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id']))); @@ -83,7 +83,7 @@ class Tasklink extends Base } $errors = array('title' => array(t('The exact same link already exists'))); - $this->session->flashError(t('Unable to create your link.')); + $this->flash->failure(t('Unable to create your link.')); } $this->create($values, $errors); @@ -129,11 +129,11 @@ class Tasklink extends Base if ($valid) { if ($this->taskLink->update($values['id'], $values['task_id'], $values['opposite_task_id'], $values['link_id'])) { - $this->session->flash(t('Link updated successfully.')); + $this->flash->success(t('Link updated successfully.')); $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links'); } - $this->session->flashError(t('Unable to update your link.')); + $this->flash->failure(t('Unable to update your link.')); } $this->edit($values, $errors); @@ -166,9 +166,9 @@ class Tasklink extends Base $task = $this->getTask(); if ($this->taskLink->remove($this->request->getIntegerParam('link_id'))) { - $this->session->flash(t('Link removed successfully.')); + $this->flash->success(t('Link removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this link.')); + $this->flash->failure(t('Unable to remove this link.')); } $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links'); diff --git a/sources/app/Controller/Taskmodification.php b/sources/app/Controller/Taskmodification.php index b1105dc..02b09a3 100644 --- a/sources/app/Controller/Taskmodification.php +++ b/sources/app/Controller/Taskmodification.php @@ -35,9 +35,9 @@ class Taskmodification extends Base list($valid, ) = $this->taskValidator->validateTimeModification($values); if ($valid && $this->taskModification->update($values)) { - $this->session->flash(t('Task updated successfully.')); + $this->flash->success(t('Task updated successfully.')); } else { - $this->session->flashError(t('Unable to update your task.')); + $this->flash->failure(t('Unable to update your task.')); } $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); @@ -60,9 +60,9 @@ class Taskmodification extends Base if ($valid) { if ($this->taskModification->update($values)) { - $this->session->flash(t('Task updated successfully.')); + $this->flash->success(t('Task updated successfully.')); } else { - $this->session->flashError(t('Unable to update your task.')); + $this->flash->failure(t('Unable to update your task.')); } if ($ajax) { @@ -140,7 +140,7 @@ class Taskmodification extends Base list($valid, $errors) = $this->taskValidator->validateModification($values); if ($valid && $this->taskModification->update($values)) { - $this->session->flash(t('Task updated successfully.')); + $this->flash->success(t('Task updated successfully.')); if ($this->request->isAjax()) { $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id']))); @@ -148,7 +148,7 @@ class Taskmodification extends Base $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); } } else { - $this->session->flashError(t('Unable to update your task.')); + $this->flash->failure(t('Unable to update your task.')); $this->edit($values, $errors); } } @@ -169,9 +169,9 @@ class Taskmodification extends Base if ($valid) { if ($this->taskModification->update($values)) { - $this->session->flash(t('Task updated successfully.')); + $this->flash->success(t('Task updated successfully.')); } else { - $this->session->flashError(t('Unable to update your task.')); + $this->flash->failure(t('Unable to update your task.')); } $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']))); diff --git a/sources/app/Controller/Taskstatus.php b/sources/app/Controller/Taskstatus.php index c0421ea..b03baeb 100644 --- a/sources/app/Controller/Taskstatus.php +++ b/sources/app/Controller/Taskstatus.php @@ -40,9 +40,9 @@ class Taskstatus extends Base $this->checkCSRFParam(); if ($this->taskStatus->$method($task['id'])) { - $this->session->flash($success_message); + $this->flash->success($success_message); } else { - $this->session->flashError($failure_message); + $this->flash->failure($failure_message); } if ($this->request->getStringParam('redirect') === 'board') { diff --git a/sources/app/Controller/Twofactor.php b/sources/app/Controller/Twofactor.php index 179241f..a7368d6 100644 --- a/sources/app/Controller/Twofactor.php +++ b/sources/app/Controller/Twofactor.php @@ -72,9 +72,9 @@ class Twofactor extends User } // Allow the user to test or disable the feature - $_SESSION['user']['twofactor_activated'] = false; + $this->userSession->disable2FA(); - $this->session->flash(t('User updated successfully.')); + $this->flash->success(t('User updated successfully.')); $this->response->redirect($this->helper->url->to('twofactor', 'index', array('user_id' => $user['id']))); } @@ -92,9 +92,9 @@ class Twofactor extends User $values = $this->request->getValues(); if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) { - $this->session->flash(t('The two factor authentication code is valid.')); + $this->flash->success(t('The two factor authentication code is valid.')); } else { - $this->session->flashError(t('The two factor authentication code is not valid.')); + $this->flash->failure(t('The two factor authentication code is not valid.')); } $this->response->redirect($this->helper->url->to('twofactor', 'index', array('user_id' => $user['id']))); @@ -114,11 +114,11 @@ class Twofactor extends User $values = $this->request->getValues(); if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) { - $this->session['2fa_validated'] = true; - $this->session->flash(t('The two factor authentication code is valid.')); + $this->sessionStorage->postAuth['validated'] = true; + $this->flash->success(t('The two factor authentication code is valid.')); $this->response->redirect($this->helper->url->to('app', 'index')); } else { - $this->session->flashError(t('The two factor authentication code is not valid.')); + $this->flash->failure(t('The two factor authentication code is not valid.')); $this->response->redirect($this->helper->url->to('twofactor', 'code')); } } diff --git a/sources/app/Controller/User.php b/sources/app/Controller/User.php index b5f4ede..23e1982 100644 --- a/sources/app/Controller/User.php +++ b/sources/app/Controller/User.php @@ -2,7 +2,7 @@ namespace Kanboard\Controller; -use Kanboard\Model\NotificationType; +use Kanboard\Notification\Mail as MailNotification; /** * User controller @@ -95,13 +95,13 @@ class User extends Base $this->projectPermission->addMember($project_id, $user_id); if (! empty($values['notifications_enabled'])) { - $this->userNotificationType->saveSelectedTypes($user_id, array(NotificationType::TYPE_EMAIL)); + $this->userNotificationType->saveSelectedTypes($user_id, array(MailNotification::TYPE)); } - $this->session->flash(t('User created successfully.')); + $this->flash->success(t('User created successfully.')); $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user_id))); } else { - $this->session->flashError(t('Unable to create your user.')); + $this->flash->failure(t('Unable to create your user.')); $values['project_id'] = $project_id; } } @@ -200,7 +200,7 @@ class User extends Base if ($this->request->isPost()) { $values = $this->request->getValues(); $this->userNotification->saveSettings($user['id'], $values); - $this->session->flash(t('User updated successfully.')); + $this->flash->success(t('User updated successfully.')); $this->response->redirect($this->helper->url->to('user', 'notifications', array('user_id' => $user['id']))); } @@ -225,7 +225,7 @@ class User extends Base if ($this->request->isPost()) { $values = $this->request->getValues(); $this->userMetadata->save($user['id'], $values); - $this->session->flash(t('User updated successfully.')); + $this->flash->success(t('User updated successfully.')); $this->response->redirect($this->helper->url->to('user', 'integrations', array('user_id' => $user['id']))); } @@ -263,9 +263,9 @@ class User extends Base $this->checkCSRFParam(); if ($this->user->{$switch.'PublicAccess'}($user['id'])) { - $this->session->flash(t('User updated successfully.')); + $this->flash->success(t('User updated successfully.')); } else { - $this->session->flashError(t('Unable to update this user.')); + $this->flash->failure(t('Unable to update this user.')); } $this->response->redirect($this->helper->url->to('user', 'share', array('user_id' => $user['id']))); @@ -294,9 +294,9 @@ class User extends Base if ($valid) { if ($this->user->update($values)) { - $this->session->flash(t('Password modified successfully.')); + $this->flash->success(t('Password modified successfully.')); } else { - $this->session->flashError(t('Unable to change the password.')); + $this->flash->failure(t('Unable to change the password.')); } $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id']))); @@ -343,9 +343,9 @@ class User extends Base if ($valid) { if ($this->user->update($values)) { - $this->session->flash(t('User updated successfully.')); + $this->flash->success(t('User updated successfully.')); } else { - $this->session->flashError(t('Unable to update your user.')); + $this->flash->failure(t('Unable to update your user.')); } $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id']))); @@ -380,9 +380,9 @@ class User extends Base if ($valid) { if ($this->user->update($values)) { - $this->session->flash(t('User updated successfully.')); + $this->flash->success(t('User updated successfully.')); } else { - $this->session->flashError(t('Unable to update your user.')); + $this->flash->failure(t('Unable to update your user.')); } $this->response->redirect($this->helper->url->to('user', 'authentication', array('user_id' => $user['id']))); @@ -409,9 +409,9 @@ class User extends Base $this->checkCSRFParam(); if ($this->user->remove($user['id'])) { - $this->session->flash(t('User removed successfully.')); + $this->flash->success(t('User removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this user.')); + $this->flash->failure(t('Unable to remove this user.')); } $this->response->redirect($this->helper->url->to('user', 'index')); diff --git a/sources/app/Controller/UserImport.php b/sources/app/Controller/UserImport.php index 32b9a86..cbc5aa1 100644 --- a/sources/app/Controller/UserImport.php +++ b/sources/app/Controller/UserImport.php @@ -46,9 +46,9 @@ class UserImport extends Base $csv->read($filename, array($this->userImport, 'import')); if ($this->userImport->counter > 0) { - $this->session->flash(t('%d user(s) have been imported successfully.', $this->userImport->counter)); + $this->flash->success(t('%d user(s) have been imported successfully.', $this->userImport->counter)); } else { - $this->session->flashError(t('Nothing have been imported!')); + $this->flash->failure(t('Nothing have been imported!')); } $this->response->redirect($this->helper->url->to('userImport', 'step1')); diff --git a/sources/app/Core/Base.php b/sources/app/Core/Base.php index d402fb3..d317102 100644 --- a/sources/app/Core/Base.php +++ b/sources/app/Core/Base.php @@ -10,20 +10,24 @@ use Pimple\Container; * @package core * @author Frederic Guillot * + * @property \Kanboard\Core\Session\SessionManager $sessionManager + * @property \Kanboard\Core\Session\SessionStorage $sessionStorage + * @property \Kanboard\Core\Session\FlashMessage $flash * @property \Kanboard\Core\Helper $helper * @property \Kanboard\Core\Mail\Client $emailClient - * @property \Kanboard\Core\HttpClient $httpClient * @property \Kanboard\Core\Paginator $paginator - * @property \Kanboard\Core\Request $request - * @property \Kanboard\Core\Session $session + * @property \Kanboard\Core\Http\Client $httpClient + * @property \Kanboard\Core\Http\Request $request + * @property \Kanboard\Core\Http\Router $router + * @property \Kanboard\Core\Http\Response $response * @property \Kanboard\Core\Template $template * @property \Kanboard\Core\OAuth2 $oauth - * @property \Kanboard\Core\Router $router * @property \Kanboard\Core\Lexer $lexer * @property \Kanboard\Core\ObjectStorage\ObjectStorageInterface $objectStorage * @property \Kanboard\Core\Cache\Cache $memoryCache * @property \Kanboard\Core\Plugin\Hook $hook * @property \Kanboard\Core\Plugin\Loader $pluginLoader + * @property \Kanboard\Core\Security\Token $token * @property \Kanboard\Integration\BitbucketWebhook $bitbucketWebhook * @property \Kanboard\Integration\GithubWebhook $githubWebhook * @property \Kanboard\Integration\GitlabWebhook $gitlabWebhook diff --git a/sources/app/Core/Csv.php b/sources/app/Core/Csv.php index bec400e..28c1997 100644 --- a/sources/app/Core/Csv.php +++ b/sources/app/Core/Csv.php @@ -93,8 +93,7 @@ class Csv { if (! empty($value)) { $value = trim(strtolower($value)); - return $value === '1' || $value{0} - === 't' ? 1 : 0; + return $value === '1' || $value{0} === 't' ? 1 : 0; } return 0; @@ -164,10 +163,14 @@ class Csv */ public function write($filename, array $rows) { - $file = new SplFileObject($filename, 'w'); + $fp = fopen($filename, 'w'); - foreach ($rows as $row) { - $file->fputcsv($row, $this->delimiter, $this->enclosure); + if (is_resource($fp)) { + foreach ($rows as $row) { + fputcsv($fp, $row, $this->delimiter, $this->enclosure); + } + + fclose($fp); } return $this; diff --git a/sources/app/Core/HttpClient.php b/sources/app/Core/Http/Client.php similarity index 80% rename from sources/app/Core/HttpClient.php rename to sources/app/Core/Http/Client.php index 7f4ea47..c6bf36a 100644 --- a/sources/app/Core/HttpClient.php +++ b/sources/app/Core/Http/Client.php @@ -1,14 +1,16 @@ getContext($method, $content, $headers))); + $response = ''; + + if (is_resource($stream)) { + $response = stream_get_contents($stream); + } else { + $this->logger->error('HttpClient: request failed'); + } + + if (DEBUG) { + $this->logger->debug('HttpClient: url='.$url); + $this->logger->debug('HttpClient: payload='.$content); + $this->logger->debug('HttpClient: metadata='.var_export(@stream_get_meta_data($stream), true)); + $this->logger->debug('HttpClient: response='.$response); + } + + return $response; + } + + /** + * Get stream context + * + * @access private + * @param string $method + * @param string $content + * @param string[] $headers + * @return array + */ + private function getContext($method, $content, array $headers) + { $default_headers = array( 'User-Agent: '.self::HTTP_USER_AGENT, 'Connection: close', @@ -126,22 +158,6 @@ class HttpClient extends Base $context['http']['request_fulluri'] = true; } - $stream = @fopen(trim($url), 'r', false, stream_context_create($context)); - $response = ''; - - if (is_resource($stream)) { - $response = stream_get_contents($stream); - } else { - $this->container['logger']->error('HttpClient: request failed'); - } - - if (DEBUG) { - $this->container['logger']->debug('HttpClient: url='.$url); - $this->container['logger']->debug('HttpClient: payload='.$content); - $this->container['logger']->debug('HttpClient: metadata='.var_export(@stream_get_meta_data($stream), true)); - $this->container['logger']->debug('HttpClient: response='.$response); - } - - return $response; + return $context; } } diff --git a/sources/app/Core/Request.php b/sources/app/Core/Http/Request.php similarity index 95% rename from sources/app/Core/Request.php rename to sources/app/Core/Http/Request.php index 5eda2d0..9f89a6e 100644 --- a/sources/app/Core/Request.php +++ b/sources/app/Core/Http/Request.php @@ -1,14 +1,16 @@ token->validateCSRFToken($_POST['csrf_token'])) { + unset($_POST['csrf_token']); return $_POST; } diff --git a/sources/app/Core/Response.php b/sources/app/Core/Http/Response.php similarity index 96% rename from sources/app/Core/Response.php rename to sources/app/Core/Http/Response.php index 528a630..c5a5d3c 100644 --- a/sources/app/Core/Response.php +++ b/sources/app/Core/Http/Response.php @@ -1,14 +1,17 @@ userSession->isLogged()) { - $author = e('%s via Kanboard', $this->user->getFullname($this->session['user'])); + $author = e('%s via Kanboard', $this->helper->user->getFullname()); } $this->getTransport(MAIL_TRANSPORT)->sendEmail($email, $name, $subject, $html, $author); diff --git a/sources/app/Core/Plugin/Loader.php b/sources/app/Core/Plugin/Loader.php index 4769e5c..530d9b4 100644 --- a/sources/app/Core/Plugin/Loader.php +++ b/sources/app/Core/Plugin/Loader.php @@ -4,6 +4,7 @@ namespace Kanboard\Core\Plugin; use DirectoryIterator; use PDOException; +use LogicException; use RuntimeException; use Kanboard\Core\Tool; @@ -59,6 +60,11 @@ class Loader extends \Kanboard\Core\Base public function load($plugin) { $class = '\Kanboard\Plugin\\'.$plugin.'\\Plugin'; + + if (! class_exists($class)) { + throw new LogicException('Unable to load this plugin class '.$class); + } + $instance = new $class($this->container); Tool::buildDic($this->container, $instance->getClasses()); diff --git a/sources/app/Core/Security.php b/sources/app/Core/Security.php deleted file mode 100644 index 54207ee..0000000 --- a/sources/app/Core/Security.php +++ /dev/null @@ -1,86 +0,0 @@ -sessionStorage->csrf)) { + $this->sessionStorage->csrf = array(); + } + + $nonce = self::getToken(); + $this->sessionStorage->csrf[$nonce] = true; + + return $nonce; + } + + /** + * Check if the token exists for the current session (a token can be used only one time) + * + * @access public + * @param string $token CSRF token + * @return bool + */ + public function validateCSRFToken($token) + { + if (isset($this->sessionStorage->csrf[$token])) { + unset($this->sessionStorage->csrf[$token]); + return true; + } + + return false; + } +} diff --git a/sources/app/Core/Session.php b/sources/app/Core/Session.php deleted file mode 100644 index a93131c..0000000 --- a/sources/app/Core/Session.php +++ /dev/null @@ -1,143 +0,0 @@ -setMessage('success', $message); + } + + /** + * Add failure message + * + * @access public + * @param string $message + */ + public function failure($message) + { + $this->setMessage('failure', $message); + } + + /** + * Add new flash message + * + * @access public + * @param string $key + * @param string $message + */ + public function setMessage($key, $message) + { + if (! isset($this->sessionStorage->flash)) { + $this->sessionStorage->flash = array(); + } + + $this->sessionStorage->flash[$key] = $message; + } + + /** + * Get flash message + * + * @access public + * @param string $key + * @return string + */ + public function getMessage($key) + { + $message = ''; + + if (isset($this->sessionStorage->flash[$key])) { + $message = $this->sessionStorage->flash[$key]; + unset($this->sessionStorage->flash[$key]); + } + + return $message; + } +} diff --git a/sources/app/Core/Session/SessionManager.php b/sources/app/Core/Session/SessionManager.php new file mode 100644 index 0000000..6153efe --- /dev/null +++ b/sources/app/Core/Session/SessionManager.php @@ -0,0 +1,102 @@ +configure(); + + if (ini_get('session.auto_start') == 1) { + session_destroy(); + } + + session_name('KB_SID'); + session_start(); + + $this->container['sessionStorage']->setStorage($_SESSION); + } + + /** + * Destroy the session + * + * @access public + */ + public function close() + { + // Destroy the session cookie + $params = session_get_cookie_params(); + + setcookie( + session_name(), + '', + time() - 42000, + $params['path'], + $params['domain'], + $params['secure'], + $params['httponly'] + ); + + session_unset(); + session_destroy(); + } + + /** + * Define session settings + * + * @access private + */ + private function configure() + { + // Session cookie: HttpOnly and secure flags + session_set_cookie_params( + SESSION_DURATION, + $this->helper->url->dir() ?: '/', + null, + Request::isHTTPS(), + true + ); + + // Avoid session id in the URL + ini_set('session.use_only_cookies', '1'); + ini_set('session.use_trans_sid', '0'); + + // Enable strict mode + ini_set('session.use_strict_mode', '1'); + + // Better session hash + ini_set('session.hash_function', 'sha512'); + ini_set('session.hash_bits_per_character', 6); + + // Set an additional entropy + ini_set('session.entropy_file', '/dev/urandom'); + ini_set('session.entropy_length', '256'); + } +} diff --git a/sources/app/Core/Session/SessionStorage.php b/sources/app/Core/Session/SessionStorage.php new file mode 100644 index 0000000..703d2fb --- /dev/null +++ b/sources/app/Core/Session/SessionStorage.php @@ -0,0 +1,72 @@ +storage =& $storage; + + // Load dynamically existing session variables into object properties + foreach ($storage as $key => $value) { + $this->$key = $value; + } + } + + /** + * Get all session variables + * + * @access public + * @return array + */ + public function getAll() + { + $session = get_object_vars($this); + unset($session['storage']); + + return $session; + } + + /** + * Copy class properties to external storage + * + * @access public + */ + public function __destruct() + { + $this->storage = $this->getAll(); + } +} diff --git a/sources/app/Core/Tool.php b/sources/app/Core/Tool.php index 247fda1..edd2e60 100644 --- a/sources/app/Core/Tool.php +++ b/sources/app/Core/Tool.php @@ -39,6 +39,7 @@ class Tool * @access public * @param Container $container * @param array $namespaces + * @return Container */ public static function buildDIC(Container $container, array $namespaces) { @@ -50,6 +51,8 @@ class Tool }; } } + + return $container; } /** diff --git a/sources/app/Helper/App.php b/sources/app/Helper/App.php index 19801fa..33729f2 100644 --- a/sources/app/Helper/App.php +++ b/sources/app/Helper/App.php @@ -62,18 +62,17 @@ class App extends \Kanboard\Core\Base */ public function flashMessage() { - $html = ''; + $success_message = $this->flash->getMessage('success'); + $failure_message = $this->flash->getMessage('failure'); - if (isset($this->session['flash_message'])) { - $html = '
'.$this->helper->e($this->session['flash_message']).'
'; - unset($this->session['flash_message']); - unset($this->session['flash_error_message']); - } elseif (isset($this->session['flash_error_message'])) { - $html = '
'.$this->helper->e($this->session['flash_error_message']).'
'; - unset($this->session['flash_message']); - unset($this->session['flash_error_message']); + if (! empty($success_message)) { + return '
'.$this->helper->e($success_message).'
'; } - return $html; + if (! empty($failure_message)) { + return '
'.$this->helper->e($failure_message).'
'; + } + + return ''; } } diff --git a/sources/app/Helper/Form.php b/sources/app/Helper/Form.php index 5f19f2a..bfd75ee 100644 --- a/sources/app/Helper/Form.php +++ b/sources/app/Helper/Form.php @@ -2,7 +2,7 @@ namespace Kanboard\Helper; -use Kanboard\Core\Security; +use Kanboard\Core\Base; /** * Form helpers @@ -10,7 +10,7 @@ use Kanboard\Core\Security; * @package helper * @author Frederic Guillot */ -class Form extends \Kanboard\Core\Base +class Form extends Base { /** * Hidden CSRF token field @@ -20,7 +20,7 @@ class Form extends \Kanboard\Core\Base */ public function csrf() { - return ''; + return ''; } /** diff --git a/sources/app/Helper/Subtask.php b/sources/app/Helper/Subtask.php index 1f367b2..4bb26e7 100644 --- a/sources/app/Helper/Subtask.php +++ b/sources/app/Helper/Subtask.php @@ -20,7 +20,7 @@ class Subtask extends \Kanboard\Core\Base */ public function toggleStatus(array $subtask, $redirect) { - if ($subtask['status'] == 0 && isset($this->session['has_subtask_inprogress']) && $this->session['has_subtask_inprogress'] === true) { + if ($subtask['status'] == 0 && isset($this->sessionStorage->hasSubtaskInProgress) && $this->sessionStorage->hasSubtaskInProgress === true) { return $this->helper->url->link( trim($this->template->render('subtask/icons', array('subtask' => $subtask))) . $this->helper->e($subtask['title']), 'subtask', diff --git a/sources/app/Helper/Url.php b/sources/app/Helper/Url.php index f120252..edb2684 100644 --- a/sources/app/Helper/Url.php +++ b/sources/app/Helper/Url.php @@ -2,8 +2,8 @@ namespace Kanboard\Helper; -use Kanboard\Core\Request; -use Kanboard\Core\Security; +use Kanboard\Core\Http\Request; +use Kanboard\Core\Base; /** * Url helpers @@ -11,7 +11,7 @@ use Kanboard\Core\Security; * @package helper * @author Frederic Guillot */ -class Url extends \Kanboard\Core\Base +class Url extends Base { private $base = ''; private $directory = ''; @@ -158,7 +158,7 @@ class Url extends \Kanboard\Core\Base } if ($csrf) { - $qs['csrf_token'] = Security::getCSRFToken(); + $qs['csrf_token'] = $this->token->getCSRFToken(); } if (! empty($qs)) { diff --git a/sources/app/Helper/User.php b/sources/app/Helper/User.php index 9cd39bd..9ef20b3 100644 --- a/sources/app/Helper/User.php +++ b/sources/app/Helper/User.php @@ -136,7 +136,7 @@ class User extends \Kanboard\Core\Base */ public function getFullname(array $user = array()) { - return $this->user->getFullname(empty($user) ? $_SESSION['user'] : $user); + return $this->user->getFullname(empty($user) ? $this->sessionStorage->user : $user); } /** diff --git a/sources/app/Locale/bs_BA/translations.php b/sources/app/Locale/bs_BA/translations.php new file mode 100644 index 0000000..9faa10e --- /dev/null +++ b/sources/app/Locale/bs_BA/translations.php @@ -0,0 +1,1071 @@ + ',', + 'number.thousands_separator' => '.', + 'None' => 'None', + 'edit' => 'uredi', + 'Edit' => 'Uredi', + 'remove' => 'ukloni', + 'Remove' => 'Ukloni', + 'Update' => 'Ažuriraj', + 'Yes' => 'Da', + 'No' => 'Ne', + 'cancel' => 'odustani', + 'or' => 'ili', + 'Yellow' => 'Žuta', + 'Blue' => 'Plava', + 'Green' => 'Zelena', + 'Purple' => 'Ljubičasta', + 'Red' => 'Crvena', + 'Orange' => 'Narandžasta', + 'Grey' => 'Siva', + 'Brown' => 'Smeđa', + 'Deep Orange' => 'Tamno narandžasta', + 'Dark Grey' => 'Tamno siva', + 'Pink' => 'Roze', + 'Teal' => 'Tirkizna', + 'Cyan' => 'Zelenkasto plava', + 'Lime' => 'Žućkasto zelena', + 'Light Green' => 'Svijetlo zelena', + 'Amber' => 'Ćilibarska', + 'Save' => 'Sačuvaj', + 'Login' => 'Prijava', + 'Official website:' => 'Zvanična stranica:', + 'Unassigned' => 'Nedodijeljen', + 'View this task' => 'Pregledaj zadatak', + 'Remove user' => 'Ukloni korisnika', + 'Do you really want to remove this user: "%s"?' => 'Da li zaista želiš da ukloniš korisnika: "%s"?', + 'New user' => 'Novi korisnik', + 'All users' => 'Svi korisnici', + 'Username' => 'Korisničko ime', + 'Password' => 'Šifra', + 'Administrator' => 'Administrator', + 'Sign in' => 'Prijava', + 'Users' => 'Korisnici', + 'No user' => 'Nema korisnika', + 'Forbidden' => 'Zabranjeno', + 'Access Forbidden' => 'Pristup zabranjen', + 'Edit user' => 'Uredi korisnika', + 'Logout' => 'Odjava', + 'Bad username or password' => 'Pogrešno korisničko ime ili šifra', + 'Edit project' => 'Uredi projekat', + 'Name' => 'Ime', + 'Projects' => 'Projekti', + 'No project' => 'Bez projekta', + 'Project' => 'Projekat', + 'Status' => 'Status', + 'Tasks' => 'Zadatak', + 'Board' => 'Tabla', + 'Actions' => 'Akcije', + 'Inactive' => 'Neaktivan', + 'Active' => 'Aktivan', + 'Add this column' => 'Dodaj kolonu', + '%d tasks on the board' => '%d zadataka na tabli', + '%d tasks in total' => '%d zadataka ukupno', + 'Unable to update this board.' => 'Nemogu da ažuriram ovu tablu.', + 'Edit board' => 'Izmijeni tablu', + 'Disable' => 'Onemogući', + 'Enable' => 'Omogući', + 'New project' => 'Novi projekat', + 'Do you really want to remove this project: "%s"?' => 'Da li želiš da ukloniš projekat: "%s"?', + 'Remove project' => 'Ukloni projekat', + 'Edit the board for "%s"' => 'Uredi 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', + 'Assigned to %s' => 'Dodijeljen korisniku %s', + 'Remove a column' => 'Ukloni kolonu', + 'Remove a column from a board' => 'Ukloni kolonu sa table', + 'Unable to remove this column.' => 'Nemoguće uklanjanje kolone.', + 'Do you really want to remove this column: "%s"?' => 'Da li zaista želiš da ukoniš ovu kolonu: "%s"?', + 'This action will REMOVE ALL TASKS associated to this column!' => 'Ova akcija BRIŠE SVE ZADATKE vezane za ovu kolonu!', + 'Settings' => 'Podešavanja', + 'Application settings' => 'Podešavanja aplikacije', + 'Language' => 'Jezik', + 'Webhook token:' => 'Token:', + 'API token:' => 'Token za API', + 'Database size:' => 'Veličina baze:', + 'Download the database' => 'Preuzmi bazu', + 'Optimize the database' => 'Optimizuj bazu', + '(VACUUM command)' => '(Naredba VACUUM)', + '(Gzip compressed Sqlite file)' => '(Sqlite baza spakovana Gzip-om)', + 'Close a task' => 'Zatvori zadatak', + 'Edit a task' => 'Uredi zadatak', + 'Column' => 'Kolona', + 'Color' => 'Boja', + 'Assignee' => 'Izvršilac', + 'Create another task' => 'Dodaj zadatak', + 'New task' => 'Novi zadatak', + 'Open a task' => 'Otvori zadatak', + 'Do you really want to open this task: "%s"?' => 'Da li zaista želiš da otvoriš zadatak: "%s"?', + 'Back to the board' => 'Nazad na tablu', + 'Created on %B %e, %Y at %k:%M %p' => 'Kreiran %e %B %Y o %k:%M', + 'There is nobody assigned' => 'Niko nije dodijeljen!', + 'Column on the board:' => 'Kolona na tabli:', + 'Status is open' => 'Status otvoren', + 'Status is closed' => 'Status zatvoren', + 'Close this task' => 'Zatvori ovaj zadatak', + 'Open this task' => 'Otvori ovaj zadatak', + 'There is no description.' => 'Bez opisa.', + 'Add a new task' => 'Dodaj zadatak', + 'The username is required' => 'Korisničko ime je obavezno', + 'The maximum length is %d characters' => 'Maksimalna dužina je %d znakova', + 'The minimum length is %d characters' => 'Minimalna dužina je %d znakova', + 'The password is required' => 'Šifra je obavezna', + 'This value must be an integer' => 'Mora biti cio broj', + 'The username must be unique' => 'Korisničko ime mora biti jedinstveno', + 'The user id is required' => 'ID korisnika je obavezan', + 'Passwords don\'t match' => 'Šifre se ne podudaraju', + 'The confirmation is required' => 'Potvrda je obavezna', + 'The project is required' => 'Projekat je obavezan', + 'The id is required' => 'ID je obavezan', + 'The project id is required' => 'ID projekta je obavezan', + 'The project name is required' => 'Naziv projekta je obavezan', + 'The title is required' => 'Naslov je obavezan', + 'Settings saved successfully.' => 'Podešavanja uspješno sačuvana.', + 'Unable to save your settings.' => 'Nemoguće sačuvati podešavanja.', + 'Database optimization done.' => 'Optimizacija baze je završena.', + 'Your project have been created successfully.' => 'Projekat je uspješno napravljen.', + 'Unable to create your project.' => 'Nemoguće kreiranje projekta.', + 'Project updated successfully.' => 'Projekat je uspješno ažuriran.', + 'Unable to update this project.' => 'Nemoguće ažuriranje projekta.', + 'Unable to remove this project.' => 'Nemoguće uklanjanje projekta.', + 'Project removed successfully.' => 'Projekat uspješno uklonjen.', + 'Project activated successfully.' => 'Projekt uspješno aktiviran.', + 'Unable to activate this project.' => 'Nemoguće aktiviranje projekta.', + 'Project disabled successfully.' => 'Projekat uspješno deaktiviran.', + 'Unable to disable this project.' => 'nemoguće deaktiviranje projekta.', + 'Unable to open this task.' => 'Nemoguće otvaranje zadatka.', + 'Task opened successfully.' => 'Zadatak uspješno otvoren.', + 'Unable to close this task.' => 'Nije moguće zatvaranje ovog zadatka.', + 'Task closed successfully.' => 'Zadatak uspješno zatvoren.', + 'Unable to update your task.' => 'Nije moguće ažuriranje zadatka.', + 'Task updated successfully.' => 'Zadatak uspješno ažuriran.', + 'Unable to create your task.' => 'Nije moguće kreiranje zadatka.', + 'Task created successfully.' => 'Zadatak uspješno kreiran.', + 'User created successfully.' => 'Korisnik uspješno kreiran', + 'Unable to create your user.' => 'Nije uspjelo kreiranje korisnika.', + 'User updated successfully.' => 'Korisnik uspješno ažuriran.', + 'Unable to update your user.' => 'Nije moguće ažuriranje korisnika.', + 'User removed successfully.' => 'Korisnik uspješno uklonjen.', + 'Unable to remove this user.' => 'Nije moguće uklanjanje korisnika.', + 'Board updated successfully.' => 'Tabla uspješno ažurirana.', + 'Ready' => 'Spreman', + 'Backlog' => 'Zaliha', + 'Work in progress' => 'U izradi', + 'Done' => 'Gotovo', + 'Application version:' => 'Verzija aplikacije:', + 'Completed on %B %e, %Y at %k:%M %p' => 'Završeno u %e %B %Y o %k:%M', + '%B %e, %Y at %k:%M %p' => '%e %B %Y o %k:%M', + 'Date created' => 'Kreiran dana', + 'Date completed' => 'Završen dana', + 'Id' => 'Id', + '%d closed tasks' => '%d zatvorenih zadataka', + 'No task for this project' => 'Nema dodijeljenih zadataka ovom projektu', + 'Public link' => 'Javni link', + 'Change assignee' => 'Promjena izvršioca', + 'Change assignee for the task "%s"' => 'Promjena izvršioca za zadatak "%s"', + 'Timezone' => 'Vremenska zona', + 'Sorry, I didn\'t find this information in my database!' => 'Na žalost, nije pronađena informacija u bazi', + 'Page not found' => 'Strana nije pronađena', + 'Complexity' => 'Složenost', + 'Task limit' => 'Najviše zadataka', + 'Task count' => 'Broj zadataka', + 'Edit project access list' => 'Uredi prava pristupa projektu', + 'Allow this user' => 'Dozvoli ovog korisnika', + 'Don\'t forget that administrators have access to everything.' => 'Zapamti: Administrator može pristupiti svemu!', + 'Revoke' => 'Opozovi', + 'List of authorized users' => 'Spisak odobrenih korisnika', + 'User' => 'Korisnik', + 'Nobody have access to this project.' => 'Niko nema pristup ovom projektu', + 'Comments' => 'Komentari', + 'Write your text in Markdown' => 'Pisanje teksta pomoću Markdown', + 'Leave a comment' => 'Ostavi komentar', + 'Comment is required' => 'Komentar je obavezan', + 'Leave a description' => 'Dodaj opis', + 'Comment added successfully.' => 'Komentar uspješno dodan', + 'Unable to create your comment.' => 'Nemoguće kreiranje komentara', + 'Edit this task' => 'Uredi ovaj zadatak', + 'Due Date' => 'Treba biti gotovo do dana', + 'Invalid date' => 'Pogrešan datum', + 'Must be done before %B %e, %Y' => 'Mora biti gotovo prije %e %B %Y', + '%B %e, %Y' => '%e %B %Y', + '%b %e, %Y' => '%b %e, %Y', + 'Automatic actions' => 'Automatske akcije', + 'Your automatic action have been created successfully.' => 'Uspješno kreirana automatska akcija', + 'Unable to create your automatic action.' => 'Nemoguće kreiranje automatske akcije', + 'Remove an action' => 'Obriši akciju', + 'Unable to remove this action.' => 'Nije moguće obrisati akciju', + 'Action removed successfully.' => 'Akcija obrisana', + 'Automatic actions for the project "%s"' => 'Akcije za automatizaciju projekta "%s"', + 'Defined actions' => 'Definisane akcje', + 'Add an action' => 'dodaj akcju', + 'Event name' => 'Naziv događaja', + 'Action name' => 'Naziv akcije', + 'Action parameters' => 'Parametri akcije', + 'Action' => 'Akcija', + 'Event' => 'Događaj', + 'When the selected event occurs execute the corresponding action.' => 'Na izabrani događaj izvrši odgovarajuću akciju', + 'Next step' => 'Slijedeći korak', + 'Define action parameters' => 'Definiši parametre akcije', + 'Save this action' => 'Snimi akciju', + 'Do you really want to remove this action: "%s"?' => 'Da li da obrišem akciju "%s"?', + 'Remove an automatic action' => 'Obriši automatsku akciju', + 'Assign the task to a specific user' => 'Dodijeli zadatak određenom korisniku', + 'Assign the task to the person who does the action' => 'Dodeli zadatak korisniku koji je izvršio akciju', + 'Duplicate the task to another project' => 'Kopiraj akciju u drugi projekat', + 'Move a task to another column' => 'Premjesti zadatak u drugu kolonu', + 'Task modification' => 'Izmjene zadatka', + 'Task creation' => 'Kreiranje zadatka', + 'Closing a task' => 'Zatvaranja zadatka', + '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', + 'Comment updated successfully.' => 'Komentar uspješno ažuriran.', + 'Unable to update your comment.' => 'Neuspješno ažuriranje komentara.', + 'Remove a comment' => 'Obriši komentar', + 'Comment removed successfully.' => 'Komentar je uspješno obrisan.', + 'Unable to remove this comment.' => 'Neuspješno brisanje komentara.', + 'Do you really want to remove this comment?' => 'Da li zaista želiš obrisati ovaj komentar?', + 'Only administrators or the creator of the comment can access to this page.' => 'Samo administrator i kreator komentara mogu pristupiti ovoj stranici.', + 'Current password for the user "%s"' => 'Trenutna šifra korisnika "%s"', + 'The current password is required' => 'Trenutna šifra je obavezna', + 'Wrong password' => 'Pogrešna šifra', + 'Unknown' => 'Nepoznat', + 'Last logins' => 'Posljednje prijave', + 'Login date' => 'Datum prijave', + 'Authentication method' => 'Metod autentikacije', + 'IP address' => 'IP adresa', + 'User agent' => 'Browser', + 'Persistent connections' => 'Stalna konekcija', + 'No session.' => 'Bez sesije', + 'Expiration date' => 'Ističe', + 'Remember Me' => 'Zapamti me', + 'Creation date' => 'Datum kreiranja', + 'Everybody' => 'Svi', + 'Open' => 'Otvoreni', + 'Closed' => 'Zatvoreni', + 'Search' => 'Pretraga', + 'Nothing found.' => 'Ništa nije pronađeno', + 'Due date' => 'Treba biti gotovo do dana', + 'Others formats accepted: %s and %s' => 'Ostali podržani formati: %s i %s', + 'Description' => 'Opis', + '%d comments' => '%d Komentara', + '%d comment' => '%d Komentar', + 'Email address invalid' => 'Pogrešan e-mail', + 'Your external account is not linked anymore to your profile.' => 'Vaš vanjski korisnički profil nije više povezan.', + 'Unable to unlink your external account.' => 'Nemoguće ukloniti vezu s vanjskim korisničkim profilom', + 'External authentication failed' => 'Vanjska autentikacija nije uspostavljena', + 'Your external account is linked to your profile successfully.' => 'Uspješno uspostavljena vanjska autentikacija', + 'Email' => 'E-mail', + 'Link my Google Account' => 'Poveži sa Google nalogom', + 'Unlink my Google Account' => 'Ukini vezu sa Google nalogom', + 'Login with my Google Account' => 'Prijavi se preko Google naloga', + 'Project not found.' => 'Projekat nije pronađen.', + 'Task removed successfully.' => 'Zadatak uspješno uklonjen.', + 'Unable to remove this task.' => 'Nemoguće uklanjanje zadatka.', + 'Remove a task' => 'Ukloni zadatak', + 'Do you really want to remove this task: "%s"?' => 'Da li zaista želiš ukloniti zadatak "%s"?', + 'Assign automatically a color based on a category' => 'Automatski dodijeli boju po kategoriji', + 'Assign automatically a category based on a color' => 'Automatski dodijeli kategoriju po boji', + 'Task creation or modification' => 'Kreiranje ili izmjena zadatka', + 'Category' => 'Kategorija', + 'Category:' => 'Kategorija:', + 'Categories' => 'Kategorije', + 'Category not found.' => 'Kategorija nije pronađena', + 'Your category have been created successfully.' => 'Uspješno kreirana kategorija.', + 'Unable to create your category.' => 'Nije moguće kreirati kategoriju.', + 'Your category have been updated successfully.' => 'Kategorija je uspješno ažurirana', + 'Unable to update your category.' => 'Nemoguće izmijeniti kategoriju', + 'Remove a category' => 'Ukloni kategoriju', + 'Category removed successfully.' => 'Kategorija uspešno uklonjena.', + 'Unable to remove this category.' => 'Nije moguće ukloniti kategoriju.', + 'Category modification for the project "%s"' => 'Izmjena kategorije za projekat "%s"', + 'Category Name' => 'Naziv kategorije', + 'Add a new category' => 'Dodaj novu kategoriju', + 'Do you really want to remove this category: "%s"?' => 'Da li zaista želiš ukloniti kategoriju: "%s"?', + 'All categories' => 'Sve kategorije', + 'No category' => 'Bez kategorije', + 'The name is required' => 'Naziv je obavezan', + 'Remove a file' => 'Ukloni fajl', + 'Unable to remove this file.' => 'Fajl nije moguće ukloniti.', + 'File removed successfully.' => 'Uspješno uklonjen fajl.', + 'Attach a document' => 'Prikači dokument', + 'Do you really want to remove this file: "%s"?' => 'Da li da uklonim fajl: "%s"?', + 'Attachments' => 'Prilozi', + 'Edit the task' => 'Uredi zadatak', + 'Edit the description' => 'Uredi opis zadatka', + 'Add a comment' => 'Dodaj komentar', + 'Edit a comment' => 'Izmijeni komentar', + 'Summary' => 'Pregled', + 'Time tracking' => 'Praćenje vremena', + 'Estimate:' => 'Procjena:', + 'Spent:' => 'Potrošeno:', + 'Do you really want to remove this sub-task?' => 'Da li da zaista želiš ukloniti pod-zdadatak?', + 'Remaining:' => 'Preostalo:', + 'hours' => 'sati', + 'spent' => 'potrošeno', + 'estimated' => 'procijenjeno', + 'Sub-Tasks' => 'Pod-zadaci', + 'Add a sub-task' => 'Dodaj pod-zadatak', + 'Original estimate' => 'Originalna procjena', + 'Create another sub-task' => 'Dodaj novi pod-zadatak', + 'Time spent' => 'Utrošeno vrijeme', + 'Edit a sub-task' => 'Izmijeni pod-zadatak', + 'Remove a sub-task' => 'Ukloni pod-zadatak', + 'The time must be a numeric value' => 'Vrijeme mora biti broj', + 'Todo' => 'Za uraditi', + 'In progress' => 'U radu', + 'Sub-task removed successfully.' => 'Pod-zadatak uspješno uklonjen.', + 'Unable to remove this sub-task.' => 'Nemoguće ukloniti pod-zadatak.', + 'Sub-task updated successfully.' => 'Pod-zadatak uspješno ažuriran.', + 'Unable to update your sub-task.' => 'Nemoguće ažurirati pod-zadatak.', + 'Unable to create your sub-task.' => 'Nemoguće dodati pod-zadatak.', + 'Sub-task added successfully.' => 'Pod-zadatak uspješno dodan.', + 'Maximum size: ' => 'Maksimalna veličina: ', + 'Unable to upload the file.' => 'Nije moguće snimiti fajl.', + 'Display another project' => 'Prikaži drugi projekat', + 'Login with my Github Account' => 'Prijavi me s mojim Github korisničkim računom', + 'Link my Github Account' => 'Poveži s mojim Github korisničkim računom', + 'Unlink my Github Account' => 'Odbavi vez s mojim Github korisničkim računom', + 'Created by %s' => 'Kreirao %s', + 'Last modified on %B %e, %Y at %k:%M %p' => 'Posljednja izmjena %e %B %Y o %k:%M', + 'Tasks Export' => 'Izvoz zadataka', + 'Tasks exportation for "%s"' => 'Izvoz zadataka za "%s"', + 'Start Date' => 'Početni datum', + 'End Date' => 'Datum završetka', + 'Execute' => 'Izvrši', + 'Task Id' => 'Identifikator zadatka', + 'Creator' => 'Autor', + 'Modification date' => 'Datum izmjene', + 'Completion date' => 'Datum završetka', + 'Clone' => 'Kloniraj', + 'Project cloned successfully.' => 'Projekat uspješno kloniran.', + 'Unable to clone this project.' => 'Nije moguće klonirati projekat.', + 'Enable email notifications' => 'Omogući obavještenja e-mailom', + 'Task position:' => 'Pozicija zadatka:', + 'The task #%d have been opened.' => 'Zadatak #%d je otvoren.', + 'The task #%d have been closed.' => 'Zadatak #%d je zatvoren.', + 'Sub-task updated' => 'Pod-zadatak izmijenjen', + 'Title:' => 'Naslov:', + 'Status:' => 'Status:', + 'Assignee:' => 'Izvršilac:', + 'Time tracking:' => 'Praćenje vremena:', + 'New sub-task' => 'Novi pod-zadatak', + 'New attachment added "%s"' => 'Ubačen novi prilog "%s"', + 'Comment updated' => 'Komentar ažuriran', + 'New comment posted by %s' => '%s ostavio novi komentar', + 'New attachment' => 'Novi prilog', + 'New comment' => 'Novi komentar', + 'New subtask' => 'Novi pod-zadatak', + 'Subtask updated' => 'Pod-zadatak ažuriran', + 'Task updated' => 'Zadatak ažuriran', + 'Task closed' => 'Zadatak je zatvoren', + 'Task opened' => 'Zadatak je otvoren', + 'I want to receive notifications only for those projects:' => 'Želim obavještenja samo za ove projekte:', + 'view the task on Kanboard' => 'Pregledaj zadatke', + 'Public access' => 'Javni pristup', + 'User management' => 'Upravljanje korisnicima', + 'Active tasks' => 'Aktivni zadaci', + 'Disable public access' => 'Zabrani javni pristup', + 'Enable public access' => 'Dozvoli javni pristup', + 'Public access disabled' => 'Javni pristup onemogućen!', + 'Do you really want to disable this project: "%s"?' => 'Da li zaista želiš da deaktiviraš projekat: "%s"?', + 'Do you really want to enable this project: "%s"?' => 'Da li zaista želiš da aktiviraš projekat: "%s"?', + 'Project activation' => 'Aktivacija projekta', + 'Move the task to another project' => 'Premjesti zadatak u drugi projekat', + 'Move to another project' => 'Premjesti u drugi projekat', + 'Do you really want to duplicate this task?' => 'Da li zaista želiš duplicirati ovaj zadatak?', + 'Duplicate a task' => 'Dupliciraj zadatak', + 'External accounts' => 'Vanjski korisnički računi', + 'Account type' => 'Tip korisničkog računa', + 'Local' => 'Lokalno', + 'Remote' => 'Udaljeno', + 'Enabled' => 'Omogućeno', + 'Disabled' => 'Onemogućeno', + 'Username:' => 'Korisničko ime:', + 'Name:' => 'Ime i Prezime', + 'Email:' => 'Email: ', + 'Notifications:' => 'Obavještenja: ', + 'Notifications' => 'Obavještenja', + 'Group:' => 'Grupa:', + 'Regular user' => 'Standardni korisnik', + 'Account type:' => 'Vrsta korisničkog računa:', + 'Edit profile' => 'Uredi profil', + 'Change password' => 'Promijeni šifru', + 'Password modification' => 'Izmjena šifre', + 'External authentications' => 'Vanjske autentikacije', + 'Google Account' => 'Google korisnički račun', + 'Github Account' => 'Github korisnički račun', + 'Never connected.' => 'Bez konekcija.', + 'No account linked.' => 'Bez povezanih korisničkih računa.', + 'Account linked.' => 'Korisnički račun povezan.', + 'No external authentication enabled.' => 'Bez omogućenih vanjskih autentikacija.', + 'Password modified successfully.' => 'Uspješna izmjena šifre.', + 'Unable to change the password.' => 'Nije moguće izmijeniti šifru.', + 'Change category for the task "%s"' => 'Izijmeni kategoriju zadatka "%s"', + 'Change category' => 'Izmijeni kategoriju', + '%s updated the task %s' => '%s izmijenio zadatak %s', + '%s opened the task %s' => '%s otvorio zadatak %s', + '%s moved the task %s to the position #%d in the column "%s"' => '%s premjestio zadatak %s na poziciju #%d u koloni "%s"', + '%s moved the task %s to the column "%s"' => '%s premjestio zadatak %s u kolonu "%s"', + '%s created the task %s' => '%s kreirao zadatak %s', + '%s closed the task %s' => '%s zatvorio zadatak %s', + '%s created a subtask for the task %s' => '%s kreirao pod-zadatak zadatka %s', + '%s updated a subtask for the task %s' => '%s izmijenio pod-zadatak zadatka %s', + 'Assigned to %s with an estimate of %s/%sh' => 'Dodijeljen korisniku %s uz procjenu vremena %s/%sh', + 'Not assigned, estimate of %sh' => 'Ne dodijeljen, procijenjeno vrijeme %sh', + '%s updated a comment on the task %s' => '%s izmijenio komentar zadatka %s', + '%s commented the task %s' => '%s komentarisao zadatak %s', + '%s\'s activity' => 'Aktivnosti %s', + 'RSS feed' => 'RSS kanal', + '%s updated a comment on the task #%d' => '%s izmijenio komentar zadatka #%d', + '%s commented on the task #%d' => '%s komentarisao zadatak #%d', + '%s updated a subtask for the task #%d' => '%s izmijenio pod-zadatak zadatka #%d', + '%s created a subtask for the task #%d' => '%s kreirao pod-zadatak zadatka #%d', + '%s updated the task #%d' => '%s ažurirao zadatak #%d', + '%s created the task #%d' => '%s kreirao zadatak #%d', + '%s closed the task #%d' => '%s zatvorio zadatak #%d', + '%s open the task #%d' => '%s otvorio zadatak #%d', + '%s moved the task #%d to the column "%s"' => '%s premjestio zadatak #%d u kolonu "%s"', + '%s moved the task #%d to the position %d in the column "%s"' => '%s premjestio zadatak #%d na poziciju %d u koloni "%s"', + 'Activity' => 'Aktivnosti', + 'Default values are "%s"' => 'Podrazumijevane vrijednosti su: "%s"', + 'Default columns for new projects (Comma-separated)' => 'Podrazumijevane kolone za novi projekat (Odvojeni zarezom)', + 'Task assignee change' => 'Promijena izvršioca zadatka', + '%s change the assignee of the task #%d to %s' => '%s zamijeni izvršioca za zadatak #%d u %s', + '%s changed the assignee of the task %s to %s' => '%s promijenio izvršioca za zadatak %s u %s', + 'New password for the user "%s"' => 'Nova šifra korisnika "%s"', + 'Choose an event' => 'Izaberi događaj', + 'Github commit received' => 'Github: commit dobijen', + 'Github issue opened' => 'Github: otvoren problem', + 'Github issue closed' => 'Github: zatvoren problem', + 'Github issue reopened' => 'Github: ponovo otvoren problem', + 'Github issue assignee change' => 'Github: izmijenjen izvršioc problema', + 'Github issue label change' => 'Github: izmjena etikete problema', + 'Create a task from an external provider' => 'Kreiraj zadatak preko posrednika', + 'Change the assignee based on an external username' => 'Izmijene izvršioca bazirano na vanjskom korisničkom imenu', + 'Change the category based on an external label' => 'Izmijene kategorije bazirano na vanjskoj etiketi', + 'Reference' => 'Referenca', + 'Reference: %s' => 'Referenca: %s', + 'Label' => 'Etiketa', + 'Database' => 'Baza', + 'About' => 'O', + 'Database driver:' => 'Database driver:', + 'Board settings' => 'Postavke table', + 'URL and token' => 'URL i token', + 'Webhook settings' => 'Postavke za webhook', + 'URL for task creation:' => 'URL za kreiranje zadataka', + 'Reset token' => 'Resetuj token', + 'API endpoint:' => 'API endpoint', + 'Refresh interval for private board' => 'Interval osvježavanja privatnih tabli', + 'Refresh interval for public board' => 'Interval osvježavanja javnih tabli', + 'Task highlight period' => 'Period naznačavanja zadatka', + 'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => 'Period (u sekundama) u kom su se događale promjene na zadatku (0 je onemogućeno, 2 dana je uobičajeno)', + 'Frequency in second (60 seconds by default)' => 'Frekvencija u sekundama (60 sekundi je uobičajeno)', + 'Frequency in second (0 to disable this feature, 10 seconds by default)' => 'Frekvencija u sekundama (0 je onemogućeno u budućnosti, 10 sekundi je uobičajeno)', + 'Application URL' => 'URL aplikacje', + 'Example: http://example.kanboard.net/ (used by email notifications)' => 'Primjer: http://example.kanboard.net/ (koristi se u obavještenjima putem email-a)', + 'Token regenerated.' => 'Token regenerisan.', + 'Date format' => 'Format datuma', + 'ISO format is always accepted, example: "%s" and "%s"' => 'Format ISO je uvek prihvatljiv, primjer: "%s", "%s"', + 'New private project' => 'Novi privatni projekat', + 'This project is private' => 'Ovaj projekat je privatan', + 'Type here to create a new sub-task' => 'Piši ovdje za kreiranje novog pod-zadatka', + 'Add' => 'Dodaj', + 'Estimated time: %s hours' => 'Procijenjeno vrijeme: %s sati', + 'Time spent: %s hours' => 'Utrošeno vrijeme: %s sati', + 'Started on %B %e, %Y' => 'Započeto dana %e %B %Y', + 'Start date' => 'Datum početka', + 'Time estimated' => 'Procijenjeno vrijeme', + 'There is nothing assigned to you.' => 'Ništa vam nije dodijeljeno', + 'My tasks' => 'Moji zadaci', + 'Activity stream' => 'Spisak aktivnosti', + 'Dashboard' => 'Panel', + 'Confirmation' => 'Potvrda', + 'Allow everybody to access to this project' => 'Dozvoli svima pristup ovom projektu', + 'Everybody have access to this project.' => 'Svima je dozvoljen pristup ovom projektu.', + 'Webhooks' => 'Webhooks', + 'API' => 'API', + 'Github webhooks' => 'Github webhooks', + 'Help on Github webhooks' => 'Pomoć na Github webhooks', + 'Create a comment from an external provider' => 'Napravi komentar preko vanjskog posrednika', + 'Github issue comment created' => 'Github: dodan komentar za problem', + 'Project management' => 'Upravljanje projektima', + 'My projects' => 'Moji projekti', + 'Columns' => 'Kolone', + 'Task' => 'Zadatak', + 'Your are not member of any project.' => 'Nisi član ni jednog projekta', + 'Percentage' => 'Procenat', + 'Number of tasks' => 'Broj zadataka', + 'Task distribution' => 'Podjela zadataka', + 'Reportings' => 'Izveštaji', + 'Task repartition for "%s"' => 'Zaduženja zadataka za "%s"', + 'Analytics' => 'Analiza', + 'Subtask' => 'Pod-zadatak', + 'My subtasks' => 'Moji pod-zadaci', + 'User repartition' => 'Zaduženja korisnika', + 'User repartition for "%s"' => 'Zaduženja korisnika za "%s"', + 'Clone this project' => 'Kloniraj ovaj projekat', + 'Column removed successfully.' => 'Kolona uspješno uklonjena.', + 'Github Issue' => 'Github problemi', + 'Not enough data to show the graph.' => 'Nedovoljno podataka za prikaz na grafikonu.', + 'Previous' => 'Prethodni', + 'The id must be an integer' => 'ID mora biti cjeloviti broj', + 'The project id must be an integer' => 'ID projekta mora biti cjeloviti broj', + 'The status must be an integer' => 'Status mora biti cjeloviti broj', + 'The subtask id is required' => 'ID pod-zadataka je obavezan', + 'The subtask id must be an integer' => 'ID pod-zadatka mora biti cjeloviti broj', + 'The task id is required' => 'ID zadatka je obavezan', + 'The task id must be an integer' => 'ID zadatka mora biti cjeloviti broj', + 'The user id must be an integer' => 'ID korisnika mora biti cjeloviti broj', + 'This value is required' => 'Vrijednost je obavezna', + 'This value must be numeric' => 'Vrijednost mora biti broj', + 'Unable to create this task.' => 'Nije moguće kreirati zadatak.', + 'Cumulative flow diagram' => 'Zbirni dijagram toka', + 'Cumulative flow diagram for "%s"' => 'Zbirni dijagram toka za "%s"', + 'Daily project summary' => 'Zbirni pregled po danima', + 'Daily project summary export' => 'Izvoz zbirnog pregleda po danima', + 'Daily project summary export for "%s"' => 'Izvoz zbirnog pregleda po danima za "%s"', + 'Exports' => 'Izvozi', + 'This export contains the number of tasks per column grouped per day.' => 'Ovaj izvoz sadržava broj zadataka po koloni grupisanih po danima.', + 'Nothing to preview...' => 'Ništa za pokazati...', + 'Preview' => 'Pregled', + 'Write' => 'Piši', + 'Active swimlanes' => 'Aktivne swimline trake', + 'Add a new swimlane' => 'Dodaj novu swimline traku', + 'Change default swimlane' => 'Preimenuj podrazumijevanu swimline traku', + 'Default swimlane' => 'Podrazumijevana swimline traka', + 'Do you really want to remove this swimlane: "%s"?' => 'Da li zaista želiš ukloniti ovu swimline traku: "%s"?', + 'Inactive swimlanes' => 'Neaktivne swimline trake', + 'Set project manager' => 'Postavi kao projekt menadžera', + 'Set project member' => 'Postavi kao člana projekta ', + '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.', + 'Swimlane removed successfully.' => 'Swimline traka uspješno uklonjena.', + '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.', + 'Example: "Bug, Feature Request, Improvement"' => 'Npr: "Greška, Zahtjev za izmjenama, Poboljšanje"', + 'Default categories for new projects (Comma-separated)' => 'Podrazumijevane kategorije za novi projekat', + 'Gitlab commit received' => 'Gitlab: commit dobijen', + 'Gitlab issue opened' => 'Gitlab: problem otvoren', + 'Gitlab issue closed' => 'Gitlab: problem zatvoren', + 'Gitlab webhooks' => 'Gitlab webhooks', + 'Help on Gitlab webhooks' => 'Pomoc na Gitlab webhooks', + 'Integrations' => 'Integracije', + 'Integration with third-party services' => 'Integracija sa uslugama vanjskih servisa', + 'Role for this project' => 'Uloga u ovom projektu', + 'Project manager' => 'Manadžer projekta', + 'Project member' => 'Učesnik projekta', + 'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Projekt menadžer može mijenjati postavke projekta i ima više prava od standardnog korisnika.', + 'Gitlab Issue' => 'Gitlab problemi', + 'Subtask Id' => 'ID pod-zadatka', + 'Subtasks' => 'Pod-zadaci', + 'Subtasks Export' => 'Izvoz pod-zadataka', + 'Subtasks exportation for "%s"' => 'Izvoz pod-zadataka za "%s"', + 'Task Title' => 'Naslov zadatka', + 'Untitled' => 'Bez naslova', + 'Application default' => 'Podrazumijevano od aplikacije', + 'Language:' => 'Jezik:', + 'Timezone:' => 'Vremenska zona:', + 'All columns' => 'Sve kolone', + 'Calendar' => 'Kalendar', + 'Next' => 'Slijedeći', + '#%d' => '#%d', + 'All swimlanes' => 'Sve swimline trake', + 'All colors' => 'Sve boje', + 'Moved to column %s' => 'Premješten u kolonu %s', + 'Change description' => 'Promijeni opis', + 'User dashboard' => 'Korisnički panel', + 'Allow only one subtask in progress at the same time for a user' => 'Dozvoli samo jedan pod-zadatak "u radu" po korisniku', + 'Edit column "%s"' => 'Uredi kolonu "%s"', + 'Select the new status of the subtask: "%s"' => 'Izaberi novi status za pod-zadatak: "%s"', + 'Subtask timesheet' => 'Vremenska tabela za pod-zadatak', + 'There is nothing to show.' => 'Nema ništa za pokazati', + 'Time Tracking' => 'Praćenje vremena', + 'You already have one subtask in progress' => 'Već imaš jedan pod-zadatak "u radu"', + 'Which parts of the project do you want to duplicate?' => 'Koje delove projekta želiš duplicirati?', + 'Disallow login form' => 'Zabrani prijavnu formu', + 'Bitbucket commit received' => 'Bitbucket: commit dobijen', + 'Bitbucket webhooks' => 'Bitbucket: webhooks', + 'Help on Bitbucket webhooks' => 'Pomoć na Bitbucket webhooks', + 'Start' => 'Početak', + 'End' => 'Kraj', + 'Task age in days' => 'Trajanje zadatka u danima', + 'Days in this column' => 'Dani u ovoj koloni', + '%dd' => '%dd', + 'Add a link' => 'Dodaj vezu', + 'Add a new link' => 'Dodaj novu vezu', + 'Do you really want to remove this link: "%s"?' => 'Da li zaista želite ukloniti ovu vezu: "%s"?', + 'Do you really want to remove this link with task #%d?' => 'Da li zaista želite ukloniti ovu vezu sa zadatkom #%d?', + 'Field required' => 'Polje je obavezno', + 'Link added successfully.' => 'Veza je uspješno dodana.', + 'Link updated successfully.' => 'Veza je uspješno ažurirana.', + 'Link removed successfully.' => 'Veza je uspješno uklonjena.', + 'Link labels' => 'Veza s etiketama', + 'Link modification' => 'Veza modifikacija', + 'Links' => 'Veze', + 'Link settings' => 'Postavke veza', + 'Opposite label' => 'Suprotna etiketa', + 'Remove a link' => 'Ukloni vezu', + 'Task\'s links' => 'Veze zadatka', + 'The labels must be different' => 'Etikete moraju biti različite', + 'There is no link.' => 'Ovdje nema veza', + 'This label must be unique' => 'Ova etiketa mora biti jedinstvena', + 'Unable to create your link.' => 'Nemoguće napraviti vezu.', + 'Unable to update your link.' => 'Nemoguće ažurirati vezu.', + 'Unable to remove this link.' => 'Nemoguće ukloniti vezu.', + 'relates to' => 'relacija sa', + 'blocks' => 'blokira', + 'is blocked by' => 'je blokiran od', + 'duplicates' => 'duplicira', + 'is duplicated by' => 'je dupliciran od', + 'is a child of' => 'je dijete od', + 'is a parent of' => 'je roditelj od', + 'targets milestone' => 'cilj prekretnice', + 'is a milestone of' => 'je od prekretnice', + 'fixes' => 'popravlja', + 'is fixed by' => 'je popravljen od', + 'This task' => 'Ovaj zadatak', + '<1h' => '<1h', + '%dh' => '%dh', + '%b %e' => '%b %e', + 'Expand tasks' => 'Proširi zadatke', + 'Collapse tasks' => 'Skupi zadatke', + 'Expand/collapse tasks' => 'Proširi/skupi zadatke', + 'Close dialog box' => 'Skupi dialog', + 'Submit a form' => 'Pošalji obrazac', + 'Board view' => 'Pregled ploče', + 'Keyboard shortcuts' => 'Prečice tastature', + 'Open board switcher' => 'Otvori prekidače ploče', + 'Application' => 'Aplikacija', + 'since %B %e, %Y at %k:%M %p' => 'od %B %e, %Y do %k:%M %p', + 'Compact view' => 'Kompaktan pregled', + 'Horizontal scrolling' => 'Horizontalno listanje', + 'Compact/wide view' => 'Skupi/raširi pregled', + 'No results match:' => 'Nema rezultata:', + 'Currency' => 'Valuta', + 'Files' => 'Fajlovi', + 'Images' => 'Slike', + 'Private project' => 'Privatni projekat', + 'AUD - Australian Dollar' => 'AUD - Australijski dolar', + 'CAD - Canadian Dollar' => 'CAD - Kanadski dolar', + 'CHF - Swiss Francs' => 'CHF - Švicarski franak', + 'Custom Stylesheet' => 'Prilagođeni stil', + 'download' => 'preuzmi', + 'EUR - Euro' => 'EUR - Evro', + 'GBP - British Pound' => 'GBP - Britanska funta', + 'INR - Indian Rupee' => 'INR - Indijski rupi', + 'JPY - Japanese Yen' => 'JPY - Japanski jen', + 'NZD - New Zealand Dollar' => 'NZD - Novozelandski dolar', + 'RSD - Serbian dinar' => 'RSD - Srpski dinar', + 'USD - US Dollar' => 'USD - Američki dolar', + 'Destination column' => 'Odredišna kolona', + 'Move the task to another column when assigned to a user' => 'Premjesti zadatak u neku drugu kolonu kada se dodijeli izvršiocu', + 'Move the task to another column when assignee is cleared' => 'Premjesti zadatak u neku drugu kolonu kada se ukloni izvršilac', + 'Source column' => 'Izvorna kolona', + 'Transitions' => 'Prelaz', + 'Executer' => 'Izvršilac', + 'Time spent in the column' => 'Vrijeme provedeno u koloni', + 'Task transitions' => 'Prelazi zadatka', + 'Task transitions export' => 'Izvezi prelaze zadatka', + 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => 'Ovaj izvještaj sadržava sve kolone premještanja za svaki zadatak s datumom, te korisnikom i utrošenim vremenom za svaki premještaj.', + 'Currency rates' => 'Stopa valute', + 'Rate' => 'Stopa', + 'Change reference currency' => 'Promijeni referencu valute', + 'Add a new currency rate' => 'Dodaj novu stopu valute', + 'Reference currency' => 'Referenca valute', + 'The currency rate have been added successfully.' => 'Stopa valute je uspješno dodana.', + 'Unable to add this currency rate.' => 'Nemoguće dodati stopu valute.', + 'Webhook URL' => 'Webhook URL', + '%s remove the assignee of the task %s' => '%s je uklonio izvršioca zadatka %s', + 'Enable Gravatar images' => 'Omogući Gravatar slike', + 'Information' => 'Informacije', + 'Check two factor authentication code' => 'Provjera faktor-dva autentifikacionog koda', + 'The two factor authentication code is not valid.' => 'Faktor-dva autentifikacionog koda nije validan.', + 'The two factor authentication code is valid.' => 'Faktor-dva autentifikacionog koda je validan.', + 'Code' => 'Kod', + 'Two factor authentication' => 'Faktor-dva autentifikacija', + 'Enable/disable two factor authentication' => 'Omogući/onemogući faktor-dva autentifikaciju', + 'This QR code contains the key URI: ' => 'Ovaj QR kod sadržava ključni URL: ', + 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => 'Sačuvaj tajni klju u svom TOTP softveru (npr. Google Authenticator or FreeOTP)', + 'Check my code' => 'Provjeri moj kod', + 'Secret key: ' => 'Tajni ključ: ', + 'Test your device' => 'Testiraj svoj uređaj', + 'Assign a color when the task is moved to a specific column' => 'Dodijeli boju kada je zadatak pomjeren u odabranu kolonu', + '%s via Kanboard' => '%s uz pomoć Kanboard-a', + 'uploaded by: %s' => 'dodano od strane: %s', + 'uploaded on: %s' => 'dodano na: %s', + 'size: %s' => 'veličina: %s', + 'Burndown chart for "%s"' => 'Grafikon izgaranja za "%s"', + 'Burndown chart' => 'Grafikon izgaranja', + 'This chart show the task complexity over the time (Work Remaining).' => 'Ovaj grafikon pokazuje kompleksnost zadatka u vremenu (Preostalo vremena)', + 'Screenshot taken %s' => 'Slika ekrana uzeta %s', + 'Add a screenshot' => 'Dodaj sliku ekrana', + 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => 'Uzmi sliku ekrana i pritisni CTRL+V ili ⌘+V da zalijepiš ovdje.', + 'Screenshot uploaded successfully.' => 'Slika ekrana uspješno dodana.', + 'SEK - Swedish Krona' => 'SEK - Švedska kruna', + 'The project identifier is an optional alphanumeric code used to identify your project.' => 'Identifikator projekta je opcionalni alfanumerički kod koji se koristi za identifikaciju projekta.', + 'Identifier' => 'Identifikator', + 'Disable two factor authentication' => 'Onemogući faktor-dva autentifikaciju', + 'Do you really want to disable the two factor authentication for this user: "%s"?' => 'Da li zaista želiš onemogućiti faktor-dva autentifikaciju: %s?', + 'Edit link' => 'Uredi vezu', + 'Start to type task title...' => 'Počni pisati naslov zadatka...', + 'A task cannot be linked to itself' => 'Zadatak ne može biti povezan sa samim sobom', + 'The exact same link already exists' => 'Ista veza već postoji', + 'Recurrent task is scheduled to be generated' => 'Ponavljajući zadatak je pripremljen da bude kreiran', + 'Recurring information' => 'Informacije o ponavljanju', + 'Score' => 'Uspjeh', + 'The identifier must be unique' => 'Identifikator mora biti jedinstven', + 'This linked task id doesn\'t exists' => 'Povezani ID zadatka ne postoji', + 'This value must be alphanumeric' => 'Ova vrijednost mora biti alfanumerička', + 'Edit recurrence' => 'Uredi ponavljanje', + 'Generate recurrent task' => 'Napravi ponavljajući zadatak', + 'Trigger to generate recurrent task' => 'Okidač koji pravi ponavljajući zadatak', + 'Factor to calculate new due date' => 'Faktor za računanje novog datuma završetka', + 'Timeframe to calculate new due date' => 'Vremenski okvir za računanje novog datuma završetka', + 'Base date to calculate new due date' => 'Početni datum za računanje novog datuma završetka', + 'Action date' => 'Datum akcije', + 'Base date to calculate new due date: ' => 'Početni datum za računanje novog datuma završetka: ', + 'This task has created this child task: ' => 'Ovaj zadatak će napraviti zadatak-dijete: ', + 'Day(s)' => 'Dan(i)', + 'Existing due date' => 'Postojeći datum završetka', + 'Factor to calculate new due date: ' => 'Faktor za računanje novog datuma završetka: ', + 'Month(s)' => 'Mjesec(i)', + 'Recurrence' => 'Referenca', + 'This task has been created by: ' => 'Ovaj zadatak će napravio: ', + 'Recurrent task has been generated:' => 'Ponavljajući zadatak je napravio:', + 'Timeframe to calculate new due date: ' => 'Vremenski okvir za računanje novog datuma završetka:', + 'Trigger to generate recurrent task: ' => 'Okidač za pravljenje ponavljajućeg zadatka', + 'When task is closed' => 'Kada je zadatak zatvoren', + 'When task is moved from first column' => 'Kada je zadatak premješten iz prve kolone', + 'When task is moved to last column' => 'Kada je zadatak premješten u posljednju kolonu', + 'Year(s)' => 'Godina/e', + 'Calendar settings' => 'Postavke kalendara', + 'Project calendar view' => 'Pregled kalendara projekta', + 'Project settings' => 'Postavke projekta', + 'Show subtasks based on the time tracking' => 'Prikaži pod-zadatke bazirano na vremenskom praćenju', + 'Show tasks based on the creation date' => 'Prikaži zadatke bazirano na vremenu otvaranja', + 'Show tasks based on the start date' => 'Prikaži zadatke bazirano na vremenu početka rada', + 'Subtasks time tracking' => 'Vremensko praćenje pod-zadataka', + 'User calendar view' => 'Pregled korisničkog kalendara', + 'Automatically update the start date' => 'Automatski ažuriraj početni datum', + 'iCal feed' => 'iCal kanal', + 'Preferences' => 'Postavke', + 'Security' => 'Sigurnost', + 'Two factor authentication disabled' => 'Faktor-dva autentifikacija onemogućena', + 'Two factor authentication enabled' => 'Faktor-dva autentifikacija omogućena', + 'Unable to update this user.' => 'Nemoguće ažurirati ovog korisnika', + 'There is no user management for private projects.' => 'Nema mehanizma za upravljanje korisnicima kod privatnih projekata.', + 'User that will receive the email' => 'Korisnik će dobiti email', + 'Email subject' => 'Predmet email-a', + 'Date' => 'Datum', + 'By @%s on Bitbucket' => 'Od @%s na Bitbucket', + 'Bitbucket Issue' => 'Bitbucket problem', + 'Commit made by @%s on Bitbucket' => 'Commit-ao @%s na Bitbucket', + 'Commit made by @%s on Github' => 'Commit-ao @%s na Github', + 'By @%s on Github' => '@%s na Github', + 'Commit made by @%s on Gitlab' => 'Commit-ao @%s na Gitlab', + 'Add a comment log when moving the task between columns' => 'Dodaj komentar u dnevnik kada se pomjeri zadatak između kolona', + 'Move the task to another column when the category is changed' => 'Pomjeri zadatak u drugu kolonu kada je kategorija promijenjena', + 'Send a task by email to someone' => 'Pošalji zadatak nekome emailom', + 'Reopen a task' => 'Ponovo otvori zadatak', + 'Bitbucket issue opened' => 'Bitbucket: otvoren problem', + 'Bitbucket issue closed' => 'Bitbucket: zatvoren problem', + 'Bitbucket issue reopened' => 'Bitbucket: problem ponovo otvoren', + 'Bitbucket issue assignee change' => 'Bitbucket: promijenjen izvršilac problema', + 'Bitbucket issue comment created' => 'Bitbucket: dodan komentar na problemu', + 'Column change' => 'Promijena kolone', + 'Position change' => 'Promjena pozicije', + 'Swimlane change' => 'Promjena swimline trake', + 'Assignee change' => 'Promijenjen izvršilac', + '[%s] Overdue tasks' => '[%s] Zaostali zadaci', + 'Notification' => 'Obavještenja', + '%s moved the task #%d to the first swimlane' => '%s je premjestio zadatak #%d u prvu swimline traku', + '%s moved the task #%d to the swimlane "%s"' => '%s je premjestio zadatak #%d u swimline traku "%s"', + 'Swimlane' => 'Swimline traka', + 'Gravatar' => 'Gravatar', + '%s moved the task %s to the first swimlane' => '%s je premjestio zadatak %s u prvi swimline traku', + '%s moved the task %s to the swimlane "%s"' => '%s je premjestio zadatak %s u swimline traku "%s"', + 'This report contains all subtasks information for the given date range.' => 'Ovaj izvještaj sadržava sve informacije o pod-zadacima za dati period', + 'This report contains all tasks information for the given date range.' => 'Ovaj izvještaj sadržava sve informacije o zadacima u datom periodu', + 'Project activities for %s' => 'Aktivnosti projekta za %s', + 'view the board on Kanboard' => 'pregled ploče na Kanboard-u', + 'The task have been moved to the first swimlane' => 'Zadatak je premješten u prvu swimline traku', + 'The task have been moved to another swimlane:' => 'Zadatak je premješten u drugu swimline traku', + 'Overdue tasks for the project "%s"' => 'Zadaci u kašnjenju za projekat "%s"', + 'New title: %s' => 'Novi naslov: %s', + 'The task is not assigned anymore' => 'Zadatak nema više izvršioca', + 'New assignee: %s' => 'Novi izvršilac: %s', + 'There is no category now' => 'Sada nema kategorije', + 'New category: %s' => 'Nova kategorija: %s', + 'New color: %s' => 'Nova boja: %s', + 'New complexity: %d' => 'Nova složenost: %d', + 'The due date have been removed' => 'Datum završetka je ukloljen', + 'There is no description anymore' => 'Nema više opisa', + 'Recurrence settings have been modified' => 'Promijenjene postavke za ponavljajuće zadatke', + 'Time spent changed: %sh' => 'Utrošeno vrijeme je promijenjeno: %sh', + 'Time estimated changed: %sh' => 'Očekivano vrijeme je promijenjeno: %sh', + 'The field "%s" have been updated' => 'Polje "%s" je ažurirano', + 'The description have been modified' => 'Promijenjen opis', + 'Do you really want to close the task "%s" as well as all subtasks?' => 'Da li zaista želiš zatvoriti zadatak "%s" kao i sve pod-zadatke?', + 'Swimlane: %s' => 'Swimline traka: %s', + 'I want to receive notifications for:' => 'Želim dobijati obavještenja za:', + 'All tasks' => 'Sve zadatke', + 'Only for tasks assigned to me' => 'Samo za zadatke na kojima sam izvršilac', + 'Only for tasks created by me' => 'Samo za zadatke koje sam ja napravio', + 'Only for tasks created by me and assigned to me' => 'Samo za zadatke koje sam ja napravio i na kojima sam izvršilac', + '%A' => '%A', + '%b %e, %Y, %k:%M %p' => '%b %e, %Y, %k:%M %p', + 'New due date: %B %e, %Y' => 'Novi datum završetka: %B %e, %Y', + 'Start date changed: %B %e, %Y' => 'Početni datum promijenjen: %B %e, %Y', + '%k:%M %p' => '%k:%M %p', + '%%Y-%%m-%%d' => '%%Y-%%m-%%d', + 'Total for all columns' => 'Ukupno za sve kolone', + 'You need at least 2 days of data to show the chart.' => 'Da bi se prikazao ovaj grafik potrebni su podaci iz najmanje posljednja dva dana.', + '<15m' => '<15m', + '<30m' => '<30m', + 'Stop timer' => 'Zaustavi tajmer', + 'Start timer' => 'Pokreni tajmer', + 'Add project member' => 'Dodaj člana projekta', + 'Enable notifications' => 'Omogući obavještenja', + 'My activity stream' => 'Tok mojih aktivnosti', + 'My calendar' => 'Moj kalendar', + 'Search tasks' => 'Pretraga zadataka', + 'Back to the calendar' => 'Vrati na kalendar', + 'Filters' => 'Filteri', + 'Reset filters' => 'Vrati filtere na početno', + 'My tasks due tomorrow' => 'Moji zadaci koje treba završiti sutra', + 'Tasks due today' => 'Zadaci koje treba završiti danas', + 'Tasks due tomorrow' => 'Zadaci koje treba završiti sutra', + 'Tasks due yesterday' => 'Zadaci koje je trebalo završiti jučer', + 'Closed tasks' => 'Zatvoreni zadaci', + 'Open tasks' => 'Otvoreni zadaci', + 'Not assigned' => 'Bez izvršioca', + 'View advanced search syntax' => 'Vidi naprednu sintaksu pretrage', + 'Overview' => 'Opšti pregled', + '%b %e %Y' => '%b %e %Y', + 'Board/Calendar/List view' => 'Pregle Table/Kalendara/Liste', + 'Switch to the board view' => 'Promijeni da vidim tablu', + 'Switch to the calendar view' => 'Promijeni da vidim kalendar', + 'Switch to the list view' => 'Promijeni da vidim listu', + 'Go to the search/filter box' => 'Idi na kutiju s pretragom/filterima', + 'There is no activity yet.' => 'Još uvijek nema aktivnosti.', + 'No tasks found.' => 'Zadaci nisu pronađeni.', + 'Keyboard shortcut: "%s"' => 'Prečica tastature: "%s"', + 'List' => 'Lista', + 'Filter' => 'Filter', + 'Advanced search' => 'Napredna pretraga', + 'Example of query: ' => 'Primjer za upit', + 'Search by project: ' => 'Pretraga po projektu', + 'Search by column: ' => 'Pretraga po koloni', + 'Search by assignee: ' => 'Pretraga po izvršiocu', + 'Search by color: ' => 'Pretraga po boji', + 'Search by category: ' => 'Pretraga po kategoriji', + 'Search by description: ' => 'Pretraga po opisu', + 'Search by due date: ' => 'Pretraga po datumu završetka', + 'Lead and Cycle time for "%s"' => 'Vrijeme upravljanje i vremenski ciklus za "%s"', + 'Average time spent into each column for "%s"' => 'Prosjek utrošenog vremena u svakoj koloni za "%s"', + 'Average time spent into each column' => 'Prosjek utrošenog vrmena u svakoj koloni', + 'Average time spent' => 'Prosjek utrošenog vremena', + 'This chart show the average time spent into each column for the last %d tasks.' => 'Ovaj grafik pokazuje prosjek utrošenog vremena u svakoj koloni za posljednjih %d zadataka.', + 'Average Lead and Cycle time' => 'Prosjek vremena upravljanja i vremenskog ciklusa', + 'Average lead time: ' => 'Prosjek vremena upravljanja', + 'Average cycle time: ' => 'Prosjek vremenskog ciklusa', + 'Cycle Time' => 'Vremenski ciklus', + 'Lead Time' => 'Vrijeme upravljanja', + 'This chart show the average lead and cycle time for the last %d tasks over the time.' => 'Ovaj grafik pokazuje prosjek vremena vođenja i vremenskog ciklusa za posljednjih %d zadataka tokom vremena.', + 'Average time into each column' => 'Prosječno vrijeme u svakoj koloni', + 'Lead and cycle time' => 'Vrijeme vođenja i vremenski ciklus', + 'Google Authentication' => 'Google autentifikacija', + 'Help on Google authentication' => 'Pomoć na Google autentifikacija', + 'Github Authentication' => 'Github autentifikacija', + 'Help on Github authentication' => 'Pomoć na Github autentifikacija', + 'Lead time: ' => 'Vrijeme vođenja: ', + 'Cycle time: ' => 'Vremenski ciklus: ', + 'Time spent into each column' => 'Utrošeno vrijeme u svakoj koloni', + 'The lead time is the duration between the task creation and the completion.' => 'Vrijeme vođenja je vrijeme koje je proteklo između otvaranja i zatvaranja zadatka.', + 'The cycle time is the duration between the start date and the completion.' => 'Vremenski ciklus je vrijeme koje je proteklo između početka i završetka rada na zadatku.', + 'If the task is not closed the current time is used instead of the completion date.' => 'Ako zadatak nije zatvoren trenutno vrijeme je iskorišteno umjesto datuma završetka.', + 'Set automatically the start date' => 'Automatski postavi početno vrijeme', + 'Edit Authentication' => 'Uredi autentifikaciju', + 'Google Id' => 'Google Id', + 'Github Id' => 'Github Id', + 'Remote user' => 'Vanjski korisnik', + 'Remote users do not store their password in Kanboard database, examples: LDAP, Google and Github accounts.' => 'Vanjski korisnik ne čuva šifru u Kanboard bazi, npr: LDAP, Google i Github korisnički računi.', + 'If you check the box "Disallow login form", credentials entered in the login form will be ignored.' => 'Ako ste označili kvadratić "Zabrani prijavnu formu", unos pristupnih podataka u prijavnoj formi će biti ignorisan.', + 'By @%s on Gitlab' => 'Od @%s s Gitlab-om', + 'Gitlab issue comment created' => 'Gitlab: dodan komentar za problem', + 'New remote user' => 'Novi vanjski korisnik', + 'New local user' => 'Novi lokalni korisnik', + 'Default task color' => 'Podrazumijevana boja zadatka', + 'Hide sidebar' => 'Sakri bočnu traku', + 'Expand sidebar' => 'Proširi bočnu traku', + 'This feature does not work with all browsers.' => 'Ovaj funkcionalnost ne radi na svim internet pretraživačima.', + 'There is no destination project available.' => 'Nema definisanog odredišta za projekat.', + 'Trigger automatically subtask time tracking' => 'Okidač za automatsko vremensko praćenje za pod-zadatke', + 'Include closed tasks in the cumulative flow diagram' => 'Obuhvati zatvorene zadatke u kumulativnom dijagramu toka', + 'Current swimlane: %s' => 'Trenutna swimline traka: %s', + 'Current column: %s' => 'Trenutna kolona: %s', + 'Current category: %s' => 'Trenutna kategorija: %s', + 'no category' => 'bez kategorije', + 'Current assignee: %s' => 'Trenutni izvršilac: %s', + 'not assigned' => 'bez ivršioca', + 'Author:' => 'Autor:', + 'contributors' => 'saradnici', + 'License:' => 'Licenca:', + 'License' => 'Licenca', + 'Project Administrator' => 'Administrator projekta', + 'Enter the text below' => 'Unesi tekst ispod', + 'Gantt chart for %s' => 'Gantogram za %s', + 'Sort by position' => 'Sortiraj po poziciji', + 'Sort by date' => 'Sortiraj po datumu', + 'Add task' => 'Dodaj zadatak', + 'Start date:' => 'Početno vrijeme:', + 'Due date:' => 'Vrijeme do kada treba završiti:', + 'There is no start date or due date for this task.' => 'Nema početnog datuma ili datuma do kada treba završiti ovaj zadatak.', + 'Moving or resizing a task will change the start and due date of the task.' => 'Premještanje ili promjena veličine zadatka će promijeniti datum početka i datum do kada treba završiti zadatak.', + 'There is no task in your project.' => 'Nema zadataka u tvom projektu.', + 'Gantt chart' => 'Gantogram', + 'People who are project managers' => 'Osobe koji su menadžeri projekta', + 'People who are project members' => 'Osobe koje su članovi projekta', + 'NOK - Norwegian Krone' => 'NOK - Norveška kruna', + 'Show this column' => 'Prikaži ovu kolonu', + 'Hide this column' => 'Sakrij ovu kolonu', + 'open file' => 'otvori fajl', + 'End date' => 'Datum završetka', + 'Users overview' => 'Opšti pregled korisnika', + 'Managers' => 'Menadžeri', + 'Members' => 'Članovi', + 'Shared project' => 'Dijeljeni projekti', + 'Project managers' => 'Menadžeri projekta', + 'Project members' => 'Članovi projekta', + 'Gantt chart for all projects' => 'Gantogram za sve projekte', + 'Projects list' => 'Lista projekata', + 'Gantt chart for this project' => 'Gantogram za ovaj projekat', + 'Project board' => 'Tabla projekta', + 'End date:' => 'Datum završetka:', + 'There is no start date or end date for this project.' => 'Nema početnog ili krajnjeg datuma za ovaj projekat.', + 'Projects Gantt chart' => 'Gantogram projekata', + 'Start date: %s' => 'Početni datum: %s', + 'End date: %s' => 'Datum završetka: %s', + 'Link type' => 'Tip veze', + 'Change task color when using a specific task link' => 'Promijeni boju zadatka kada se koristi određena veza na zadatku', + 'Task link creation or modification' => 'Veza na zadatku je napravljena ili izmijenjena', + 'Login with my Gitlab Account' => 'Prijava s mojim Gitlab korisničkim računom', + 'Milestone' => 'Prekretnica', + 'Gitlab Authentication' => 'Gitlab autentifikacija', + 'Help on Gitlab authentication' => 'Pomoć na Gitlab autentifikacija', + 'Gitlab Id' => 'Gitlab Id', + 'Gitlab Account' => 'Gitlab korisnički račun', + 'Link my Gitlab Account' => 'Veza s mojim Gitlab korisničkim računom', + 'Unlink my Gitlab Account' => 'Prekini vezu s mojim Gitlab korisničkim računom', + 'Documentation: %s' => 'Dokumentacija: %s', + 'Switch to the Gantt chart view' => 'Promijeni u gantogram pregled', + 'Reset the search/filter box' => 'Vrati na početno pretragu/filtere', + 'Documentation' => 'Dokumentacija', + 'Table of contents' => 'Sadržaj', + 'Gantt' => 'Gantogram', + 'Help with project permissions' => 'Pomoć s pravima nad projektom', + 'Author' => 'Autor', + 'Version' => 'Verzija', + 'Plugins' => 'Dodaci', + 'There is no plugin loaded.' => 'Nema učitanih dodataka.', + 'Set maximum column height' => 'Postavi maksimalnu visinu kolone', + 'Remove maximum column height' => 'Ukloni maksimalnu visinu kolone', + 'My notifications' => 'Moja obavještenja', + 'Custom filters' => 'Prilagođeni filteri', + 'Your custom filter have been created successfully.' => 'Tvoj prilagođeni filter je uspješno napravljen.', + 'Unable to create your custom filter.' => 'Nemoguće napraviti prilagođeni filter.', + 'Custom filter removed successfully.' => 'Prilagođeni filter uspješno uklonjen.', + 'Unable to remove this custom filter.' => 'Nemoguće ukloniti prilagođeni filter.', + 'Edit custom filter' => 'Uredi prilagođeni filter', + 'Your custom filter have been updated successfully.' => 'Prilagođeni filter uspješno ažuriran.', + 'Unable to update custom filter.' => 'Nemoguće ažurirati prilagođeni filter', + 'Web' => 'Web', + 'New attachment on task #%d: %s' => 'Novi priložak na zadatku #%d: %s', + 'New comment on task #%d' => 'Novi komentar na zadatku #%d', + 'Comment updated on task #%d' => 'Ažuriran komentar na zadatku #%d', + 'New subtask on task #%d' => 'Novi pod-zadatak na zadatku #%d', + 'Subtask updated on task #%d' => 'Pod-zadatak ažuriran na zadatku #%d', + 'New task #%d: %s' => 'Novi zadatak #%d: %s', + 'Task updated #%d' => 'Zadatak ažuriran #%d', + 'Task #%d closed' => 'Zadatak #%d zatvoren', + 'Task #%d opened' => 'Zadatak #%d otvoren', + 'Column changed for task #%d' => 'Promijenjena kolona za zadatak #%d', + 'New position for task #%d' => 'Nova pozicija za zadatak #%d', + 'Swimlane changed for task #%d' => 'Swimline traka promijenjena za zadatak #%d', + 'Assignee changed on task #%d' => 'Promijenjen izvršilac na zadatku #%d', + '%d overdue tasks' => '%d zadataka kasni', + 'Task #%d is overdue' => 'Zadatak #%d kasni', + 'No new notifications.' => 'Nema novi obavještenja.', + 'Mark all as read' => 'Označi sve kao pročitano', + 'Mark as read' => 'Označi kao pročitano', + 'Total number of tasks in this column across all swimlanes' => 'Ukupan broj zadataka u ovoj koloni u svim swimline trakama', + 'Collapse swimlane' => 'Skupi swimline trake', + 'Expand swimlane' => 'Proširi swimline trake', + 'Add a new filter' => 'Dodaj novi filter', + 'Share with all project members' => 'Podijeli s svim članovima projekta', + 'Shared' => 'Podijeljeno', + 'Owner' => 'Vlasnik', + 'Unread notifications' => 'Nepročitana obavještenja', + 'My filters' => 'Moji filteri', + 'Notification methods:' => 'Metode obavještenja:', + 'Import tasks from CSV file' => 'Uvezi zadatke putem CSV fajla', + 'Unable to read your file' => 'Nemoguće pročitati fajl', + '%d task(s) have been imported successfully.' => '%d zadataka uspješno uvezeno.', + 'Nothing have been imported!' => 'Ništa nije uvezeno!', + 'Import users from CSV file' => 'Uvezi korisnike putem CSV fajla', + '%d user(s) have been imported successfully.' => '%d korisnika uspješno uvezeno.', + 'Comma' => 'Zarez', + 'Semi-colon' => 'Tačka-zarez', + 'Tab' => 'Tab', + 'Vertical bar' => 'Vertikalna traka', + 'Double Quote' => 'Dvostruki navodnici', + 'Single Quote' => 'Jednostruki navodnici', + '%s attached a file to the task #%d' => '%s file je prirodan zadatku #%d', + 'There is no column or swimlane activated in your project!' => 'Nema kolone ili swimline trake aktivirane za ovaj projekat!', + 'Append filter (instead of replacement)' => 'Dodaj filter (umjesto zamjene postojećeg)', + 'Append/Replace' => 'Dodaj/Zamijeni', + 'Append' => 'Dodaj', + 'Replace' => 'Zamijeni', + 'There is no notification method registered.' => 'Nema registrovanih metoda za obavještenja', + 'Import' => 'Uvoz', + 'change sorting' => 'Promijeni sortiranje', + 'Tasks Importation' => 'Uvoz zadataka', + 'Delimiter' => 'Djelilac', + 'Enclosure' => 'Prilog', + 'CSV File' => 'CSV File', + 'Instructions' => 'Uputstva', + 'Your file must use the predefined CSV format' => 'File mora biti predefinisani CSV format', + 'Your file must be encoded in UTF-8' => 'File mora biti u UTF-8 kodu', + 'The first row must be the header' => 'Prvi red mora biti zaglavlje', + 'Duplicates are not verified for you' => 'Dipliciranje nisu potvrđena', + 'The due date must use the ISO format: YYYY-MM-DD' => 'Datum do kog se treba izvršiti mora biti u ISO formatu: GGGG-MM-DD', + 'Download CSV template' => 'Preuzmi CSV šablon', + 'No external integration registered.' => 'Nema registrovanih vanjskih integracija.', + 'Duplicates are not imported' => 'Duplikati nisu uvezeni', + 'Usernames must be lowercase and unique' => 'Korisničko ime mora biti malim slovima i jedinstveno', + 'Passwords will be encrypted if present' => 'Šifra će biti kriptovana', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + 'BAM - Konvertibile Mark' => 'BAM - Konvertibilna marka', + // 'Assignee Username' => '', + // 'Assignee Name' => '', +); diff --git a/sources/app/Locale/cs_CZ/translations.php b/sources/app/Locale/cs_CZ/translations.php index 2631ab2..5d6af0b 100644 --- a/sources/app/Locale/cs_CZ/translations.php +++ b/sources/app/Locale/cs_CZ/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'ID je vyžadováno', 'The project id is required' => 'ID projektu je vyžadováno', 'The project name is required' => 'Jméno projektu je vyžadováno', - 'This project must be unique' => 'Jméno projektu musí být jedinečné', 'The title is required' => 'Nadpis je vyžadován', 'Settings saved successfully.' => 'Nastavení bylo úspěšně uloženo', 'Unable to save your settings.' => 'Vaše nastavení nelze uložit.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/da_DK/translations.php b/sources/app/Locale/da_DK/translations.php index 6d221a7..a5ac1d3 100644 --- a/sources/app/Locale/da_DK/translations.php +++ b/sources/app/Locale/da_DK/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'Id\'et er krævet', 'The project id is required' => 'Projektets id er krævet', 'The project name is required' => 'Projektets navn er krævet', - 'This project must be unique' => 'Projektets navn skal være unikt', 'The title is required' => 'Titel er krævet', 'Settings saved successfully.' => 'Indstillinger gemt.', 'Unable to save your settings.' => 'Indstillinger kunne ikke gemmes.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/de_DE/translations.php b/sources/app/Locale/de_DE/translations.php index e566c0f..13fa754 100644 --- a/sources/app/Locale/de_DE/translations.php +++ b/sources/app/Locale/de_DE/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'Die ID ist anzugeben', 'The project id is required' => 'Die Projekt ID ist anzugeben', 'The project name is required' => 'Der Projektname ist anzugeben', - 'This project must be unique' => 'Der Projektname muss eindeutig sein', 'The title is required' => 'Der Titel ist anzugeben', 'Settings saved successfully.' => 'Einstellungen erfolgreich gespeichert.', 'Unable to save your settings.' => 'Speichern der Einstellungen nicht möglich.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/es_ES/translations.php b/sources/app/Locale/es_ES/translations.php index 4159da2..02c6961 100644 --- a/sources/app/Locale/es_ES/translations.php +++ b/sources/app/Locale/es_ES/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'El identificador es obligatorio', 'The project id is required' => 'El identificador del proyecto es obligatorio', 'The project name is required' => 'El nombre del proyecto es obligatorio', - 'This project must be unique' => 'El nombre del proyecto debe ser único', 'The title is required' => 'El título es obligatorio', 'Settings saved successfully.' => 'Parámetros guardados correctamente.', 'Unable to save your settings.' => 'No se pueden guardar sus parámetros.', @@ -984,84 +983,89 @@ return array( 'Table of contents' => 'Tabla de contenido', 'Gantt' => 'Gantt', 'Help with project permissions' => 'Ayuda con permisos del proyecto', - // 'Author' => '', - // 'Version' => '', - // 'Plugins' => '', - // 'There is no plugin loaded.' => '', - // 'Set maximum column height' => '', - // 'Remove maximum column height' => '', - // 'My notifications' => '', - // 'Custom filters' => '', - // 'Your custom filter have been created successfully.' => '', - // 'Unable to create your custom filter.' => '', - // 'Custom filter removed successfully.' => '', - // 'Unable to remove this custom filter.' => '', - // 'Edit custom filter' => '', - // 'Your custom filter have been updated successfully.' => '', - // 'Unable to update custom filter.' => '', - // 'Web' => '', - // 'New attachment on task #%d: %s' => '', - // 'New comment on task #%d' => '', - // 'Comment updated on task #%d' => '', - // 'New subtask on task #%d' => '', - // 'Subtask updated on task #%d' => '', - // 'New task #%d: %s' => '', - // 'Task updated #%d' => '', - // 'Task #%d closed' => '', - // 'Task #%d opened' => '', - // 'Column changed for task #%d' => '', - // 'New position for task #%d' => '', - // 'Swimlane changed for task #%d' => '', - // 'Assignee changed on task #%d' => '', - // '%d overdue tasks' => '', - // 'Task #%d is overdue' => '', - // 'No new notifications.' => '', - // 'Mark all as read' => '', - // 'Mark as read' => '', - // 'Total number of tasks in this column across all swimlanes' => '', - // 'Collapse swimlane' => '', - // 'Expand swimlane' => '', - // 'Add a new filter' => '', - // 'Share with all project members' => '', - // 'Shared' => '', - // 'Owner' => '', - // 'Unread notifications' => '', - // 'My filters' => '', - // 'Notification methods:' => '', - // 'Import tasks from CSV file' => '', - // 'Unable to read your file' => '', - // '%d task(s) have been imported successfully.' => '', - // 'Nothing have been imported!' => '', - // 'Import users from CSV file' => '', - // '%d user(s) have been imported successfully.' => '', - // 'Comma' => '', - // 'Semi-colon' => '', - // 'Tab' => '', - // 'Vertical bar' => '', - // 'Double Quote' => '', - // 'Single Quote' => '', - // '%s attached a file to the task #%d' => '', - // 'There is no column or swimlane activated in your project!' => '', - // 'Append filter (instead of replacement)' => '', - // 'Append/Replace' => '', - // 'Append' => '', - // 'Replace' => '', - // 'There is no notification method registered.' => '', - // 'Import' => '', - // 'change sorting' => '', - // 'Tasks Importation' => '', - // 'Delimiter' => '', + 'Author' => 'Autor', + 'Version' => 'Versión', + 'Plugins' => 'Plugins', + 'There is no plugin loaded.' => 'No hay ningún plugin cargado', + 'Set maximum column height' => 'Establecer altura máxima de la columna', + 'Remove maximum column height' => 'Eliminar altura máxima de la columna', + 'My notifications' => 'Mis notificaciones', + 'Custom filters' => 'Filtros personalizados', + 'Your custom filter have been created successfully.' => 'Tus filtros personalizados han sido creados exitosamente', + 'Unable to create your custom filter.' => 'No se ha podido crear tu filtro personalizado', + 'Custom filter removed successfully.' => 'Filtro personalizado ha sido eliminado exitosamente', + 'Unable to remove this custom filter.' => 'No se ha podido eliminar tu filtro personalizado', + 'Edit custom filter' => 'Modificar filtro personalizado', + 'Your custom filter have been updated successfully.' => 'Tu filtro personalizado ha sido actualizado exitosamente', + 'Unable to update custom filter.' => 'No se ha podido actualizar tu filtro personalizado', + 'Web' => 'Web', + 'New attachment on task #%d: %s' => 'Nuevo adjunto en la tarea #%d: %s', + 'New comment on task #%d' => 'Nuevo comentario en la tarea #%d', + 'Comment updated on task #%d' => 'Comentario actualizado en la tarea #%d', + 'New subtask on task #%d' => 'Nueva subtarea en la tarea #%d', + 'Subtask updated on task #%d' => 'La subtarea en la tarea #%d ha sido actualizada', + 'New task #%d: %s' => 'Nueva tarea #%d: %s', + 'Task updated #%d' => 'Tarea actualizada #%d', + 'Task #%d closed' => 'Tarea #%d ha sido cerrada', + 'Task #%d opened' => 'Tarea #%d ha sido abierta', + 'Column changed for task #%d' => 'Columna para tarea #%d ha sido cambiada', + 'New position for task #%d' => 'Nueva posición para tarea #%d', + 'Swimlane changed for task #%d' => 'Se cambió el swimlane de la tarea #%d', + 'Assignee changed on task #%d' => 'Se cambió el asignado de la tarea #%d', + '%d overdue tasks' => '%d tareas atrasadas', + 'Task #%d is overdue' => 'La tarea #%d está atrasada', + 'No new notifications.' => 'No hay nuevas notificaciones', + 'Mark all as read' => 'Marcar todo como leído', + 'Mark as read' => 'Marcar como leído', + 'Total number of tasks in this column across all swimlanes' => 'Número total de tareas en esta columna por todas las swimlanes', + 'Collapse swimlane' => 'Contraer swimlane', + 'Expand swimlane' => 'Ampliar swimlane', + 'Add a new filter' => 'Añadir nuevo filtro', + 'Share with all project members' => 'Compartir con todos los miembros del proyecto', + 'Shared' => 'Compartido', + 'Owner' => 'Dueño', + 'Unread notifications' => 'Notificaciones sin leer', + 'My filters' => 'Mis filtros', + 'Notification methods:' => 'Métodos de notificación', + 'Import tasks from CSV file' => 'Importar tareas desde archivo CSV', + 'Unable to read your file' => 'No es posible leer el archivo', + '%d task(s) have been imported successfully.' => '%d tarea(s) han sido importadas exitosamente', + 'Nothing have been imported!' => 'No se ha importado nada!', + 'Import users from CSV file' => 'Importar usuarios desde archivo CSV', + '%d user(s) have been imported successfully.' => '%d usuario(s) se han importado exitosamente', + 'Comma' => 'Coma', + 'Semi-colon' => 'Punto y coma', + 'Tab' => 'Tabulación', + 'Vertical bar' => 'Pleca', + 'Double Quote' => 'Comilla doble', + 'Single Quote' => 'Comilla sencilla', + '%s attached a file to the task #%d' => '%s adjuntó un archivo a la tarea #%d', + 'There is no column or swimlane activated in your project!' => 'No hay ninguna columna o swimlane activada en su proyecto!', + 'Append filter (instead of replacement)' => 'Añadir filtro (en vez de reemplazar)', + 'Append/Replace' => 'Añadir/Reemplazar', + 'Append' => 'Añadir', + 'Replace' => 'Reemplazar', + 'There is no notification method registered.' => 'No hay método de notificación registrado', + 'Import' => 'Importar', + 'change sorting' => 'Cambiar orden', + 'Tasks Importation' => 'Importación de tareas', + 'Delimiter' => 'Delimitador', // 'Enclosure' => '', - // 'CSV File' => '', - // 'Instructions' => '', - // 'Your file must use the predefined CSV format' => '', - // 'Your file must be encoded in UTF-8' => '', - // 'The first row must be the header' => '', - // 'Duplicates are not verified for you' => '', - // 'The due date must use the ISO format: YYYY-MM-DD' => '', - // 'Download CSV template' => '', - // 'No external integration registered.' => '', - // 'Duplicates are not imported' => '', - // 'Usernames must be lowercase and unique' => '', - // 'Passwords will be encrypted if present' => '', + 'CSV File' => 'Archivo CSV', + 'Instructions' => 'Indicaciones', + 'Your file must use the predefined CSV format' => 'Su archivo debe utilizar el formato CSV predeterminado', + 'Your file must be encoded in UTF-8' => 'Su archivo debe ser codificado en UTF-8', + 'The first row must be the header' => 'La primera fila debe ser el encabezado', + 'Duplicates are not verified for you' => 'Los duplicados no serán verificados', + 'The due date must use the ISO format: YYYY-MM-DD' => 'La fecha de entrega debe utilizar el formato ISO: AAAA-MM-DD', + 'Download CSV template' => 'Descargar plantilla CSV', + 'No external integration registered.' => 'No se ha registrado integración externa', + 'Duplicates are not imported' => 'Los duplicados no son importados', + 'Usernames must be lowercase and unique' => 'Los nombres de usuario deben ser únicos y contener sólo minúsculas', + 'Passwords will be encrypted if present' => 'Las contraseñas serán cifradas si es que existen', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/fi_FI/translations.php b/sources/app/Locale/fi_FI/translations.php index 998684f..bff0f05 100644 --- a/sources/app/Locale/fi_FI/translations.php +++ b/sources/app/Locale/fi_FI/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'ID vaaditaan', 'The project id is required' => 'Projektin ID on pakollinen', 'The project name is required' => 'Projektin nimi on pakollinen', - 'This project must be unique' => 'Projektin nimi täytyy olla uniikki', 'The title is required' => 'Otsikko vaaditaan', 'Settings saved successfully.' => 'Asetukset tallennettu onnistuneesti.', 'Unable to save your settings.' => 'Asetusten tallentaminen epäonnistui.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/fr_FR/translations.php b/sources/app/Locale/fr_FR/translations.php index e39c766..36ecf2e 100644 --- a/sources/app/Locale/fr_FR/translations.php +++ b/sources/app/Locale/fr_FR/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'L\'identifiant est obligatoire', 'The project id is required' => 'L\'identifiant du projet est obligatoire', 'The project name is required' => 'Le nom du projet est obligatoire', - 'This project must be unique' => 'Le nom du projet doit être unique', 'The title is required' => 'Le titre est obligatoire', 'Settings saved successfully.' => 'Paramètres sauvegardés avec succès.', 'Unable to save your settings.' => 'Impossible de sauvegarder vos réglages.', @@ -1066,4 +1065,10 @@ return array( 'Duplicates are not imported' => 'Les doublons ne sont pas importés', 'Usernames must be lowercase and unique' => 'Les noms d\'utilisateurs doivent être en minuscule et unique', 'Passwords will be encrypted if present' => 'Les mots de passe seront chiffrés si présent', + '%s attached a new file to the task %s' => '%s a attaché un nouveau fichier à la tâche %s', + 'Link type' => 'Type de lien', + 'Assign automatically a category based on a link' => 'Assigner automatiquement une catégorie en fonction d\'un lien', + 'BAM - Konvertibile Mark' => 'BAM - Mark convertible', + 'Assignee Username' => 'Utilisateur assigné', + 'Assignee Name' => 'Nom de l\'assigné', ); diff --git a/sources/app/Locale/hu_HU/translations.php b/sources/app/Locale/hu_HU/translations.php index 59b1d56..1a34a5b 100644 --- a/sources/app/Locale/hu_HU/translations.php +++ b/sources/app/Locale/hu_HU/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'Az ID-t (azonosítót) meg kell adni', 'The project id is required' => 'A projekt ID-t (azonosítót) meg kell adni', 'The project name is required' => 'A projekt nevét meg kell adni', - 'This project must be unique' => 'A projekt nevének egyedinek kell lennie', 'The title is required' => 'A címet meg kell adni', 'Settings saved successfully.' => 'A beállítások sikeresen mentve.', 'Unable to save your settings.' => 'A beállítások mentése sikertelen.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/id_ID/translations.php b/sources/app/Locale/id_ID/translations.php index 8408fc1..3e80025 100644 --- a/sources/app/Locale/id_ID/translations.php +++ b/sources/app/Locale/id_ID/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'Id diperlukan', 'The project id is required' => 'Id proyek diperlukan', 'The project name is required' => 'Nama proyek diperlukan', - 'This project must be unique' => 'Proyek ini harus unik', 'The title is required' => 'Judul diperlukan', 'Settings saved successfully.' => 'Pengaturan berhasil disimpan.', 'Unable to save your settings.' => 'Tidak dapat menyimpan pengaturan anda.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/it_IT/translations.php b/sources/app/Locale/it_IT/translations.php index 08bf722..7fd39d9 100644 --- a/sources/app/Locale/it_IT/translations.php +++ b/sources/app/Locale/it_IT/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'Si richiede l\'identificatore', 'The project id is required' => 'Si richiede l\'identificatore del progetto', 'The project name is required' => 'Si richiede il nome del progetto', - 'This project must be unique' => 'Il nome del progetto deve essere unico', 'The title is required' => 'Si richiede un titolo', 'Settings saved successfully.' => 'Impostazioni salvate correttamente.', 'Unable to save your settings.' => 'Non si possono salvare le impostazioni.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/ja_JP/translations.php b/sources/app/Locale/ja_JP/translations.php index fb40271..8447113 100644 --- a/sources/app/Locale/ja_JP/translations.php +++ b/sources/app/Locale/ja_JP/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'ID が必要です', 'The project id is required' => 'プロジェクト ID が必要です', 'The project name is required' => 'プロジェクト名が必要です', - 'This project must be unique' => 'プロジェクト名がすでに使われています', 'The title is required' => 'タイトルが必要です', 'Settings saved successfully.' => '設定を保存しました。', 'Unable to save your settings.' => '設定の保存に失敗しました。', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/nb_NO/translations.php b/sources/app/Locale/nb_NO/translations.php index 598a15c..b0fa064 100644 --- a/sources/app/Locale/nb_NO/translations.php +++ b/sources/app/Locale/nb_NO/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'Id\'en er pøøkrevet', 'The project id is required' => 'Prosjektet-id er påkrevet', 'The project name is required' => 'Prosjektnavn er påkrevet', - 'This project must be unique' => 'Prosjektnavnet skal være unikt', 'The title is required' => 'Tittel er pårevet', 'Settings saved successfully.' => 'Innstillinger lagret.', 'Unable to save your settings.' => 'Innstillinger kunne ikke lagres.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/nl_NL/translations.php b/sources/app/Locale/nl_NL/translations.php index fd74c97..eaeca45 100644 --- a/sources/app/Locale/nl_NL/translations.php +++ b/sources/app/Locale/nl_NL/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'Het id is verplicht', 'The project id is required' => 'Het project id is verplicht', 'The project name is required' => 'De projectnaam is verplicht', - 'This project must be unique' => 'Dit project moet uniek zijn', 'The title is required' => 'De titel is verplicht', 'Settings saved successfully.' => 'Instellingen succesvol opgeslagen.', 'Unable to save your settings.' => 'Instellingen opslaan niet gelukt.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/pl_PL/translations.php b/sources/app/Locale/pl_PL/translations.php index bcc0c43..7419e13 100644 --- a/sources/app/Locale/pl_PL/translations.php +++ b/sources/app/Locale/pl_PL/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'ID jest wymagane', 'The project id is required' => 'ID projektu jest wymagane', 'The project name is required' => 'Nazwa projektu jest wymagana', - 'This project must be unique' => 'Projekt musi być unikalny', 'The title is required' => 'Tutył jest wymagany', 'Settings saved successfully.' => 'Ustawienia zapisane.', 'Unable to save your settings.' => 'Nie udało się zapisać ustawień.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/pt_BR/translations.php b/sources/app/Locale/pt_BR/translations.php index 6ee5f2d..f03be30 100644 --- a/sources/app/Locale/pt_BR/translations.php +++ b/sources/app/Locale/pt_BR/translations.php @@ -68,7 +68,7 @@ return array( 'Disable' => 'Desativar', 'Enable' => 'Ativar', 'New project' => 'Novo projeto', - 'Do you really want to remove this project: "%s"?' => 'Você realmente deseja remover este projeto: "%s" ?', + 'Do you really want to remove this project: "%s"?' => 'Você realmente deseja remover este projeto: "%s"?', 'Remove project' => 'Remover projeto', 'Edit the board for "%s"' => 'Editar o board para "%s"', 'All projects' => 'Todos os projetos', @@ -124,7 +124,6 @@ return array( 'The id is required' => 'O ID é obrigatório', 'The project id is required' => 'O ID do projeto é obrigatório', 'The project name is required' => 'O nome do projeto é obrigatório', - 'This project must be unique' => 'Este projeto deve ser único', 'The title is required' => 'O título é obrigatório', 'Settings saved successfully.' => 'Configurações salvas com sucesso.', 'Unable to save your settings.' => 'Não é possível salvar suas configurações.', @@ -167,8 +166,8 @@ return array( '%d closed tasks' => '%d tarefas finalizadas', 'No task for this project' => 'Não há tarefa para este projeto', 'Public link' => 'Link público', - 'Change assignee' => 'Mudar a designação', - 'Change assignee for the task "%s"' => 'Modificar designação para a tarefa "%s"', + 'Change assignee' => 'Alterar designação', + 'Change assignee for the task "%s"' => 'Alterar designação para a tarefa "%s"', 'Timezone' => 'Fuso horário', 'Sorry, I didn\'t find this information in my database!' => 'Desculpe, não encontrei esta informação no meu banco de dados!', 'Page not found' => 'Página não encontrada', @@ -217,7 +216,7 @@ return array( 'Remove an automatic action' => 'Remover uma ação automática', 'Assign the task to a specific user' => 'Designar a tarefa para um usuário específico', 'Assign the task to the person who does the action' => 'Designar a tarefa para a pessoa que executa a ação', - 'Duplicate the task to another project' => 'Duplicar a tarefa para um outro projeto', + 'Duplicate the task to another project' => 'Duplicar a tarefa para outro projeto', 'Move a task to another column' => 'Mover a tarefa para outra coluna', 'Task modification' => 'Modificação de tarefa', 'Task creation' => 'Criação de tarefa', @@ -274,7 +273,7 @@ return array( 'Task removed successfully.' => 'Tarefa removida com sucesso.', 'Unable to remove this task.' => 'Não foi possível remover esta tarefa.', 'Remove a task' => 'Remover uma tarefa', - 'Do you really want to remove this task: "%s"?' => 'Você realmente deseja remover esta tarefa: "%s"', + 'Do you really want to remove this task: "%s"?' => 'Você realmente deseja remover esta tarefa: "%s"?', 'Assign automatically a color based on a category' => 'Atribuir automaticamente uma cor com base em uma categoria', 'Assign automatically a category based on a color' => 'Atribuir automaticamente uma categoria com base em uma cor', 'Task creation or modification' => 'Criação ou modificação de tarefa', @@ -287,12 +286,12 @@ return array( 'Your category have been updated successfully.' => 'A sua categoria foi atualizada com sucesso.', 'Unable to update your category.' => 'Não foi possível atualizar a sua categoria.', 'Remove a category' => 'Remover uma categoria', - 'Category removed successfully.' => 'Categoria removido com sucesso.', + 'Category removed successfully.' => 'Categoria removida com sucesso.', 'Unable to remove this category.' => 'Não foi possível remover esta categoria.', 'Category modification for the project "%s"' => 'Modificação de categoria para o projeto "%s"', - 'Category Name' => 'Nome da Categoria', + 'Category Name' => 'Nome da categoria', 'Add a new category' => 'Adicionar uma nova categoria', - 'Do you really want to remove this category: "%s"?' => 'Você realmente deseja remover esta categoria: "%s"', + 'Do you really want to remove this category: "%s"?' => 'Você realmente deseja remover esta categoria: "%s"?', 'All categories' => 'Todas as categorias', 'No category' => 'Nenhum categoria', 'The name is required' => 'O nome é obrigatório', @@ -300,7 +299,7 @@ return array( 'Unable to remove this file.' => 'Não foi possível remover este arquivo.', 'File removed successfully.' => 'Arquivo removido com sucesso.', 'Attach a document' => 'Anexar um documento', - 'Do you really want to remove this file: "%s"?' => 'Você realmente deseja remover este arquivo: "%s"', + 'Do you really want to remove this file: "%s"?' => 'Você realmente deseja remover este arquivo: "%s"?', 'Attachments' => 'Anexos', 'Edit the task' => 'Editar a tarefa', 'Edit the description' => 'Editar a descrição', @@ -331,7 +330,7 @@ return array( 'Unable to update your sub-task.' => 'Não foi possível atualizar a sua subtarefa.', 'Unable to create your sub-task.' => 'Não é possível criar a sua subtarefa.', 'Sub-task added successfully.' => 'Subtarefa adicionada com sucesso.', - 'Maximum size: ' => 'Tamanho máximo:', + 'Maximum size: ' => 'Tamanho máximo: ', 'Unable to upload the file.' => 'Não foi possível carregar o arquivo.', 'Display another project' => 'Exibir outro projeto', 'Login with my Github Account' => 'Entrar com minha Conta do Github', @@ -461,7 +460,7 @@ return array( 'Database' => 'Banco de dados', 'About' => 'Sobre', 'Database driver:' => 'Driver do banco de dados:', - 'Board settings' => 'Configurações do Board', + 'Board settings' => 'Configurações do board', 'URL and token' => 'URL e token', 'Webhook settings' => 'Configurações do Webhook', 'URL for task creation:' => 'URL para a criação da tarefa:', @@ -475,7 +474,7 @@ return array( 'Frequency in second (0 to disable this feature, 10 seconds by default)' => 'Frequência em segundos (0 para desativar este recurso, 10 segundos por padrão)', 'Application URL' => 'URL da Aplicação', 'Example: http://example.kanboard.net/ (used by email notifications)' => 'Exemplo: http://example.kanboard.net/ (utilizado nas notificações por e-mail)', - 'Token regenerated.' => 'Token ', + 'Token regenerated.' => 'Novo token gerado.', 'Date format' => 'Formato de data', 'ISO format is always accepted, example: "%s" and "%s"' => 'O formato ISO é sempre aceito, exemplo: "%s" e "%s"', 'New private project' => 'Novo projeto privado', @@ -562,7 +561,7 @@ return array( '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.', - 'Example: "Bug, Feature Request, Improvement"' => 'Exemplo: "Bug, Feature Request, Improvement"', + 'Example: "Bug, Feature Request, Improvement"' => 'Exemplo: "Bug, Solicitação de Recurso, Melhoria"', 'Default categories for new projects (Comma-separated)' => 'Categorias padrões para novos projetos (separadas por vírgula)', 'Gitlab commit received' => 'Gitlab commit received', 'Gitlab issue opened' => 'Gitlab issue opened', @@ -574,7 +573,7 @@ return array( 'Role for this project' => 'Função para este projeto', 'Project manager' => 'Gerente do projeto', 'Project member' => 'Membro do projeto', - 'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Um gerente do projeto pode alterar as configurações do projeto e ter mais privilégios que um usuário padrão.', + 'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Um gerente de projeto pode alterar as configurações do projeto e ter mais privilégios que um usuário padrão.', 'Gitlab Issue' => 'Gitlab Issue', 'Subtask Id' => 'ID da subtarefa', 'Subtasks' => 'Subtarefas', @@ -582,13 +581,13 @@ return array( 'Subtasks exportation for "%s"' => 'Subtarefas exportadas para "%s"', 'Task Title' => 'Título da Tarefa', 'Untitled' => 'Sem título', - 'Application default' => 'Aplicação padrão', + 'Application default' => 'Padrão da aplicação', 'Language:' => 'Idioma', 'Timezone:' => 'Fuso horário', 'All columns' => 'Todas as colunas', 'Calendar' => 'Calendário', 'Next' => 'Próximo', - // '#%d' => '', + '#%d' => '#%d', 'All swimlanes' => 'Todas as swimlanes', 'All colors' => 'Todas as cores', 'Moved to column %s' => 'Mover para a coluna %s', @@ -598,7 +597,7 @@ return array( 'Edit column "%s"' => 'Editar a coluna "%s"', 'Select the new status of the subtask: "%s"' => 'Selecionar um novo status para a subtarefa: "%s"', 'Subtask timesheet' => 'Gestão de tempo das subtarefas', - 'There is nothing to show.' => 'Não há nada para mostrar', + 'There is nothing to show.' => 'Não há nada para mostrar.', 'Time Tracking' => 'Gestão de tempo', 'You already have one subtask in progress' => 'Você já tem um subtarefa em andamento', 'Which parts of the project do you want to duplicate?' => 'Quais partes do projeto você deseja duplicar?', @@ -610,11 +609,11 @@ return array( 'End' => 'Fim', 'Task age in days' => 'Idade da tarefa em dias', 'Days in this column' => 'Dias nesta coluna', - // '%dd' => '', + '%dd' => '%dd', 'Add a link' => 'Adicionar uma associação', 'Add a new link' => 'Adicionar uma nova associação', 'Do you really want to remove this link: "%s"?' => 'Você realmente deseja remover esta associação: "%s"?', - 'Do you really want to remove this link with task #%d?' => 'Você realmente deseja remover esta associação com a tarefa n°%d?', + 'Do you really want to remove this link with task #%d?' => 'Você realmente deseja remover esta associação com a tarefa #%d?', 'Field required' => 'Campo requerido', 'Link added successfully.' => 'Associação criada com sucesso.', 'Link updated successfully.' => 'Associação atualizada com sucesso.', @@ -637,8 +636,8 @@ return array( 'is blocked by' => 'está bloqueada por', 'duplicates' => 'duplica', 'is duplicated by' => 'é duplicada por', - 'is a child of' => 'é um filho de', - 'is a parent of' => 'é um parente do', + 'is a child of' => 'é filha de', + 'is a parent of' => 'é mãe de', 'targets milestone' => 'visa um milestone', 'is a milestone of' => 'é um milestone de', 'fixes' => 'corrige', @@ -698,12 +697,12 @@ return array( '%s remove the assignee of the task %s' => '%s removeu a pessoa designada para a tarefa %s', 'Enable Gravatar images' => 'Ativar imagens do Gravatar', 'Information' => 'Informações', - 'Check two factor authentication code' => 'Verificação do código de autenticação à fator duplo', - 'The two factor authentication code is not valid.' => 'O código de autenticação à fator duplo não é válido', - 'The two factor authentication code is valid.' => 'O código de autenticação à fator duplo é válido', + 'Check two factor authentication code' => 'Verifique o código de autenticação em duas etapas', + 'The two factor authentication code is not valid.' => 'O código de autenticação em duas etapas não é válido.', + 'The two factor authentication code is valid.' => 'O código de autenticação em duas etapas é válido.', 'Code' => 'Código', - 'Two factor authentication' => 'Autenticação à fator duplo', - 'Enable/disable two factor authentication' => 'Ativar/Desativar autenticação à fator duplo', + 'Two factor authentication' => 'Autenticação em duas etapas', + 'Enable/disable two factor authentication' => 'Ativar/desativar autenticação em duas etapas', 'This QR code contains the key URI: ' => 'Este Código QR contém a chave URI:', 'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => 'Salve esta chave secreta no seu software TOTP (por exemplo Google Authenticator ou FreeOTP).', 'Check my code' => 'Verifique o meu código', @@ -717,19 +716,19 @@ return array( 'Burndown chart for "%s"' => 'Gráfico de Burndown para "%s"', 'Burndown chart' => 'Gráfico de Burndown', 'This chart show the task complexity over the time (Work Remaining).' => 'Este gráfico mostra a complexidade da tarefa ao longo do tempo (Trabalho Restante).', - 'Screenshot taken %s' => 'Screenshot tomada em %s', - 'Add a screenshot' => 'Adicionar uma Screenshot', - 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => 'Tomar um screenshot e pressione CTRL + V ou ⌘ + V para colar aqui.', - 'Screenshot uploaded successfully.' => 'Screenshot enviada com sucesso.', + 'Screenshot taken %s' => 'Captura de tela tirada em %s', + 'Add a screenshot' => 'Adicionar uma captura de tela', + 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => 'Tire uma captura de tela e pressione CTRL + V ou ⌘ + V para colar aqui.', + 'Screenshot uploaded successfully.' => 'Captura de tela enviada com sucesso.', 'SEK - Swedish Krona' => 'SEK - Coroa sueca', 'The project identifier is an optional alphanumeric code used to identify your project.' => 'O identificador de projeto é um código alfanumérico opcional utilizado para identificar o seu projeto.', 'Identifier' => 'Identificador', - 'Disable two factor authentication' => 'Desativar autenticação à dois fatores', - 'Do you really want to disable the two factor authentication for this user: "%s"?' => 'Você deseja realmente desativar a autenticação à dois fatores para esse usuário: "%s"?', + 'Disable two factor authentication' => 'Desativar autenticação em duas etapas', + 'Do you really want to disable the two factor authentication for this user: "%s"?' => 'Você realmente deseja desativar a autenticação em duas etapas para este usuário: "%s"?', 'Edit link' => 'Editar um link', 'Start to type task title...' => 'Digite o título do trabalho...', - 'A task cannot be linked to itself' => 'Uma tarefa não pode ser ligada a si própria', - 'The exact same link already exists' => 'Um link idêntico jà existe', + 'A task cannot be linked to itself' => 'Uma tarefa não pode ser vinculada a si própria', + 'The exact same link already exists' => 'Um link idêntico já existe', 'Recurrent task is scheduled to be generated' => 'A tarefa recorrente está programada para ser criada', 'Recurring information' => 'Informação sobre a recorrência', 'Score' => 'Complexidade', @@ -739,7 +738,7 @@ return array( 'Edit recurrence' => 'Modificar a recorrência', 'Generate recurrent task' => 'Gerar uma tarefa recorrente', 'Trigger to generate recurrent task' => 'Trigger para gerar tarefa recorrente', - 'Factor to calculate new due date' => 'Fator para o cálculo do nova data limite', + 'Factor to calculate new due date' => 'Fator para o cálculo da nova data limite', 'Timeframe to calculate new due date' => 'Escala de tempo para o cálculo da nova data limite', 'Base date to calculate new due date' => 'Data a ser utilizada para calcular a nova data limite', 'Action date' => 'Data da ação', @@ -770,8 +769,8 @@ return array( 'iCal feed' => 'Subscrição iCal', 'Preferences' => 'Preferências', 'Security' => 'Segurança', - 'Two factor authentication disabled' => 'Autenticação à fator duplo desativado', - 'Two factor authentication enabled' => 'Autenticação à fator duplo activado', + 'Two factor authentication disabled' => 'Autenticação em duas etapas desativada', + 'Two factor authentication enabled' => 'Autenticação em duas etapas ativada', 'Unable to update this user.' => 'Impossível de atualizar esse usuário.', 'There is no user management for private projects.' => 'Não há gerenciamento de usuários para projetos privados.', 'User that will receive the email' => 'O usuário que vai receber o e-mail', @@ -795,7 +794,7 @@ return array( 'Column change' => 'Mudança de coluna', 'Position change' => 'Mudança de posição', 'Swimlane change' => 'Mudança de swimlane', - 'Assignee change' => 'Mudança do designado', + 'Assignee change' => 'Mudança de designação', '[%s] Overdue tasks' => '[%s] Tarefas atrasadas', 'Notification' => 'Notificação', '%s moved the task #%d to the first swimlane' => '%s moveu a tarefa #%d para a primeira swimlane', @@ -804,7 +803,7 @@ return array( 'Gravatar' => 'Gravatar', '%s moved the task %s to the first swimlane' => '%s moveu a tarefa %s para a primeira swimlane', '%s moved the task %s to the swimlane "%s"' => '%s moveu a tarefa %s para a swimlane "%s"', - 'This report contains all subtasks information for the given date range.' => 'Este relatório contém informações de todas as sub-tarefas para o período selecionado.', + 'This report contains all subtasks information for the given date range.' => 'Este relatório contém informações de todas as subtarefas para o período selecionado.', 'This report contains all tasks information for the given date range.' => 'Este relatório contém informações de todas as tarefas para o período selecionado.', 'Project activities for %s' => 'Atividade do projeto "%s"', 'view the board on Kanboard' => 'ver o painel no Kanboard', @@ -825,7 +824,7 @@ return array( 'Time estimated changed: %sh' => 'O tempo estimado foi mudado/ %sh', 'The field "%s" have been updated' => 'O campo "%s" foi atualizada', 'The description have been modified' => 'A descrição foi modificada', - 'Do you really want to close the task "%s" as well as all subtasks?' => 'Você realmente quer fechar a tarefa "%s" e todas as suas sub-tarefas?', + 'Do you really want to close the task "%s" as well as all subtasks?' => 'Você realmente deseja finalizar a tarefa "%s" e todas as suas subtarefas?', 'Swimlane: %s' => 'Swimlane: %s', 'I want to receive notifications for:' => 'Eu quero receber as notificações para:', 'All tasks' => 'Todas as tarefas', @@ -844,7 +843,7 @@ return array( '<30m' => '<30m', 'Stop timer' => 'Stop timer', 'Start timer' => 'Start timer', - 'Add project member' => 'Adicionar um membro ao projeto', + 'Add project member' => 'Adicionar membro ao projeto', 'Enable notifications' => 'Ativar as notificações', 'My activity stream' => 'Meu feed de atividades', 'My calendar' => 'Minha agenda', @@ -868,7 +867,7 @@ return array( 'Switch to the list view' => 'Mudar par o modo Lista', 'Go to the search/filter box' => 'Ir para o campo de pesquisa', 'There is no activity yet.' => 'Não há nenhuma atividade ainda.', - 'No tasks found.' => 'Nenhuma tarefa encontrada', + 'No tasks found.' => 'Nenhuma tarefa encontrada.', 'Keyboard shortcut: "%s"' => 'Tecla de atalho: "%s"', 'List' => 'Lista', 'Filter' => 'Filtro', @@ -918,7 +917,7 @@ return array( 'Default task color' => 'Cor padrão para as tarefas', 'Hide sidebar' => 'Esconder a barra lateral', 'Expand sidebar' => 'Expandir a barra lateral', - 'This feature does not work with all browsers.' => 'Esta funcionalidade não é compatível com todos os navegadores', + 'This feature does not work with all browsers.' => 'Esta funcionalidade não é compatível com todos os navegadores.', 'There is no destination project available.' => 'Não há nenhum projeto de destino disponível.', 'Trigger automatically subtask time tracking' => 'Ativar automaticamente o monitoramento do tempo para as subtarefas', 'Include closed tasks in the cumulative flow diagram' => 'Incluir as tarefas fechadas no diagrama de fluxo acumulado', @@ -932,7 +931,7 @@ return array( 'contributors' => 'contribuidores', 'License:' => 'Licença:', 'License' => 'Licença', - 'Project Administrator' => 'Administrador de Projeto', + 'Project Administrator' => 'Administrador de projeto', 'Enter the text below' => 'Entre o texto abaixo', 'Gantt chart for %s' => 'Gráfico de Gantt para %s', 'Sort by position' => 'Ordenar por posição', @@ -959,7 +958,7 @@ return array( 'Project members' => 'Membros de projeto', 'Gantt chart for all projects' => 'Gráfico de Gantt para todos os projetos', 'Projects list' => 'Lista dos projetos', - 'Gantt chart for this project' => 'Gráfico de Gantt para este projecto', + 'Gantt chart for this project' => 'Gráfico de Gantt para este projeto', 'Project board' => 'Painel do projeto', 'End date:' => 'Data de término:', 'There is no start date or end date for this project.' => 'Não há data de início ou data de término para este projeto.', @@ -1028,40 +1027,45 @@ return array( 'Unread notifications' => 'Notificações não lidas', 'My filters' => 'Meus filtros', 'Notification methods:' => 'Métodos de notificação:', - // 'Import tasks from CSV file' => '', - // 'Unable to read your file' => '', - // '%d task(s) have been imported successfully.' => '', - // 'Nothing have been imported!' => '', - // 'Import users from CSV file' => '', - // '%d user(s) have been imported successfully.' => '', - // 'Comma' => '', - // 'Semi-colon' => '', - // 'Tab' => '', - // 'Vertical bar' => '', - // 'Double Quote' => '', - // 'Single Quote' => '', - // '%s attached a file to the task #%d' => '', - // 'There is no column or swimlane activated in your project!' => '', - // 'Append filter (instead of replacement)' => '', - // 'Append/Replace' => '', - // 'Append' => '', - // 'Replace' => '', - // 'There is no notification method registered.' => '', - // 'Import' => '', - // 'change sorting' => '', - // 'Tasks Importation' => '', - // 'Delimiter' => '', - // 'Enclosure' => '', - // 'CSV File' => '', - // 'Instructions' => '', - // 'Your file must use the predefined CSV format' => '', - // 'Your file must be encoded in UTF-8' => '', - // 'The first row must be the header' => '', - // 'Duplicates are not verified for you' => '', - // 'The due date must use the ISO format: YYYY-MM-DD' => '', - // 'Download CSV template' => '', - // 'No external integration registered.' => '', - // 'Duplicates are not imported' => '', - // 'Usernames must be lowercase and unique' => '', - // 'Passwords will be encrypted if present' => '', + 'Import tasks from CSV file' => 'Importar tarefas a partir de arquivo CSV', + 'Unable to read your file' => 'Não foi possível ler seu arquivo', + '%d task(s) have been imported successfully.' => '%d tarefa(s) importada(s) com sucesso.', + 'Nothing have been imported!' => 'Nada foi importado!', + 'Import users from CSV file' => 'Importar usuários a partir de arquivo CSV', + '%d user(s) have been imported successfully.' => '%d usuário(s) importado(s) com sucesso.', + 'Comma' => 'Vírgula', + 'Semi-colon' => 'Ponto e vírgula', + 'Tab' => 'Tab', + 'Vertical bar' => 'Barra vertical', + 'Double Quote' => 'Aspas duplas', + 'Single Quote' => 'Aspas simples', + '%s attached a file to the task #%d' => '%s anexou um arquivo à tarefa #%d', + 'There is no column or swimlane activated in your project!' => 'Não há coluna ou swimlane ativa em seu projeto!', + 'Append filter (instead of replacement)' => 'Adicionar filtro (em vez de substituir)', + 'Append/Replace' => 'Adicionar/Substituir', + 'Append' => 'Adicionar', + 'Replace' => 'Substituir', + 'There is no notification method registered.' => 'Não há metodo de notificação registrado.', + 'Import' => 'Importar', + 'change sorting' => 'alterar ordenação', + 'Tasks Importation' => 'Importação de Tarefas', + 'Delimiter' => 'Separador', + 'Enclosure' => 'Delimitador de campos', + 'CSV File' => 'Arquivo CSV', + 'Instructions' => 'Instruções', + 'Your file must use the predefined CSV format' => 'Seu arquivo deve utilizar o formato CSV pré-definido', + 'Your file must be encoded in UTF-8' => 'Seu arquivo deve estar codificado em UTF-8', + 'The first row must be the header' => 'A primeira linha deve ser o cabeçalho', + 'Duplicates are not verified for you' => 'Registros duplicados não são verificados', + 'The due date must use the ISO format: YYYY-MM-DD' => 'A data de vencimento deve utilizar o formato ISO: YYYY-MM-DD', + 'Download CSV template' => 'Baixar modelo de arquivo CSV', + 'No external integration registered.' => 'Nenhuma integração externa registrada.', + 'Duplicates are not imported' => 'Registros duplicados não são importados', + 'Usernames must be lowercase and unique' => 'Nomes de usuário devem ser únicos e em letras minúsculas', + 'Passwords will be encrypted if present' => 'Senhas serão encriptadas, se presentes', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/pt_PT/translations.php b/sources/app/Locale/pt_PT/translations.php index 540a4a5..5e6c57d 100644 --- a/sources/app/Locale/pt_PT/translations.php +++ b/sources/app/Locale/pt_PT/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'O ID é obrigatório', 'The project id is required' => 'O ID do projecto é obrigatório', 'The project name is required' => 'O nome do projecto é obrigatório', - 'This project must be unique' => 'Este projecto deve ser único', 'The title is required' => 'O título é obrigatório', 'Settings saved successfully.' => 'Configurações guardadas com sucesso.', 'Unable to save your settings.' => 'Não é possível guardar as suas configurações.', @@ -1027,41 +1026,46 @@ return array( 'Owner' => 'Dono', 'Unread notifications' => 'Notificações por ler', 'My filters' => 'Os meus filtros', - 'Notification methods:' => 'Metodos de notificação:', - // 'Import tasks from CSV file' => '', - // 'Unable to read your file' => '', - // '%d task(s) have been imported successfully.' => '', - // 'Nothing have been imported!' => '', - // 'Import users from CSV file' => '', - // '%d user(s) have been imported successfully.' => '', - // 'Comma' => '', - // 'Semi-colon' => '', - // 'Tab' => '', - // 'Vertical bar' => '', - // 'Double Quote' => '', - // 'Single Quote' => '', - // '%s attached a file to the task #%d' => '', - // 'There is no column or swimlane activated in your project!' => '', - // 'Append filter (instead of replacement)' => '', - // 'Append/Replace' => '', - // 'Append' => '', - // 'Replace' => '', - // 'There is no notification method registered.' => '', - // 'Import' => '', - // 'change sorting' => '', - // 'Tasks Importation' => '', - // 'Delimiter' => '', - // 'Enclosure' => '', - // 'CSV File' => '', - // 'Instructions' => '', - // 'Your file must use the predefined CSV format' => '', - // 'Your file must be encoded in UTF-8' => '', - // 'The first row must be the header' => '', - // 'Duplicates are not verified for you' => '', - // 'The due date must use the ISO format: YYYY-MM-DD' => '', - // 'Download CSV template' => '', - // 'No external integration registered.' => '', - // 'Duplicates are not imported' => '', - // 'Usernames must be lowercase and unique' => '', - // 'Passwords will be encrypted if present' => '', + 'Notification methods:' => 'Métodos de notificação:', + 'Import tasks from CSV file' => 'Importar tarefas de um ficheiro CSV', + 'Unable to read your file' => 'Não foi possivel ler o ficheiro', + '%d task(s) have been imported successfully.' => '%d tarefa(s) importada(s) com successo.', + 'Nothing have been imported!' => 'Nada foi importado', + 'Import users from CSV file' => 'Importar utilizadores de um ficheiro CSV', + '%d user(s) have been imported successfully.' => '%d utilizadore(s) importados com successo.', + 'Comma' => 'Vírgula', + 'Semi-colon' => 'Ponto e Vírgula', + 'Tab' => 'Tabulação', + 'Vertical bar' => 'Barra vertical', + 'Double Quote' => 'Aspas', + 'Single Quote' => 'Plica', + '%s attached a file to the task #%d' => '%s anexou um ficheiro à tarefa #%d', + 'There is no column or swimlane activated in your project!' => 'Não existe nenhuma coluna ou swimlane activado no seu projecto!', + 'Append filter (instead of replacement)' => 'Acrescentar filtro (em vez de substituir)', + 'Append/Replace' => 'Acrescentar/Substituir', + 'Append' => 'Acrescentar', + 'Replace' => 'Substituir', + 'There is no notification method registered.' => 'Não existe método de notificação registrado.', + 'Import' => 'Importar', + 'change sorting' => 'alterar ordernação', + 'Tasks Importation' => 'Importação de Tarefas', + 'Delimiter' => 'Delimitador', + 'Enclosure' => 'Clausura', + 'CSV File' => 'Ficheiro CSV', + 'Instructions' => 'Instruções', + 'Your file must use the predefined CSV format' => 'O seu ficheiro tem de usar um formato CSV pre-definido', + 'Your file must be encoded in UTF-8' => 'O seu ficheiro tem de estar codificado como UTF-8', + 'The first row must be the header' => 'A primeira linha tem de ser o cabeçalho', + 'Duplicates are not verified for you' => 'Duplicados não são verificados por si', + 'The due date must use the ISO format: YYYY-MM-DD' => 'A data de expiração tem de estar no formato ISO: AAAA-MM-DD', + 'Download CSV template' => 'Descarregar template CSV', + 'No external integration registered.' => 'Nenhuma integração externa registrada.', + 'Duplicates are not imported' => 'Duplicados não são importados', + 'Usernames must be lowercase and unique' => 'Utilizadores tem de estar em letra pequena e ser unicos', + 'Passwords will be encrypted if present' => 'Senhas serão encriptadas se presentes', + '%s attached a new file to the task %s' => '%s anexou um novo ficheiro à tarefa %s', + 'Assign automatically a category based on a link' => 'Assignar automáticamente a categoria baseada num link', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/ru_RU/translations.php b/sources/app/Locale/ru_RU/translations.php index 0e9f2da..e7f2d7a 100644 --- a/sources/app/Locale/ru_RU/translations.php +++ b/sources/app/Locale/ru_RU/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'Необходим ID', 'The project id is required' => 'Необходим ID проекта', 'The project name is required' => 'Необходимо имя проекта', - 'This project must be unique' => 'Проект должен быть уникальным', 'The title is required' => 'Необходим заголовок', 'Settings saved successfully.' => 'Параметры успешно сохранены.', 'Unable to save your settings.' => 'Невозможно сохранить параметры.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/sr_Latn_RS/translations.php b/sources/app/Locale/sr_Latn_RS/translations.php index 0e25033..af785f9 100644 --- a/sources/app/Locale/sr_Latn_RS/translations.php +++ b/sources/app/Locale/sr_Latn_RS/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'ID je obavezan', 'The project id is required' => 'ID projekta je obavezan', 'The project name is required' => 'Naziv projekta je obavezan', - 'This project must be unique' => 'Projekat mora biti jedinstven', 'The title is required' => 'Naslov je obavezan', 'Settings saved successfully.' => 'Podešavanja uspešno snimljena.', 'Unable to save your settings.' => 'Nemoguće snimanje podešavanja.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/sv_SE/translations.php b/sources/app/Locale/sv_SE/translations.php index 8663d60..188b2bd 100644 --- a/sources/app/Locale/sv_SE/translations.php +++ b/sources/app/Locale/sv_SE/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'Aktuellt ID måste anges', 'The project id is required' => 'Projekt-ID måste anges', 'The project name is required' => 'Ett projektnamn måste anges', - 'This project must be unique' => 'Detta projekt måste vara unikt', 'The title is required' => 'En titel måste anges.', 'Settings saved successfully.' => 'Inställningarna har sparats.', 'Unable to save your settings.' => 'Kunde inte spara dina ändringar', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/th_TH/translations.php b/sources/app/Locale/th_TH/translations.php index 50181c7..d180c5e 100644 --- a/sources/app/Locale/th_TH/translations.php +++ b/sources/app/Locale/th_TH/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'ต้องการไอดี', 'The project id is required' => 'ต้องการไอดีโปรเจค', 'The project name is required' => 'ต้องการชื่อโปรเจค', - 'This project must be unique' => 'ชื่อโปรเจคต้องไม่ซ้ำ', 'The title is required' => 'ต้องการหัวเรื่อง', 'Settings saved successfully.' => 'บันทึกการตั้งค่าเรียบร้อยแล้ว', 'Unable to save your settings.' => 'ไม่สามารถบันทึกการตั้งค่าได้', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/tr_TR/translations.php b/sources/app/Locale/tr_TR/translations.php index 0527779..fca425e 100644 --- a/sources/app/Locale/tr_TR/translations.php +++ b/sources/app/Locale/tr_TR/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => 'Kod gerekli', 'The project id is required' => 'Proje kodu gerekli', 'The project name is required' => 'Proje adı gerekli', - 'This project must be unique' => 'Bu projenin tekil olması gerekli', 'The title is required' => 'Başlık gerekli', 'Settings saved successfully.' => 'Ayarlar başarıyla kaydedildi.', 'Unable to save your settings.' => 'Ayarlarınız kaydedilemedi.', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Locale/zh_CN/translations.php b/sources/app/Locale/zh_CN/translations.php index cc7de56..7642e01 100644 --- a/sources/app/Locale/zh_CN/translations.php +++ b/sources/app/Locale/zh_CN/translations.php @@ -124,7 +124,6 @@ return array( 'The id is required' => '需要指定id', 'The project id is required' => '需要指定项目id', 'The project name is required' => '需要指定项目名称', - 'This project must be unique' => '项目名称必须唯一', 'The title is required' => '需要指定标题', 'Settings saved successfully.' => '设置成功保存。', 'Unable to save your settings.' => '无法保存你的设置。', @@ -1064,4 +1063,9 @@ return array( // 'Duplicates are not imported' => '', // 'Usernames must be lowercase and unique' => '', // 'Passwords will be encrypted if present' => '', + // '%s attached a new file to the task %s' => '', + // 'Assign automatically a category based on a link' => '', + // 'BAM - Konvertibile Mark' => '', + // 'Assignee Username' => '', + // 'Assignee Name' => '', ); diff --git a/sources/app/Model/Action.php b/sources/app/Model/Action.php index ba74218..dbf17e4 100644 --- a/sources/app/Model/Action.php +++ b/sources/app/Model/Action.php @@ -73,6 +73,7 @@ class Action extends Base 'TaskAssignColorUser' => t('Assign a color to a specific user'), 'TaskAssignColorCategory' => t('Assign automatically a color based on a category'), 'TaskAssignCategoryColor' => t('Assign automatically a category based on a color'), + 'TaskAssignCategoryLink' => t('Assign automatically a category based on a link'), 'CommentCreation' => t('Create a comment from an external provider'), 'TaskCreation' => t('Create a task from an external provider'), 'TaskLogMoveAnotherColumn' => t('Add a comment log when moving the task between columns'), diff --git a/sources/app/Model/Authentication.php b/sources/app/Model/Authentication.php index 580c1e1..83d8543 100644 --- a/sources/app/Model/Authentication.php +++ b/sources/app/Model/Authentication.php @@ -2,7 +2,7 @@ namespace Kanboard\Model; -use Kanboard\Core\Request; +use Kanboard\Core\Http\Request; use SimpleValidator\Validator; use SimpleValidator\Validators; use Gregwar\Captcha\CaptchaBuilder; @@ -45,11 +45,11 @@ class Authentication extends Base // Check if the user session match an existing user $userNotFound = ! $this->user->exists($this->userSession->getId()); - $reverseProxyWrongUser = REVERSE_PROXY_AUTH && $this->backend('reverseProxy')->getUsername() !== $_SESSION['user']['username']; + $reverseProxyWrongUser = REVERSE_PROXY_AUTH && $this->backend('reverseProxy')->getUsername() !== $this->userSession->getUsername(); if ($userNotFound || $reverseProxyWrongUser) { $this->backend('rememberMe')->destroy($this->userSession->getId()); - $this->session->close(); + $this->sessionManager->close(); return false; } @@ -176,8 +176,12 @@ class Authentication extends Base public function validateFormCaptcha(array $values) { if ($this->hasCaptcha($values['username'])) { + if (! isset($this->sessionStorage->captcha)) { + return false; + } + $builder = new CaptchaBuilder; - $builder->setPhrase($this->session['captcha']); + $builder->setPhrase($this->sessionStorage->captcha); return $builder->testPhrase(isset($values['captcha']) ? $values['captcha'] : ''); } diff --git a/sources/app/Model/Config.php b/sources/app/Model/Config.php index cf634f8..273f884 100644 --- a/sources/app/Model/Config.php +++ b/sources/app/Model/Config.php @@ -3,8 +3,8 @@ namespace Kanboard\Model; use Kanboard\Core\Translator; -use Kanboard\Core\Security; -use Kanboard\Core\Session; +use Kanboard\Core\Security\Token; +use Kanboard\Core\Session\SessionManager; /** * Config model @@ -35,6 +35,7 @@ class Config extends Setting 'RSD' => t('RSD - Serbian dinar'), 'SEK' => t('SEK - Swedish Krona'), 'NOK' => t('NOK - Norwegian Krone'), + 'BAM' => t('BAM - Konvertibile Mark'), ); } @@ -69,6 +70,7 @@ class Config extends Setting // Sorted by value $languages = array( 'id_ID' => 'Bahasa Indonesia', + 'bs_BA' => 'Bosanski', 'cs_CZ' => 'Čeština', 'da_DK' => 'Dansk', 'de_DE' => 'Deutsch', @@ -108,7 +110,7 @@ class Config extends Setting public function getJsLanguageCode() { $languages = array( - 'cs_CZ' => 'cz', + 'cs_CZ' => 'cs', 'da_DK' => 'da', 'de_DE' => 'de', 'en_US' => 'en', @@ -145,8 +147,8 @@ class Config extends Setting */ public function getCurrentLanguage() { - if ($this->userSession->isLogged() && ! empty($this->session['user']['language'])) { - return $this->session['user']['language']; + if ($this->userSession->isLogged() && ! empty($this->sessionStorage->user['language'])) { + return $this->sessionStorage->user['language']; } return $this->get('application_language', 'en_US'); @@ -162,17 +164,17 @@ class Config extends Setting */ public function get($name, $default_value = '') { - if (! Session::isOpen()) { + if (! SessionManager::isOpen()) { return $this->getOption($name, $default_value); } // Cache config in session - if (! isset($this->session['config'][$name])) { - $this->session['config'] = $this->getAll(); + if (! isset($this->sessionStorage->config[$name])) { + $this->sessionStorage->config = $this->getAll(); } - if (! empty($this->session['config'][$name])) { - return $this->session['config'][$name]; + if (! empty($this->sessionStorage->config[$name])) { + return $this->sessionStorage->config[$name]; } return $default_value; @@ -185,7 +187,7 @@ class Config extends Setting */ public function reload() { - $this->session['config'] = $this->getAll(); + $this->sessionStorage->config = $this->getAll(); $this->setupTranslations(); } @@ -207,8 +209,8 @@ class Config extends Setting */ public function getCurrentTimezone() { - if ($this->userSession->isLogged() && ! empty($this->session['user']['timezone'])) { - return $this->session['user']['timezone']; + if ($this->userSession->isLogged() && ! empty($this->sessionStorage->user['timezone'])) { + return $this->sessionStorage->user['timezone']; } return $this->get('application_timezone', 'UTC'); @@ -265,7 +267,7 @@ class Config extends Setting */ public function regenerateToken($option) { - $this->save(array($option => Security::generateToken())); + $this->save(array($option => Token::getToken())); } /** diff --git a/sources/app/Model/Project.php b/sources/app/Model/Project.php index b767af2..a7f9309 100644 --- a/sources/app/Model/Project.php +++ b/sources/app/Model/Project.php @@ -4,7 +4,7 @@ namespace Kanboard\Model; use SimpleValidator\Validator; use SimpleValidator\Validators; -use Kanboard\Core\Security; +use Kanboard\Core\Security\Token; /** * Project model @@ -491,7 +491,7 @@ class Project extends Base $this->db ->table(self::TABLE) ->eq('id', $project_id) - ->save(array('is_public' => 1, 'token' => Security::generateToken())); + ->save(array('is_public' => 1, 'token' => Token::getToken())); } /** @@ -527,7 +527,6 @@ class Project extends Base new Validators\MaxLength('start_date', t('The maximum length is %d characters', 10), 10), new Validators\MaxLength('end_date', t('The maximum length is %d characters', 10), 10), new Validators\AlphaNumeric('identifier', t('This value must be alphanumeric')) , - new Validators\Unique('name', t('This project must be unique'), $this->db->getConnection(), self::TABLE), new Validators\Unique('identifier', t('The identifier must be unique'), $this->db->getConnection(), self::TABLE), ); } diff --git a/sources/app/Model/ProjectDailyColumnStats.php b/sources/app/Model/ProjectDailyColumnStats.php index 8ed6137..4b75fff 100644 --- a/sources/app/Model/ProjectDailyColumnStats.php +++ b/sources/app/Model/ProjectDailyColumnStats.php @@ -34,40 +34,51 @@ class ProjectDailyColumnStats extends Base { $status = $this->config->get('cfd_include_closed_tasks') == 1 ? array(Task::STATUS_OPEN, Task::STATUS_CLOSED) : array(Task::STATUS_OPEN); - return $this->db->transaction(function (Database $db) use ($project_id, $date, $status) { + $this->db->startTransaction(); - $column_ids = $db->table(Board::TABLE)->eq('project_id', $project_id)->findAllByColumn('id'); + $column_ids = $this->db->table(Board::TABLE)->eq('project_id', $project_id)->findAllByColumn('id'); - foreach ($column_ids as $column_id) { + foreach ($column_ids as $column_id) { - // This call will fail if the record already exists - // (cross database driver hack for INSERT..ON DUPLICATE KEY UPDATE) - $db->table(ProjectDailyColumnStats::TABLE)->insert(array( - 'day' => $date, - 'project_id' => $project_id, - 'column_id' => $column_id, - 'total' => 0, - 'score' => 0, - )); + $exists = $this->db->table(ProjectDailyColumnStats::TABLE) + ->eq('project_id', $project_id) + ->eq('column_id', $column_id) + ->eq('day', $date) + ->exists(); - $db->table(ProjectDailyColumnStats::TABLE) + $score = $this->db->table(Task::TABLE) + ->eq('project_id', $project_id) + ->eq('column_id', $column_id) + ->eq('is_active', Task::STATUS_OPEN) + ->sum('score'); + + $total = $this->db->table(Task::TABLE) + ->eq('project_id', $project_id) + ->eq('column_id', $column_id) + ->in('is_active', $status) + ->count(); + + if ($exists) { + $this->db->table(ProjectDailyColumnStats::TABLE) ->eq('project_id', $project_id) ->eq('column_id', $column_id) ->eq('day', $date) - ->update(array( - 'score' => $db->table(Task::TABLE) - ->eq('project_id', $project_id) - ->eq('column_id', $column_id) - ->eq('is_active', Task::STATUS_OPEN) - ->sum('score'), - 'total' => $db->table(Task::TABLE) - ->eq('project_id', $project_id) - ->eq('column_id', $column_id) - ->in('is_active', $status) - ->count() - )); + ->update(array('score' => $score, 'total' => $total)); + + } else { + $this->db->table(ProjectDailyColumnStats::TABLE)->insert(array( + 'day' => $date, + 'project_id' => $project_id, + 'column_id' => $column_id, + 'total' => $total, + 'score' => $score, + )); } - }); + } + + $this->db->closeTransaction(); + + return true; } /** diff --git a/sources/app/Model/ProjectDailyStats.php b/sources/app/Model/ProjectDailyStats.php index 46ca0a4..7ec1ee2 100644 --- a/sources/app/Model/ProjectDailyStats.php +++ b/sources/app/Model/ProjectDailyStats.php @@ -29,27 +29,35 @@ class ProjectDailyStats extends Base */ public function updateTotals($project_id, $date) { + $this->db->startTransaction(); + $lead_cycle_time = $this->projectAnalytic->getAverageLeadAndCycleTime($project_id); - return $this->db->transaction(function (Database $db) use ($project_id, $date, $lead_cycle_time) { + $exists = $this->db->table(ProjectDailyStats::TABLE) + ->eq('day', $date) + ->eq('project_id', $project_id) + ->exists(); - // This call will fail if the record already exists - // (cross database driver hack for INSERT..ON DUPLICATE KEY UPDATE) - $db->table(ProjectDailyStats::TABLE)->insert(array( - 'day' => $date, - 'project_id' => $project_id, - 'avg_lead_time' => 0, - 'avg_cycle_time' => 0, - )); - - $db->table(ProjectDailyStats::TABLE) + if ($exists) { + $this->db->table(ProjectDailyStats::TABLE) ->eq('project_id', $project_id) ->eq('day', $date) ->update(array( 'avg_lead_time' => $lead_cycle_time['avg_lead_time'], 'avg_cycle_time' => $lead_cycle_time['avg_cycle_time'], )); - }); + } else { + $this->db->table(ProjectDailyStats::TABLE)->insert(array( + 'day' => $date, + 'project_id' => $project_id, + 'avg_lead_time' => $lead_cycle_time['avg_lead_time'], + 'avg_cycle_time' => $lead_cycle_time['avg_cycle_time'], + )); + } + + $this->db->closeTransaction(); + + return true; } /** diff --git a/sources/app/Model/TaskExport.php b/sources/app/Model/TaskExport.php index d38a538..278c089 100644 --- a/sources/app/Model/TaskExport.php +++ b/sources/app/Model/TaskExport.php @@ -58,6 +58,7 @@ class TaskExport extends Base tasks.date_due, creators.username AS creator_username, users.username AS assignee_username, + users.name AS assignee_name, tasks.score, tasks.title, tasks.date_creation, @@ -129,7 +130,8 @@ class TaskExport extends Base e('Color'), e('Due date'), e('Creator'), - e('Assignee'), + e('Assignee Username'), + e('Assignee Name'), e('Complexity'), e('Title'), e('Creation date'), diff --git a/sources/app/Model/User.php b/sources/app/Model/User.php index 6e7e94e..88361ce 100644 --- a/sources/app/Model/User.php +++ b/sources/app/Model/User.php @@ -5,8 +5,8 @@ namespace Kanboard\Model; use PicoDb\Database; use SimpleValidator\Validator; use SimpleValidator\Validators; -use Kanboard\Core\Session; -use Kanboard\Core\Security; +use Kanboard\Core\Session\SessionManager; +use Kanboard\Core\Security\Token; /** * User model @@ -320,8 +320,8 @@ class User extends Base $result = $this->db->table(self::TABLE)->eq('id', $values['id'])->update($values); // If the user is connected refresh his session - if (Session::isOpen() && $this->userSession->getId() == $values['id']) { - $this->userSession->refresh(); + if (SessionManager::isOpen() && $this->userSession->getId() == $values['id']) { + $this->userSession->initialize($this->getById($this->userSession->getId())); } return $result; @@ -383,7 +383,7 @@ class User extends Base return $this->db ->table(self::TABLE) ->eq('id', $user_id) - ->save(array('token' => Security::generateToken())); + ->save(array('token' => Token::getToken())); } /** @@ -587,7 +587,7 @@ class User extends Base if ($v->execute()) { // Check password - if ($this->authentication->authenticate($this->session['user']['username'], $values['current_password'])) { + if ($this->authentication->authenticate($this->userSession->getUsername(), $values['current_password'])) { return array(true, array()); } else { return array(false, array('current_password' => array(t('Wrong password')))); diff --git a/sources/app/Model/UserSession.php b/sources/app/Model/UserSession.php index 1778114..a687952 100644 --- a/sources/app/Model/UserSession.php +++ b/sources/app/Model/UserSession.php @@ -11,17 +11,13 @@ namespace Kanboard\Model; class UserSession extends Base { /** - * Update user session information + * Update user session * * @access public - * @param array $user User data + * @param array $user */ - public function refresh(array $user = array()) + public function initialize(array $user) { - if (empty($user)) { - $user = $this->user->getById($this->userSession->getId()); - } - if (isset($user['password'])) { unset($user['password']); } @@ -31,12 +27,13 @@ class UserSession extends Base } $user['id'] = (int) $user['id']; - $user['is_admin'] = (bool) $user['is_admin']; - $user['is_project_admin'] = (bool) $user['is_project_admin']; - $user['is_ldap_user'] = (bool) $user['is_ldap_user']; - $user['twofactor_activated'] = (bool) $user['twofactor_activated']; + $user['is_admin'] = isset($user['is_admin']) ? (bool) $user['is_admin'] : false; + $user['is_project_admin'] = isset($user['is_project_admin']) ? (bool) $user['is_project_admin'] : false; + $user['is_ldap_user'] = isset($user['is_ldap_user']) ? (bool) $user['is_ldap_user'] : false; + $user['twofactor_activated'] = isset($user['twofactor_activated']) ? (bool) $user['twofactor_activated'] : false; - $this->session['user'] = $user; + $this->sessionStorage->user = $user; + $this->sessionStorage->postAuth = array('validated' => false); } /** @@ -47,7 +44,7 @@ class UserSession extends Base */ public function check2FA() { - return isset($this->session['2fa_validated']) && $this->session['2fa_validated'] === true; + return isset($this->sessionStorage->postAuth['validated']) && $this->sessionStorage->postAuth['validated'] === true; } /** @@ -58,7 +55,17 @@ class UserSession extends Base */ public function has2FA() { - return isset($this->session['user']['twofactor_activated']) && $this->session['user']['twofactor_activated'] === true; + return isset($this->sessionStorage->user['twofactor_activated']) && $this->sessionStorage->user['twofactor_activated'] === true; + } + + /** + * Disable 2FA for the current session + * + * @access public + */ + public function disable2FA() + { + $this->sessionStorage->user['twofactor_activated'] = false; } /** @@ -69,7 +76,7 @@ class UserSession extends Base */ public function isAdmin() { - return isset($this->session['user']['is_admin']) && $this->session['user']['is_admin'] === true; + return isset($this->sessionStorage->user['is_admin']) && $this->sessionStorage->user['is_admin'] === true; } /** @@ -80,7 +87,7 @@ class UserSession extends Base */ public function isProjectAdmin() { - return isset($this->session['user']['is_project_admin']) && $this->session['user']['is_project_admin'] === true; + return isset($this->sessionStorage->user['is_project_admin']) && $this->sessionStorage->user['is_project_admin'] === true; } /** @@ -91,7 +98,18 @@ class UserSession extends Base */ public function getId() { - return isset($this->session['user']['id']) ? (int) $this->session['user']['id'] : 0; + return isset($this->sessionStorage->user['id']) ? (int) $this->sessionStorage->user['id'] : 0; + } + + /** + * Get username + * + * @access public + * @return integer + */ + public function getUsername() + { + return isset($this->sessionStorage->user['username']) ? $this->sessionStorage->user['username'] : ''; } /** @@ -102,7 +120,7 @@ class UserSession extends Base */ public function isLogged() { - return ! empty($this->session['user']); + return isset($this->sessionStorage->user) && ! empty($this->sessionStorage->user); } /** @@ -114,7 +132,7 @@ class UserSession extends Base */ public function getFilters($project_id) { - return ! empty($_SESSION['filters'][$project_id]) ? $_SESSION['filters'][$project_id] : 'status:open'; + return ! empty($this->sessionStorage->filters[$project_id]) ? $this->sessionStorage->filters[$project_id] : 'status:open'; } /** @@ -126,7 +144,7 @@ class UserSession extends Base */ public function setFilters($project_id, $filters) { - $_SESSION['filters'][$project_id] = $filters; + $this->sessionStorage->filters[$project_id] = $filters; } /** @@ -138,7 +156,7 @@ class UserSession extends Base */ public function isBoardCollapsed($project_id) { - return ! empty($_SESSION['board_collapsed'][$project_id]) ? $_SESSION['board_collapsed'][$project_id] : false; + return ! empty($this->sessionStorage->boardCollapsed[$project_id]) ? $this->sessionStorage->boardCollapsed[$project_id] : false; } /** @@ -146,11 +164,11 @@ class UserSession extends Base * * @access public * @param integer $project_id - * @param boolean $collapsed + * @param boolean $is_collapsed */ - public function setBoardDisplayMode($project_id, $collapsed) + public function setBoardDisplayMode($project_id, $is_collapsed) { - $_SESSION['board_collapsed'][$project_id] = $collapsed; + $this->sessionStorage->boardCollapsed[$project_id] = $is_collapsed; } /** @@ -161,7 +179,7 @@ class UserSession extends Base */ public function setCommentSorting($order) { - $this->session['comment_sorting'] = $order; + $this->sessionStorage->commentSorting = $order; } /** @@ -172,6 +190,6 @@ class UserSession extends Base */ public function getCommentSorting() { - return $this->session['comment_sorting'] ?: 'ASC'; + return empty($this->sessionStorage->commentSorting) ? 'ASC' : $this->sessionStorage->commentSorting; } } diff --git a/sources/app/Notification/Mail.php b/sources/app/Notification/Mail.php index cd8af85..98bffef 100644 --- a/sources/app/Notification/Mail.php +++ b/sources/app/Notification/Mail.php @@ -16,6 +16,13 @@ use Kanboard\Model\Subtask; */ class Mail extends Base implements NotificationInterface { + /** + * Notification type + * + * @var string + */ + const TYPE = 'email'; + /** * Send notification to a user * diff --git a/sources/app/Notification/Web.php b/sources/app/Notification/Web.php index 989ae06..9271c19 100644 --- a/sources/app/Notification/Web.php +++ b/sources/app/Notification/Web.php @@ -12,6 +12,13 @@ use Kanboard\Core\Base; */ class Web extends Base implements NotificationInterface { + /** + * Notification type + * + * @var string + */ + const TYPE = 'web'; + /** * Send notification to a user * diff --git a/sources/app/Schema/Mysql.php b/sources/app/Schema/Mysql.php index a021c1c..52a73fb 100644 --- a/sources/app/Schema/Mysql.php +++ b/sources/app/Schema/Mysql.php @@ -3,9 +3,15 @@ namespace Schema; use PDO; -use Kanboard\Core\Security; +use Kanboard\Core\Security\Token; -const VERSION = 93; +const VERSION = 94; + +function version_94(PDO $pdo) +{ + $pdo->exec('ALTER TABLE `projects` DROP INDEX `name`'); + $pdo->exec('ALTER TABLE `projects` DROP INDEX `name_2`'); +} function version_93(PDO $pdo) { @@ -869,7 +875,7 @@ function version_20(PDO $pdo) function version_19(PDO $pdo) { $pdo->exec("ALTER TABLE config ADD COLUMN api_token VARCHAR(255) DEFAULT ''"); - $pdo->exec("UPDATE config SET api_token='".Security::generateToken()."'"); + $pdo->exec("UPDATE config SET api_token='".Token::getToken()."'"); } function version_18(PDO $pdo) @@ -1091,6 +1097,6 @@ function version_1(PDO $pdo) $pdo->exec(" INSERT INTO config (webhooks_token) - VALUES ('".Security::generateToken()."') + VALUES ('".Token::getToken()."') "); } diff --git a/sources/app/Schema/Postgres.php b/sources/app/Schema/Postgres.php index a3fb6d4..5cd1a7d 100644 --- a/sources/app/Schema/Postgres.php +++ b/sources/app/Schema/Postgres.php @@ -3,9 +3,14 @@ namespace Schema; use PDO; -use Kanboard\Core\Security; +use Kanboard\Core\Security\Token; -const VERSION = 73; +const VERSION = 74; + +function version_74(PDO $pdo) +{ + $pdo->exec('ALTER TABLE projects DROP CONSTRAINT IF EXISTS projects_name_key'); +} function version_73(PDO $pdo) { @@ -994,6 +999,6 @@ function version_1(PDO $pdo) $pdo->exec(" INSERT INTO config (webhooks_token, api_token) - VALUES ('".Security::generateToken()."', '".Security::generateToken()."') + VALUES ('".Token::getToken()."', '".Token::getToken()."') "); } diff --git a/sources/app/Schema/Sqlite.php b/sources/app/Schema/Sqlite.php index b9ab86f..fa26b15 100644 --- a/sources/app/Schema/Sqlite.php +++ b/sources/app/Schema/Sqlite.php @@ -2,7 +2,7 @@ namespace Schema; -use Kanboard\Core\Security; +use Kanboard\Core\Security\Token; use PDO; const VERSION = 88; @@ -799,7 +799,7 @@ function version_20(PDO $pdo) function version_19(PDO $pdo) { $pdo->exec("ALTER TABLE config ADD COLUMN api_token TEXT DEFAULT ''"); - $pdo->exec("UPDATE config SET api_token='".Security::generateToken()."'"); + $pdo->exec("UPDATE config SET api_token='".Token::getToken()."'"); } function version_18(PDO $pdo) @@ -1026,7 +1026,7 @@ function version_1(PDO $pdo) $pdo->exec(" CREATE TABLE projects ( id INTEGER PRIMARY KEY, - name TEXT NOCASE NOT NULL UNIQUE, + name TEXT NOCASE NOT NULL, is_active INTEGER DEFAULT 1 ) "); @@ -1068,6 +1068,6 @@ function version_1(PDO $pdo) $pdo->exec(" INSERT INTO config (webhooks_token) - VALUES ('".Security::generateToken()."') + VALUES ('".Token::getToken()."') "); } diff --git a/sources/app/ServiceProvider/ClassProvider.php b/sources/app/ServiceProvider/ClassProvider.php index c103d63..9c9bc23 100644 --- a/sources/app/ServiceProvider/ClassProvider.php +++ b/sources/app/ServiceProvider/ClassProvider.php @@ -11,8 +11,11 @@ use Kanboard\Core\ObjectStorage\FileStorage; use Kanboard\Core\Paginator; use Kanboard\Core\OAuth2; use Kanboard\Core\Tool; +use Kanboard\Core\Http\Client as HttpClient; use Kanboard\Model\UserNotificationType; use Kanboard\Model\ProjectNotificationType; +use Kanboard\Notification\Mail as MailNotification; +use Kanboard\Notification\Web as WebNotification; class ClassProvider implements ServiceProviderInterface { @@ -81,19 +84,23 @@ class ClassProvider implements ServiceProviderInterface 'Core' => array( 'DateParser', 'Helper', - 'HttpClient', 'Lexer', - 'Request', - 'Router', - 'Session', 'Template', ), + 'Core\Http' => array( + 'Request', + 'Response', + 'Router', + ), 'Core\Cache' => array( 'MemoryCache', ), 'Core\Plugin' => array( 'Hook', ), + 'Core\Security' => array( + 'Token', + ), 'Integration' => array( 'BitbucketWebhook', 'GithubWebhook', @@ -113,6 +120,10 @@ class ClassProvider implements ServiceProviderInterface return new OAuth2($c); }); + $container['httpClient'] = function ($c) { + return new HttpClient($c); + }; + $container['htmlConverter'] = function () { return new HtmlConverter(array('strip_tags' => true)); }; @@ -131,8 +142,8 @@ class ClassProvider implements ServiceProviderInterface $container['userNotificationType'] = function ($container) { $type = new UserNotificationType($container); - $type->setType('email', t('Email'), '\Kanboard\Notification\Mail'); - $type->setType('web', t('Web'), '\Kanboard\Notification\Web'); + $type->setType(MailNotification::TYPE, t('Email'), '\Kanboard\Notification\Mail'); + $type->setType(WebNotification::TYPE, t('Web'), '\Kanboard\Notification\Web'); return $type; }; @@ -146,5 +157,7 @@ class ClassProvider implements ServiceProviderInterface $container['pluginLoader'] = new Loader($container); $container['cspRules'] = array('style-src' => "'self' 'unsafe-inline'", 'img-src' => '* data:'); + + return $container; } } diff --git a/sources/app/ServiceProvider/DatabaseProvider.php b/sources/app/ServiceProvider/DatabaseProvider.php index b211564..8cede8a 100644 --- a/sources/app/ServiceProvider/DatabaseProvider.php +++ b/sources/app/ServiceProvider/DatabaseProvider.php @@ -15,6 +15,8 @@ class DatabaseProvider implements ServiceProviderInterface $container['db'] = $this->getInstance(); $container['db']->stopwatch = DEBUG; $container['db']->logQueries = DEBUG; + + return $container; } /** diff --git a/sources/app/ServiceProvider/EventDispatcherProvider.php b/sources/app/ServiceProvider/EventDispatcherProvider.php index 1711919..17141fd 100644 --- a/sources/app/ServiceProvider/EventDispatcherProvider.php +++ b/sources/app/ServiceProvider/EventDispatcherProvider.php @@ -32,5 +32,7 @@ class EventDispatcherProvider implements ServiceProviderInterface // Automatic actions $container['action']->attachEvents(); + + return $container; } } diff --git a/sources/app/ServiceProvider/LoggingProvider.php b/sources/app/ServiceProvider/LoggingProvider.php index 4344bcc..68c074f 100644 --- a/sources/app/ServiceProvider/LoggingProvider.php +++ b/sources/app/ServiceProvider/LoggingProvider.php @@ -26,5 +26,7 @@ class LoggingProvider implements ServiceProviderInterface } $container['logger'] = $logger; + + return $container; } } diff --git a/sources/app/ServiceProvider/SessionProvider.php b/sources/app/ServiceProvider/SessionProvider.php new file mode 100644 index 0000000..414d957 --- /dev/null +++ b/sources/app/ServiceProvider/SessionProvider.php @@ -0,0 +1,29 @@ +
- +
diff --git a/sources/app/Template/event/file_create.php b/sources/app/Template/event/file_create.php new file mode 100644 index 0000000..1a36bc8 --- /dev/null +++ b/sources/app/Template/event/file_create.php @@ -0,0 +1,11 @@ +user->avatar($email, $author) ?> + +

+ e($author), + $this->url->link(t('#%d', $task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) + ) ?> +

+

+ e($file['name']) ?> +

\ No newline at end of file diff --git a/sources/app/Template/project/filters.php b/sources/app/Template/project/filters.php index c17cfb3..9e12629 100644 --- a/sources/app/Template/project/filters.php +++ b/sources/app/Template/project/filters.php @@ -1,4 +1,6 @@ + + hook->render('template:project:header:after', array('project' => $project)) ?> \ No newline at end of file diff --git a/sources/app/Template/subtask/show.php b/sources/app/Template/subtask/show.php index 1f0f9bb..dc85164 100644 --- a/sources/app/Template/subtask/show.php +++ b/sources/app/Template/subtask/show.php @@ -1,91 +1,90 @@ - - - -
- - - - - - - - - - - - - + + + +
+ + + + + + + + - subtask->toggleStatus($subtask, 'task') ?> - - render('subtask/icons', array('subtask' => $subtask)) . $this->e($subtask['title']) ?> + - - - - + + + + + - - - -
- - - url->link($this->e($subtask['name'] ?: $subtask['username']), 'user', 'show', array('user_id' => $subtask['user_id'])) ?> - - e($subtask['name'] ?: $subtask['username']) ?> - - - -
    -
  • - - e($subtask['time_spent']).'h' ?> - - - - e($subtask['time_estimated']).'h' ?> - -
  • - user->getId()): ?> -
  • - - - url->link(t('Stop timer'), 'timer', 'subtask', array('timer' => 'stop', 'project_id' => $task['project_id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'])) ?> - (dt->age($subtask['timer_start_date']) ?>) - - - url->link(t('Start timer'), 'timer', 'subtask', array('timer' => 'start', 'project_id' => $task['project_id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'])) ?> - -
  • - -
-
-
    - -
  • - url->link(t('Move Up'), 'subtask', 'movePosition', array('project_id' => $project['id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'direction' => 'up'), true) ?> -
  • + + subtask->toggleStatus($subtask, 'task') ?> + + render('subtask/icons', array('subtask' => $subtask)) . $this->e($subtask['title']) ?> + +
+ + + url->link($this->e($subtask['name'] ?: $subtask['username']), 'user', 'show', array('user_id' => $subtask['user_id'])) ?> + + e($subtask['name'] ?: $subtask['username']) ?> - -
  • - url->link(t('Move Down'), 'subtask', 'movePosition', array('project_id' => $project['id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'direction' => 'down'), true) ?> -
  • + +
    +
      +
    • + + e($subtask['time_spent']).'h' ?> + + + + e($subtask['time_estimated']).'h' ?> + +
    • + user->getId()): ?> +
    • + + + url->link(t('Stop timer'), 'timer', 'subtask', array('timer' => 'stop', 'project_id' => $task['project_id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'])) ?> + (dt->age($subtask['timer_start_date']) ?>) + + + url->link(t('Start timer'), 'timer', 'subtask', array('timer' => 'start', 'project_id' => $task['project_id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'])) ?> + +
    • -
    • - url->link(t('Edit'), 'subtask', 'edit', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'subtask_id' => $subtask['id'])) ?> -
    • -
    • - url->link(t('Remove'), 'subtask', 'confirm', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'subtask_id' => $subtask['id'])) ?> -
    + +
    +
      + +
    • + url->link(t('Move Up'), 'subtask', 'movePosition', array('project_id' => $project['id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'direction' => 'up'), true) ?> +
    • + + +
    • + url->link(t('Move Down'), 'subtask', 'movePosition', array('project_id' => $project['id'], 'task_id' => $subtask['task_id'], 'subtask_id' => $subtask['id'], 'direction' => 'down'), true) ?> +
    • + +
    • + url->link(t('Edit'), 'subtask', 'edit', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'subtask_id' => $subtask['id'])) ?> +
    • +
    • + url->link(t('Remove'), 'subtask', 'confirm', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'subtask_id' => $subtask['id'])) ?> +
    • +
    +
    +
    @@ -99,4 +98,3 @@
    - diff --git a/sources/app/common.php b/sources/app/common.php index 85a2b7d..56f3c70 100644 --- a/sources/app/common.php +++ b/sources/app/common.php @@ -23,6 +23,7 @@ require __DIR__.'/constants.php'; require __DIR__.'/check_setup.php'; $container = new Pimple\Container; +$container->register(new Kanboard\ServiceProvider\SessionProvider); $container->register(new Kanboard\ServiceProvider\LoggingProvider); $container->register(new Kanboard\ServiceProvider\DatabaseProvider); $container->register(new Kanboard\ServiceProvider\ClassProvider); diff --git a/sources/app/constants.php b/sources/app/constants.php index e864493..988d759 100644 --- a/sources/app/constants.php +++ b/sources/app/constants.php @@ -8,7 +8,7 @@ defined('DEBUG_FILE') or define('DEBUG_FILE', __DIR__.DIRECTORY_SEPARATOR.'..'.D defined('PLUGINS_DIR') or define('PLUGINS_DIR', __DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'plugins'); // Application version -defined('APP_VERSION') or define('APP_VERSION', '1.0.20'); +defined('APP_VERSION') or define('APP_VERSION', '1.0.21'); // Database driver: sqlite, mysql or postgres defined('DB_DRIVER') or define('DB_DRIVER', 'sqlite'); diff --git a/sources/assets/css/app.css b/sources/assets/css/app.css index 4c10661..a1ea499 100644 --- a/sources/assets/css/app.css +++ b/sources/assets/css/app.css @@ -18,4 +18,4 @@ * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.4.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"} -.c3 svg{font:10px sans-serif}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}li,ul,ol,table,tr,td,th,p,blockquote,body{margin:0;padding:0;font-size:100%}body{margin-left:10px;margin-right:10px;padding-bottom:20px;color:#333;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;text-rendering:optimizeLegibility}.page{clear:both}ul.no-bullet li{list-style-type:none;margin-left:0}.pull-right{text-align:right}hr{border:0;height:0;border-top:1px solid rgba(0,0,0,0.1);border-bottom:1px solid rgba(255,255,255,0.3)}.chosen-select{min-height:27px}.avatar{float:left;margin-right:10px}#ui-datepicker-div{font-size:.8em}#app-loading-icon{position:fixed;right:3px;bottom:3px}.web-notification-icon{color:#36c}.web-notification-icon:focus,.web-notification-icon:hover{color:#000}a{color:#36c;border:0}a:focus{outline:0;color:#df5353;text-decoration:none;border:1px dotted #aaa}a:hover{color:#333;text-decoration:none}h1,h2,h3{font-weight:normal;color:#333}h2{font-size:1.3em;margin-bottom:10px}h3{margin-top:10px;font-size:1.2em}table{width:100%;border-collapse:collapse;border-spacing:0;margin-bottom:20px;font-size:.95em}#calendar table{margin-bottom:0}th,td{border:1px solid #eee;padding-top:.5em;padding-bottom:.5em;padding-left:3px;padding-right:3px}td{vertical-align:top}th{background:#fbfbfb;text-align:left}td li{margin-left:20px}.table-small{font-size:.8em}th a{text-decoration:none;color:#333}th a:focus,th a:hover{text-decoration:underline}.table-fixed{table-layout:fixed;white-space:nowrap}.table-fixed th{overflow:hidden}.table-fixed td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.table-stripped tr:nth-child(odd) td{background:#fefefe}.column-3{width:3%}.column-5{width:5%}.column-8{width:7.5%}.column-10{width:10%}.column-12{width:12%}.column-15{width:15%}.column-18{width:18%}.column-20{width:20%}.column-25{width:25%}.column-30{width:30%}.column-35{width:35%}.column-40{width:40%}.column-50{width:50%}.column-60{width:60%}.column-70{width:70%}form{margin-bottom:20px}label{cursor:pointer;display:block;margin-top:10px}input[type="number"],input[type="date"],input[type="email"],input[type="password"],input[type="text"]{color:#888;border:1px solid #ccc;width:300px;max-width:95%;font-size:100%;height:25px;padding-bottom:0;font-family:sans-serif;margin-top:10px;-webkit-appearance:none;appearance:none}input[type="number"]:focus,input[type="date"]:focus,input[type="email"]:focus,input[type="password"]:focus,input[type="text"]:focus,textarea:focus{color:#000;border-color:rgba(82,168,236,0.8);outline:0;box-shadow:0 0 8px rgba(82,168,236,0.6)}input.form-numeric,input[type="number"]{width:70px}textarea{border:1px solid #ccc;width:400px;max-width:99%;height:200px;font-size:100%;font-family:sans-serif}select{max-width:95%}select:focus{outline:0}::-webkit-input-placeholder{color:#ddd;padding-top:2px}::-ms-input-placeholder{color:#ddd;padding-top:2px}::-moz-placeholder{color:#ddd;padding-top:2px}.form-actions{padding-top:20px;clear:both}input.form-error,textarea.form-error{border:2px solid #b94a48}input.form-error:focus,textarea.form-error:focus{box-shadow:none;border:2px solid #b94a48}.form-required{color:red;padding-left:5px;font-weight:bold}.form-errors{color:#b94a48;list-style-type:none}ul.form-errors li{margin-left:0}.form-help{font-size:.8em;color:brown;margin-bottom:15px}.form-inline{padding:0;margin:0;border:0}.form-inline label{display:inline}.form-inline input,.form-inline select{margin:0;margin-right:15px}.form-inline .form-required{display:none}.form-inline-group{display:inline}input.form-datetime,input.form-date{width:150px}input.form-input-large{width:400px}.form-row{margin-top:10px;margin-bottom:20px}.form-column{float:left;margin-right:3%;max-width:47%}.form-column ul{margin-top:15px}.form-login{width:350px;margin:0 auto;margin-top:8%}.form-column li,.form-login li{margin-left:25px;line-height:25px}label+.form-tabs{margin-top:10px}.form-tabs{width:100%;max-width:800px}ul.form-tabs-nav{margin-bottom:8px;margin-top:0}.form-tabs-nav li{margin-left:0;display:inline}.form-tab{margin-right:20px}.form-tab a{color:#ccc;font-weight:bold;text-decoration:none}.form-tab a:focus,.form-tab a:hover{color:#000}.form-tab-selected a{color:#333}.preview-area{border:1px dashed #000;padding-top:5px;padding-left:5px;padding-right:5px;margin-bottom:5px;display:none;overflow:auto}.btn{-webkit-appearance:none;appearance:none;display:inline-block;color:#333;border:1px solid #ccc;background:#efefef;padding:5px;padding-left:15px;padding-right:15px;font-size:.9em;cursor:pointer;border-radius:2px}a.btn{text-decoration:none;font-weight:bold}.btn-small{padding:2px;padding-left:5px;padding-right:5px}.btn-red{border-color:#b0281a;background:#d14836;color:#fff}a.btn-red:hover,.btn-red:hover,.btn-red:focus{color:#fff;background:#c53727}a.btn-blue,.btn-blue{border-color:#3079ed;background:#4d90fe;color:#fff}a.btn-blue:hover,.btn-blue:hover,a.btn-blue:focus,.btn-blue:focus{border-color:#2f5bb7;background:#357ae8}.btn-blue:disabled{color:#ccc;border:1px solid #ccc;background:#f7f7f7}#main .alert,.page .alert{margin-top:10px}.alert{padding:8px 35px 8px 14px;margin-bottom:10px;color:#c09853;background-color:#fcf8e3;border:1px solid #fbeed5;border-radius:4px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-normal{color:#333;background-color:#f0f0f0;border-color:#ddd}.alert ul{margin-top:10px;margin-bottom:10px}.alert li{margin-left:25px}.tooltip-arrow:after{background:#fff;border:1px solid #aaa;box-shadow:0 0 5px #aaa}div.ui-tooltip{min-width:200px;max-width:600px;font-size:.85em}.tooltip-arrow{width:20px;height:10px;overflow:hidden;position:absolute}.tooltip-arrow.top{top:-10px}.tooltip-arrow.bottom{bottom:-10px}.tooltip-arrow.align-left{left:10px}.tooltip-arrow.align-right{right:10px}.tooltip-arrow:after{content:"";position:absolute;width:14px;height:14px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.tooltip-arrow.bottom:after{top:-10px}.tooltip-arrow.top:after{bottom:-10px}.tooltip-arrow.align-left:after{left:0}.tooltip-arrow.align-right:after{right:0}.tooltip-large{width:550px}.ui-tooltip-content .markdown p{margin-bottom:0}.tooltip .fa-info-circle{color:#999;font-size:.95em}.ui-tooltip ul{margin-left:20px}header{margin-top:10px;padding-bottom:10px;border-bottom:1px solid #dedede}header h1{margin:0;padding:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:70%;float:left}header ul{text-align:right;font-size:.9em}header li{display:inline;padding-left:30px}header a{color:#777;text-decoration:none}nav .active a{color:#333;font-weight:bold}.username a{color:#000}.username a:hover{color:#df5353;text-decoration:underline}.logo{opacity:.3;color:#d40000}.logo span{color:#333}.logo:hover{opacity:.8}.logo:focus span,.logo:hover span{color:#d40000}.page-header{margin-bottom:20px}.page-header h2{margin:0;padding:0;font-size:1.4em;font-weight:bold;border-bottom:1px dotted #ccc}.page-header h2 a{color:#ddd}.page-header h2 a:focus,.page-header h2 a:hover{color:#333}.page-header ul{text-align:left;margin-top:5px;display:inline-block}.menu-inline li,.page-header li{display:inline;padding-right:10px;font-size:.95em}.menu-inline{margin-bottom:5px}@media only screen and (max-width:640px){.page-header-mobile li{display:block;margin-bottom:5px}}.public-board{margin-top:5px}.public-task{max-width:800px;margin:0 auto;margin-top:5px}#board-container{overflow-x:auto}#board{table-layout:fixed}#board th.board-column-header{width:240px}#board td{vertical-align:top}.board-container-compact{overflow-x:initial}@media all and (-ms-high-contrast:active),(-ms-high-contrast:none){.board-container-compact #board{table-layout:auto}}#board th.board-column-header.board-column-compact{width:initial}.board-column-collapsed{display:none}td.board-column-task-collapsed{font-weight:bold;background-color:#fbfbfb}#board th.board-column-header-collapsed{width:28px;min-width:28px;text-align:center;overflow:hidden}.board-rotation-wrapper{position:relative;padding:8px 4px;min-height:150px;overflow:hidden}.board-rotation{white-space:nowrap;-webkit-backface-visibility:hidden;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);-webkit-transform-origin:0 100%;-moz-transform-origin:0 100%;-ms-transform-origin:0 100%;transform-origin:0 100%}.board-column-title{cursor:pointer}.board-add-icon{float:left;padding:0 5px}.board-add-icon a{text-decoration:none;color:#36c;font-size:150%;line-height:70%}.board-add-icon a:focus,.board-add-icon a:hover{text-decoration:none;color:red}.board-column-header-task-count{color:#999;font-weight:normal}th.board-column-header-collapsed .board-column-header-task-count{font-size:.85em}a.board-swimlane-toggle{font-size:.95em;text-decoration:none}a.board-swimlane-toggle:hover,a.board-swimlane-toggle:focus{color:#000;text-decoration:none;border:0}.board-task-list{overflow:auto;min-height:60px}.board-task-list-limit{background-color:#df5353}.draggable-item{cursor:pointer;user-select:none}.draggable-placeholder{border:2px dashed #000;background:#fafafa;height:70px;margin-bottom:10px}div.draggable-item-selected{border:1px solid #000}.task-board-sort-handle{float:left;padding-right:5px}.task-board{position:relative;margin-bottom:4px;border:1px solid #000;padding:2px;font-size:.85em;word-wrap:break-word}div.task-board-recent{box-shadow:2px 2px 3px rgba(0,0,0,0.2)}div.task-board-status-closed{user-select:none;border:1px dotted #555}.task-table a,.task-board a{color:#000;text-decoration:none;font-weight:bold}.task-table a:focus,.task-table a:hover,.task-board a:focus,.task-board a:hover{text-decoration:underline}.task-board-collapsed{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}a.task-board-collapsed-title{font-weight:normal}.task-board .dropdown{font-size:1.1em}.task-board-title{margin-top:5px;margin-bottom:5px;font-size:1.1em}.task-board-title a{font-weight:normal}.task-board-user{font-size:.8em}.task-board-current-user a{text-decoration:underline}.task-board-current-user a:focus,.task-board-current-user a:hover{text-decoration:none}a.task-board-nobody{font-weight:normal;font-style:italic;color:#444}.task-board-category-container{text-align:right}.task-board-category{font-weight:bold;font-size:.9em;color:#000;border:1px solid #555;padding:2px;padding-right:5px;padding-left:5px}.task-board-icons{text-align:right;margin-top:8px}.task-board-icons a{opacity:.5}.task-board-icons span{opacity:.5;margin-left:2px}.task-board-icons a:hover,.task-board-icons span:hover{opacity:1.0}.task-board-date{font-weight:bold;color:#000}span.task-board-date-overdue{color:#d90000;opacity:1.0}.task-score{font-weight:bold}.task-board .task-score{font-size:1.1em}.task-show-details .task-score{position:absolute;bottom:5px;right:5px;font-size:2em}.task-board-closed,.task-board-days{position:absolute;right:5px;top:5px;opacity:.5;font-size:.8em}.task-board-days:hover{opacity:1.0}.task-days-age{border:#666 1px solid;padding:1px 4px 1px 2px;border-top-left-radius:3px;border-bottom-left-radius:3px}.task-days-incolumn{border:#666 1px solid;border-left:0;margin-left:-5px;padding:1px 2px 1px 4px;border-top-right-radius:3px;border-bottom-right-radius:3px}.board-container-compact .task-board-days{display:none}.task-show-details{position:relative;border-radius:5px;padding-bottom:10px}.task-show-details h2{font-size:1.8em;margin:0;margin-bottom:25px;padding:0;padding-left:10px;padding-right:10px}.task-show-details li{margin-left:25px;list-style-type:circle}.task-show-section{margin-top:30px;margin-bottom:20px}.task-show-files a{font-weight:bold;text-decoration:none}.task-show-files li{margin-left:25px;list-style-type:square;line-height:25px}.task-show-file-actions{font-size:.75em}.task-show-file-actions:before{content:" ["}.task-show-file-actions:after{content:"]"}.task-show-file-actions a{color:#333}.task-show-description{border-left:4px solid #333;padding-left:20px}.task-show-description-textarea{width:99%;max-width:99%;height:300px}.task-file-viewer{position:relative}.task-file-viewer img{max-width:95%;max-height:85%;margin-top:10px}.task-time-form{margin-top:10px;margin-bottom:25px;padding:3px}.task-link-closed{text-decoration:line-through}.task-show-images{list-style-type:none}.task-show-images li img{width:100%}.task-show-images li .img_container{width:250px;height:100px;overflow:hidden}.task-show-images li{padding:10px;overflow:auto;width:250px;min-height:120px;display:inline-block;vertical-align:top}.task-show-images li p{padding:5px;font-weight:bold}.task-show-images li:hover{background:#eee}.task-show-image-actions{margin-left:5px}.task-show-file-table{width:auto}.task-show-start-link{color:#000}.task-show-start-link:hover,.task-show-start-link:focus{color:red}.flag-milestone{color:green}.color-picker{min-height:35px}.color-square{display:inline-block;width:30px;height:30px;margin-right:5px;margin-bottom:5px;border:1px solid #000;cursor:pointer}.color-square:hover{border-style:dotted}div.color-square-selected{border-width:2px;width:28px;height:28px;box-shadow:3px 2px 10px 0 rgba(180,180,180,0.9)}.comment{margin-bottom:20px}.comment:hover{background:#f7f8e0}.comment-inner{border-left:4px solid #333;padding-bottom:10px;padding-left:20px;margin-left:20px;margin-right:10px}.comment-preview{border:2px solid #000;border-radius:3px;padding:10px}.comment-preview .comment-inner{border:0;padding:0;margin:0}.comment-title{margin-bottom:8px;padding-bottom:3px;border-bottom:1px dotted #aaa}.ui-tooltip .comment-title{font-size:80%}.ui-tooltip .comment-inner{padding-bottom:0}.comment-actions{font-size:.8em;padding:0;text-align:right}.comment-actions li{display:inline;padding-left:5px;padding-right:5px;border-right:1px dotted #000}.comment-actions li:last-child{padding-right:0;border:0}.comment-username{font-weight:bold}.comment-textarea{height:200px;width:80%;max-width:800px}.comment-sorting{font-size:.5em}span.comment-sorting a{color:#555;font-weight:normal;text-decoration:none}span.comment-sorting a:hover{color:#aaa}#comments .comment-textarea{height:80px;width:500px}.subtasks-table{font-size:.85em}.subtasks-table td{vertical-align:middle}.markdown{line-height:1.4em;font-size:1.0}.markdown h1{margin-top:5px;margin-bottom:10px;font-size:1.5em;font-weight:bold;text-decoration:underline}.markdown h2{font-size:1.2em;font-weight:bold;text-decoration:underline}.markdown h3{font-size:1.1em;text-decoration:underline}.markdown h4{font-size:1.1em;text-decoration:underline}.markdown p{margin-bottom:10px}.markdown ol,.markdown ul{margin-left:25px;margin-top:10px;margin-bottom:10px}.markdown pre{background:#fbfbfb;padding:10px;border-radius:5px;border:1px solid #ddd;overflow:auto;color:#444}.markdown blockquote{font-style:italic;border-left:3px solid #ddd;padding-left:10px;margin-bottom:10px;margin-left:20px}.markdown img{display:block;max-width:80%;margin-top:10px}.documentation{margin:0 auto;padding:20px;max-width:850px;background:#fefefe;border:1px solid #ccc;border-radius:5px;font-size:1.1em;color:#555}.documentation img{border:1px solid #333}.documentation h1{text-decoration:none;font-size:1.8em;margin-bottom:30px}.documentation h2{font-size:1.3em;text-decoration:none;border-bottom:1px solid #ccc;margin-bottom:25px}.documentation li{line-height:30px}.listing{border-radius:4px;padding:8px 35px 8px 14px;margin-bottom:20px;border:1px solid #ddd;color:#333;background-color:#fefefe;overflow:auto}.listing li{list-style-type:square;margin-left:20px;margin-bottom:3px}.listing ul{margin-top:15px;margin-bottom:15px}.activity-event{margin-bottom:20px}.activity-datetime{color:#999;font-size:.85em}.activity-content{margin-top:10px;margin-left:20px;padding-left:20px;border-left:2px solid #666}.activity-title{font-weight:bold;color:#000}.activity-description{font-size:.9em;color:#aaa;padding-top:5px}.activity-description ul{margin-top:10px}.activity-description li{margin-left:40px;list-style-type:circle;color:#555}.activity-description .markdown{margin-top:10px;color:#555}.activity-changes{margin-top:10px;font-size:.85em}.activity-changes ul{margin-left:25px}.dashboard-project-stats span{font-size:.75em;margin-right:10px;color:#999}.dashboard-project-stats strong{font-size:1.2em}.dashboard-table-link{font-weight:bold;color:#444;text-decoration:none}.dashboard-table-link:focus,.dashboard-table-link:hover{color:#999}.pagination{text-align:center}.pagination-next{margin-left:5px}.pagination-previous{margin-right:5px}#popover-container{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.8);overflow:auto;z-index:100}#popover-content{position:absolute;width:70%;margin:0 0 0 -35%;left:50%;top:1%;padding:15px;background:#fff;overflow:auto;max-height:85%}#main .confirm{max-width:700px;font-size:1.1em}.sidebar-container{margin-top:10px;position:relative;clear:both}.sidebar-content{margin-left:23%;width:76%;position:absolute}.sidebar{width:20%;float:left;padding:10px;padding-top:0;border:1px solid #ddd;background:#fdfdfd;border-radius:5px}.sidebar li{list-style-type:square;margin-left:30px;line-height:1.8em}.sidebar li.active a{color:#000;font-weight:bold;text-decoration:none}.sidebar li.active a:focus,.sidebar li.active a:hover{text-decoration:underline}.sidebar-collapsed .sidebar{width:10px;padding-bottom:0;float:none}.sidebar-collapsed .sidebar-content{margin:0;margin-top:15px;width:100%}.sidebar-collapse{text-align:right}.sidebar-collapse a,.sidebar-expand a{color:#333;text-decoration:none}.sidebar-collapse a:hover,.sidebar-expand a:hover{color:#df5353}@media only screen and (max-width:1024px){.sidebar{width:25%}.sidebar-content{margin-left:30%;width:70%}}@media only screen and (max-width:767px){.sidebar{width:95%;float:none}.sidebar-content{margin:0;margin-top:15px;width:100%}}@media only screen and (max-width:1080px){div.filter-dropdowns .filters{margin-left:0}div.filter-dropdowns{display:block;margin-top:5px}}@media only screen and (max-width:1024px){li.hide-tablet,.hide-tablet{display:none}body{font-size:.85em}.form-tab{max-width:404px}.form-inline-group input[type="submit"],.form-inline-group label{display:block}.form-inline-group input[type="submit"]{margin-top:20px}td>input[type="text"]{max-width:150px}.task-time-form label{display:block}.task-time-form input[type="submit"]{margin-top:10px;display:block}.page-header .form-input-large{width:300px}}@media only screen and (max-width:1024px) and (orientation:landscape){header{padding-bottom:4px}div.chosen-container{font-size:.9em}input[type="number"],input[type="date"],input[type="email"],input[type="password"],input[type="text"]{height:18px}.page-header .form-input-large{width:300px}}@media only screen and (max-width:640px){.hide-mobile{display:none}}.dropdown{display:inline;position:relative}.dropdown ul{display:none}ul.dropdown-submenu-open{display:block;position:absolute;z-index:1000;min-width:285px;list-style:none;margin:3px 0 0 1px;padding:6px 0;background-color:#fff;border:1px solid #b2b2b2;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,0.15)}.dropdown-submenu-open li{display:block;margin:0;padding:0;padding-left:10px;padding-right:10px;padding-top:8px;padding-bottom:8px;font-size:.85em;border-bottom:1px solid #f8f8f8}.dropdown-submenu-open li:last-child{border:0}.dropdown-submenu-open li:hover{background:#4078c0;color:#fff}.dropdown-submenu-open li:hover a{color:#fff}.dropdown-submenu-open a{text-decoration:none;color:#333}.dropdown-submenu-open a:focus{text-decoration:underline}.page-header .dropdown{padding-right:10px}#screenshot-zone{position:relative;border:2px dashed #ccc;width:90%;height:250px;overflow:auto}#screenshot-inner{position:absolute;left:0;bottom:48%;width:100%;text-align:center}#screenshot-zone.screenshot-pasted{border:2px solid #333}.toolbar{font-size:.9em;padding-top:5px}.views{display:inline-block;margin-right:10px;font-size:.9em}.views li{border:1px solid #eee;padding-left:8px;padding-right:8px;padding-top:5px;padding-bottom:5px;display:inline}.menu-inline li.active a,.views li.active a{font-weight:bold;color:#000;text-decoration:none}.views li:first-child{border-right:0;border-top-left-radius:5px;border-bottom-left-radius:5px}.views li:last-child{border-left:0;border-top-right-radius:5px;border-bottom-right-radius:5px}.filters{display:inline-block;border:1px solid #eee;border-radius:5px;padding:5px;padding-right:10px;margin-left:8px}.filters ul{font-size:.8em}.page-header .filters ul{font-size:.9em}form.search{display:inline}div.search{margin-bottom:20px}.filter-dropdowns{font-size:.9em;display:inline-block}div.ganttview-hzheader-month,div.ganttview-hzheader-day,div.ganttview-vtheader,div.ganttview-vtheader-item-name,div.ganttview-vtheader-series,div.ganttview-grid,div.ganttview-grid-row-cell{float:left}div.ganttview-hzheader-month,div.ganttview-hzheader-day{text-align:center}div.ganttview-grid-row-cell.last,div.ganttview-hzheader-day.last,div.ganttview-hzheader-month.last{border-right:0}div.ganttview{border:1px solid #999}div.ganttview-hzheader-month{width:60px;height:20px;border-right:1px solid #d0d0d0;line-height:20px;overflow:hidden}div.ganttview-hzheader-day{width:20px;height:20px;border-right:1px solid #f0f0f0;border-top:1px solid #d0d0d0;line-height:20px;color:#777}div.ganttview-vtheader{margin-top:41px;width:400px;overflow:hidden;background-color:#fff}div.ganttview-vtheader-item{color:#666}div.ganttview-vtheader-series-name{width:400px;height:31px;line-height:31px;padding-left:3px;border-top:1px solid #d0d0d0;font-size:.9em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}div.ganttview-vtheader-series-name a{color:#666;text-decoration:none}div.ganttview-vtheader-series-name a:hover{color:#333;text-decoration:underline}div.ganttview-vtheader-series-name a i{color:#000}div.ganttview-vtheader-series-name a:hover i{color:#666}div.ganttview-slide-container{overflow:auto;border-left:1px solid #999}div.ganttview-grid-row-cell{width:20px;height:31px;border-right:1px solid #f0f0f0;border-top:1px solid #f0f0f0}div.ganttview-grid-row-cell.ganttview-weekend{background-color:#fafafa}div.ganttview-blocks{margin-top:40px}div.ganttview-block-container{height:28px;padding-top:4px}div.ganttview-block{position:relative;height:25px;background-color:#e5ecf9;border:1px solid silver;border-radius:3px}.ganttview-block-movable{cursor:move}div.ganttview-block-not-defined{border-color:#000;background-color:#000}div.ganttview-block-text{position:absolute;height:12px;font-size:.7em;color:#999;padding:2px 3px}div.ganttview-block div.ui-resizable-handle.ui-resizable-s{bottom:-0} \ No newline at end of file +.c3 svg{font:10px sans-serif}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}li,ul,ol,table,tr,td,th,p,blockquote,body{margin:0;padding:0;font-size:100%}body{margin-left:10px;margin-right:10px;padding-bottom:20px;color:#333;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;text-rendering:optimizeLegibility}.page{clear:both}ul.no-bullet li{list-style-type:none;margin-left:0}.pull-right{text-align:right}hr{border:0;height:0;border-top:1px solid rgba(0,0,0,0.1);border-bottom:1px solid rgba(255,255,255,0.3)}.chosen-select{min-height:27px}.avatar{float:left;margin-right:10px}#ui-datepicker-div{font-size:.8em}#app-loading-icon{position:fixed;right:3px;bottom:3px}.web-notification-icon{color:#36c}.web-notification-icon:focus,.web-notification-icon:hover{color:#000}a{color:#36c;border:0}a:focus{outline:0;color:#df5353;text-decoration:none;border:1px dotted #aaa}a:hover{color:#333;text-decoration:none}h1,h2,h3{font-weight:normal;color:#333}h2{font-size:1.3em;margin-bottom:10px}h3{margin-top:10px;font-size:1.2em}table{width:100%;border-collapse:collapse;border-spacing:0;margin-bottom:20px;font-size:.95em}#calendar table{margin-bottom:0}th,td{border:1px solid #eee;padding-top:.5em;padding-bottom:.5em;padding-left:3px;padding-right:3px}td{vertical-align:top}th{background:#fbfbfb;text-align:left}td li{margin-left:20px}.table-small{font-size:.8em}th a{text-decoration:none;color:#333}th a:focus,th a:hover{text-decoration:underline}.table-fixed{table-layout:fixed;white-space:nowrap}.table-fixed th{overflow:hidden}.table-fixed td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.table-stripped tr:nth-child(odd) td{background:#fefefe}.column-3{width:3%}.column-5{width:5%}.column-8{width:7.5%}.column-10{width:10%}.column-12{width:12%}.column-15{width:15%}.column-18{width:18%}.column-20{width:20%}.column-25{width:25%}.column-30{width:30%}.column-35{width:35%}.column-40{width:40%}.column-50{width:50%}.column-60{width:60%}.column-70{width:70%}form{margin-bottom:20px}label{cursor:pointer;display:block;margin-top:10px}input[type="number"],input[type="date"],input[type="email"],input[type="password"],input[type="text"]{color:#888;border:1px solid #ccc;width:300px;max-width:95%;font-size:100%;height:25px;padding-bottom:0;font-family:sans-serif;margin-top:10px;-webkit-appearance:none;appearance:none}input[type="number"]:focus,input[type="date"]:focus,input[type="email"]:focus,input[type="password"]:focus,input[type="text"]:focus,textarea:focus{color:#000;border-color:rgba(82,168,236,0.8);outline:0;box-shadow:0 0 8px rgba(82,168,236,0.6)}input.form-numeric,input[type="number"]{width:70px}textarea{border:1px solid #ccc;width:400px;max-width:99%;height:200px;font-size:100%;font-family:sans-serif}select{max-width:95%}select:focus{outline:0}::-webkit-input-placeholder{color:#ddd;padding-top:2px}::-ms-input-placeholder{color:#ddd;padding-top:2px}::-moz-placeholder{color:#ddd;padding-top:2px}.form-actions{padding-top:20px;clear:both}input.form-error,textarea.form-error{border:2px solid #b94a48}input.form-error:focus,textarea.form-error:focus{box-shadow:none;border:2px solid #b94a48}.form-required{color:red;padding-left:5px;font-weight:bold}.form-errors{color:#b94a48;list-style-type:none}ul.form-errors li{margin-left:0}.form-help{font-size:.8em;color:brown;margin-bottom:15px}.form-inline{padding:0;margin:0;border:0}.form-inline label{display:inline}.form-inline input,.form-inline select{margin:0;margin-right:15px}.form-inline .form-required{display:none}.form-inline-group{display:inline}input.form-datetime,input.form-date{width:150px}input.form-input-large{width:400px}.form-row{margin-top:10px;margin-bottom:20px}.form-column{float:left;margin-right:3%;max-width:47%}.form-column ul{margin-top:15px}.form-login{width:350px;margin:0 auto;margin-top:8%}.form-column li,.form-login li{margin-left:25px;line-height:25px}label+.form-tabs{margin-top:10px}.form-tabs{width:100%;max-width:800px}ul.form-tabs-nav{margin-bottom:8px;margin-top:0}.form-tabs-nav li{margin-left:0;display:inline}.form-tab{margin-right:20px}.form-tab a{color:#ccc;font-weight:bold;text-decoration:none}.form-tab a:focus,.form-tab a:hover{color:#000}.form-tab-selected a{color:#333}.preview-area{border:1px dashed #000;padding-top:5px;padding-left:5px;padding-right:5px;margin-bottom:5px;display:none;overflow:auto}.btn{-webkit-appearance:none;appearance:none;display:inline-block;color:#333;border:1px solid #ccc;background:#efefef;padding:5px;padding-left:15px;padding-right:15px;font-size:.9em;cursor:pointer;border-radius:2px}a.btn{text-decoration:none;font-weight:bold}.btn-small{padding:2px;padding-left:5px;padding-right:5px}.btn-red{border-color:#b0281a;background:#d14836;color:#fff}a.btn-red:hover,.btn-red:hover,.btn-red:focus{color:#fff;background:#c53727}a.btn-blue,.btn-blue{border-color:#3079ed;background:#4d90fe;color:#fff}a.btn-blue:hover,.btn-blue:hover,a.btn-blue:focus,.btn-blue:focus{border-color:#2f5bb7;background:#357ae8}.btn-blue:disabled{color:#ccc;border:1px solid #ccc;background:#f7f7f7}#main .alert,.page .alert{margin-top:10px}.alert{padding:8px 35px 8px 14px;margin-bottom:10px;color:#c09853;background-color:#fcf8e3;border:1px solid #fbeed5;border-radius:4px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-normal{color:#333;background-color:#f0f0f0;border-color:#ddd}.alert ul{margin-top:10px;margin-bottom:10px}.alert li{margin-left:25px}.tooltip-arrow:after{background:#fff;border:1px solid #aaa;box-shadow:0 0 5px #aaa}div.ui-tooltip{min-width:200px;max-width:600px;font-size:.85em}.tooltip-arrow{width:20px;height:10px;overflow:hidden;position:absolute}.tooltip-arrow.top{top:-10px}.tooltip-arrow.bottom{bottom:-10px}.tooltip-arrow.align-left{left:10px}.tooltip-arrow.align-right{right:10px}.tooltip-arrow:after{content:"";position:absolute;width:14px;height:14px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.tooltip-arrow.bottom:after{top:-10px}.tooltip-arrow.top:after{bottom:-10px}.tooltip-arrow.align-left:after{left:0}.tooltip-arrow.align-right:after{right:0}.tooltip-large{width:550px}.ui-tooltip-content .markdown p{margin-bottom:0}.tooltip .fa-info-circle{color:#999;font-size:.95em}.ui-tooltip ul{margin-left:20px}header{margin-top:10px;padding-bottom:10px;border-bottom:1px solid #dedede}header h1{margin:0;padding:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:70%;float:left}header ul{text-align:right;font-size:.9em}header li{display:inline;padding-left:30px}header a{color:#777;text-decoration:none}nav .active a{color:#333;font-weight:bold}.username a{color:#000}.username a:hover{color:#df5353;text-decoration:underline}.logo{opacity:.3;color:#d40000}.logo span{color:#333}.logo:hover{opacity:.8}.logo:focus span,.logo:hover span{color:#d40000}.page-header{margin-bottom:20px}.page-header h2{margin:0;padding:0;font-size:1.4em;font-weight:bold;border-bottom:1px dotted #ccc}.page-header h2 a{color:#ddd}.page-header h2 a:focus,.page-header h2 a:hover{color:#333}.page-header ul{text-align:left;margin-top:5px;display:inline-block}.menu-inline li,.page-header li{display:inline;padding-right:10px;font-size:.95em}.menu-inline{margin-bottom:5px}@media only screen and (max-width:640px){.page-header-mobile li{display:block;margin-bottom:5px}}.public-board{margin-top:5px}.public-task{max-width:800px;margin:0 auto;margin-top:5px}#board-container{overflow-x:auto}#board{table-layout:fixed}#board th.board-column-header{width:240px}#board td{vertical-align:top}.board-container-compact{overflow-x:initial}@media all and (-ms-high-contrast:active),(-ms-high-contrast:none){.board-container-compact #board{table-layout:auto}}#board th.board-column-header.board-column-compact{width:initial}.board-column-collapsed{display:none}td.board-column-task-collapsed{font-weight:bold;background-color:#fbfbfb}#board th.board-column-header-collapsed{width:28px;min-width:28px;text-align:center;overflow:hidden}.board-rotation-wrapper{position:relative;padding:8px 4px;min-height:150px;overflow:hidden}.board-rotation{white-space:nowrap;-webkit-backface-visibility:hidden;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);-webkit-transform-origin:0 100%;-moz-transform-origin:0 100%;-ms-transform-origin:0 100%;transform-origin:0 100%}.board-column-title{cursor:pointer}.board-add-icon{float:left;padding:0 5px}.board-add-icon a{text-decoration:none;color:#36c;font-size:150%;line-height:70%}.board-add-icon a:focus,.board-add-icon a:hover{text-decoration:none;color:red}.board-column-header-task-count{color:#999;font-weight:normal}th.board-column-header-collapsed .board-column-header-task-count{font-size:.85em}a.board-swimlane-toggle{font-size:.95em;text-decoration:none}a.board-swimlane-toggle:hover,a.board-swimlane-toggle:focus{color:#000;text-decoration:none;border:0}.board-task-list{overflow:auto;min-height:60px}.board-task-list-limit{background-color:#df5353}.draggable-item{cursor:pointer;user-select:none}.draggable-placeholder{border:2px dashed #000;background:#fafafa;height:70px;margin-bottom:10px}div.draggable-item-selected{border:1px solid #000}.task-board-sort-handle{float:left;padding-right:5px}.task-board{position:relative;margin-bottom:4px;border:1px solid #000;padding:2px;font-size:.85em;word-wrap:break-word}div.task-board-recent{box-shadow:2px 2px 3px rgba(0,0,0,0.2)}div.task-board-status-closed{user-select:none;border:1px dotted #555}.task-table a,.task-board a{color:#000;text-decoration:none;font-weight:bold}.task-table a:focus,.task-table a:hover,.task-board a:focus,.task-board a:hover{text-decoration:underline}.task-board-collapsed{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}a.task-board-collapsed-title{font-weight:normal}.task-board .dropdown{font-size:1.1em}.task-board-title{margin-top:5px;margin-bottom:5px;font-size:1.1em}.task-board-title a{font-weight:normal}.task-board-user{font-size:.8em}.task-board-current-user a{text-decoration:underline}.task-board-current-user a:focus,.task-board-current-user a:hover{text-decoration:none}a.task-board-nobody{font-weight:normal;font-style:italic;color:#444}.task-board-category-container{text-align:right}.task-board-category{font-weight:bold;font-size:.9em;color:#000;border:1px solid #555;padding:2px;padding-right:5px;padding-left:5px}.task-board-icons{text-align:right;margin-top:8px}.task-board-icons a{opacity:.5}.task-board-icons span{opacity:.5;margin-left:2px}.task-board-icons a:hover,.task-board-icons span:hover{opacity:1.0}.task-board-date{font-weight:bold;color:#000}span.task-board-date-overdue{color:#d90000;opacity:1.0}.task-score{font-weight:bold}.task-board .task-score{font-size:1.1em}.task-show-details .task-score{position:absolute;bottom:5px;right:5px;font-size:2em}.task-board-closed,.task-board-days{position:absolute;right:5px;top:5px;opacity:.5;font-size:.8em}.task-board-days:hover{opacity:1.0}.task-days-age{border:#666 1px solid;padding:1px 4px 1px 2px;border-top-left-radius:3px;border-bottom-left-radius:3px}.task-days-incolumn{border:#666 1px solid;border-left:0;margin-left:-5px;padding:1px 2px 1px 4px;border-top-right-radius:3px;border-bottom-right-radius:3px}.board-container-compact .task-board-days{display:none}.task-show-details{position:relative;border-radius:5px;padding-bottom:10px}.task-show-details h2{font-size:1.8em;margin:0;margin-bottom:25px;padding:0;padding-left:10px;padding-right:10px}.task-show-details li{margin-left:25px;list-style-type:circle}.task-show-section{margin-top:30px;margin-bottom:20px}.task-show-files a{font-weight:bold;text-decoration:none}.task-show-files li{margin-left:25px;list-style-type:square;line-height:25px}.task-show-file-actions{font-size:.75em}.task-show-file-actions:before{content:" ["}.task-show-file-actions:after{content:"]"}.task-show-file-actions a{color:#333}.task-show-description{border-left:4px solid #333;padding-left:20px}.task-show-description-textarea{width:99%;max-width:99%;height:300px}.task-file-viewer{position:relative}.task-file-viewer img{max-width:95%;max-height:85%;margin-top:10px}.task-time-form{margin-top:10px;margin-bottom:25px;padding:3px}.task-link-closed{text-decoration:line-through}.task-show-images{list-style-type:none}.task-show-images li img{width:100%}.task-show-images li .img_container{width:250px;height:100px;overflow:hidden}.task-show-images li{padding:10px;overflow:auto;width:250px;min-height:120px;display:inline-block;vertical-align:top}.task-show-images li p{padding:5px;font-weight:bold}.task-show-images li:hover{background:#eee}.task-show-image-actions{margin-left:5px}.task-show-file-table{width:auto}.task-show-start-link{color:#000}.task-show-start-link:hover,.task-show-start-link:focus{color:red}.flag-milestone{color:green}.color-picker{min-height:35px}.color-square{display:inline-block;width:30px;height:30px;margin-right:5px;margin-bottom:5px;border:1px solid #000;cursor:pointer}.color-square:hover{border-style:dotted}div.color-square-selected{border-width:2px;width:28px;height:28px;box-shadow:3px 2px 10px 0 rgba(180,180,180,0.9)}.comment{margin-bottom:20px}.comment:hover{background:#f7f8e0}.comment-inner{border-left:4px solid #333;padding-bottom:10px;padding-left:20px;margin-left:20px;margin-right:10px}.comment-preview{border:2px solid #000;border-radius:3px;padding:10px}.comment-preview .comment-inner{border:0;padding:0;margin:0}.comment-title{margin-bottom:8px;padding-bottom:3px;border-bottom:1px dotted #aaa}.ui-tooltip .comment-title{font-size:80%}.ui-tooltip .comment-inner{padding-bottom:0}.comment-actions{font-size:.8em;padding:0;text-align:right}.comment-actions li{display:inline;padding-left:5px;padding-right:5px;border-right:1px dotted #000}.comment-actions li:last-child{padding-right:0;border:0}.comment-username{font-weight:bold}.comment-textarea{height:200px;width:80%;max-width:800px}.comment-sorting{font-size:.5em}span.comment-sorting a{color:#555;font-weight:normal;text-decoration:none}span.comment-sorting a:hover{color:#aaa}#comments .comment-textarea{height:80px;width:500px}.subtasks-table{font-size:.85em}.subtasks-table td{vertical-align:middle}.markdown{line-height:1.4em;font-size:1.0}.markdown h1{margin-top:5px;margin-bottom:10px;font-size:1.5em;font-weight:bold;text-decoration:underline}.markdown h2{font-size:1.2em;font-weight:bold;text-decoration:underline}.markdown h3{font-size:1.1em;text-decoration:underline}.markdown h4{font-size:1.1em;text-decoration:underline}.markdown p{margin-bottom:10px}.markdown ol,.markdown ul{margin-left:25px;margin-top:10px;margin-bottom:10px}.markdown pre{background:#fbfbfb;padding:10px;border-radius:5px;border:1px solid #ddd;overflow:auto;color:#444}.markdown blockquote{font-style:italic;border-left:3px solid #ddd;padding-left:10px;margin-bottom:10px;margin-left:20px}.markdown img{display:block;max-width:80%;margin-top:10px}.documentation{margin:0 auto;padding:20px;max-width:850px;background:#fefefe;border:1px solid #ccc;border-radius:5px;font-size:1.1em;color:#555}.documentation img{border:1px solid #333}.documentation h1{text-decoration:none;font-size:1.8em;margin-bottom:30px}.documentation h2{font-size:1.3em;text-decoration:none;border-bottom:1px solid #ccc;margin-bottom:25px}.documentation li{line-height:30px}.listing{border-radius:4px;padding:8px 35px 8px 14px;margin-bottom:20px;border:1px solid #ddd;color:#333;background-color:#fefefe;overflow:auto}.listing li{list-style-type:square;margin-left:20px;margin-bottom:3px}.listing ul{margin-top:15px;margin-bottom:15px}.activity-event{margin-bottom:20px}.activity-datetime{color:#999;font-size:.85em}.activity-content{margin-top:10px;margin-left:20px;padding-left:20px;border-left:2px solid #666}.activity-title{font-weight:bold;color:#000}.activity-description{font-size:.9em;color:#aaa;padding-top:5px}.activity-description ul{margin-top:10px}.activity-description li{margin-left:40px;list-style-type:circle;color:#555}.activity-description .markdown{margin-top:10px;color:#555}.activity-changes{margin-top:10px;font-size:.85em}.activity-changes ul{margin-left:25px}.dashboard-project-stats span{font-size:.75em;margin-right:10px;color:#999}.dashboard-project-stats strong{font-size:1.2em}.dashboard-table-link{font-weight:bold;color:#444;text-decoration:none}.dashboard-table-link:focus,.dashboard-table-link:hover{color:#999}.pagination{text-align:center}.pagination-next{margin-left:5px}.pagination-previous{margin-right:5px}#popover-container{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.8);overflow:auto;z-index:100}#popover-content{position:absolute;width:70%;margin:0 0 0 -35%;left:50%;top:1%;padding:15px;background:#fff;overflow:auto;max-height:85%}#main .confirm{max-width:700px;font-size:1.1em}.sidebar-container{margin-top:10px;position:relative;clear:both}.sidebar-content{margin-left:23%;width:76%;position:absolute}.sidebar{width:20%;float:left;padding:10px;padding-top:0;border:1px solid #ddd;background:#fdfdfd;border-radius:5px}.sidebar li{list-style-type:square;margin-left:30px;line-height:1.8em}.sidebar li.active a{color:#000;font-weight:bold;text-decoration:none}.sidebar li.active a:focus,.sidebar li.active a:hover{text-decoration:underline}.sidebar-collapsed .sidebar{width:10px;padding-bottom:0;float:none}.sidebar-collapsed .sidebar-content{margin:0;margin-top:15px;width:100%}.sidebar-collapse{text-align:right}.sidebar-collapse a,.sidebar-expand a{color:#333;text-decoration:none}.sidebar-collapse a:hover,.sidebar-expand a:hover{color:#df5353}@media only screen and (max-width:1024px){.sidebar{width:25%}.sidebar-content{margin-left:30%;width:70%}}@media only screen and (max-width:767px){.sidebar{width:95%;float:none}.sidebar-content{margin:0;margin-top:15px;width:100%}}@media only screen and (max-width:1080px){div.filter-dropdowns .filters{margin-left:0}div.filter-dropdowns{display:block;margin-top:5px}}@media only screen and (max-width:1024px){li.hide-tablet,.hide-tablet{display:none}body{font-size:.85em}.form-tab{max-width:404px}.form-inline-group input[type="submit"],.form-inline-group label{display:block}.form-inline-group input[type="submit"]{margin-top:20px}td>input[type="text"]{max-width:150px}.task-time-form label{display:block}.task-time-form input[type="submit"]{margin-top:10px;display:block}.page-header .form-input-large{width:300px}}@media only screen and (max-width:1024px) and (orientation:landscape){header{padding-bottom:4px}div.chosen-container{font-size:.9em}input[type="number"],input[type="date"],input[type="email"],input[type="password"],input[type="text"]{height:18px}.page-header .form-input-large{width:300px}}@media only screen and (max-width:640px){.hide-mobile{display:none}}.dropdown{display:inline;position:relative}.dropdown ul{display:none}ul.dropdown-submenu-open{display:block;position:absolute;z-index:1000;min-width:285px;list-style:none;margin:3px 0 0 1px;padding:6px 0;background-color:#fff;border:1px solid #b2b2b2;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,0.15)}.dropdown-submenu-open li{display:block;margin:0;padding:0;padding-left:10px;padding-right:10px;padding-top:8px;padding-bottom:8px;font-size:.85em;border-bottom:1px solid #f8f8f8;cursor:pointer}.dropdown-submenu-open li:last-child{border:0}.dropdown-submenu-open li:hover{background:#4078c0;color:#fff}.dropdown-submenu-open li:hover a{color:#fff}.dropdown-submenu-open a{text-decoration:none;color:#333}.dropdown-submenu-open a:focus{text-decoration:underline}.page-header .dropdown{padding-right:10px}#screenshot-zone{position:relative;border:2px dashed #ccc;width:90%;height:250px;overflow:auto}#screenshot-inner{position:absolute;left:0;bottom:48%;width:100%;text-align:center}#screenshot-zone.screenshot-pasted{border:2px solid #333}.toolbar{font-size:.9em;padding-top:5px}.views{display:inline-block;margin-right:10px;font-size:.9em}.views li{border:1px solid #eee;padding-left:8px;padding-right:8px;padding-top:5px;padding-bottom:5px;display:inline}.menu-inline li.active a,.views li.active a{font-weight:bold;color:#000;text-decoration:none}.views li:first-child{border-right:0;border-top-left-radius:5px;border-bottom-left-radius:5px}.views li:last-child{border-left:0;border-top-right-radius:5px;border-bottom-right-radius:5px}.filters{display:inline-block;border:1px solid #eee;border-radius:5px;padding:5px;padding-right:10px;margin-left:8px}.filters ul{font-size:.8em}.page-header .filters ul{font-size:.9em}form.search{display:inline}div.search{margin-bottom:20px}.filter-dropdowns{font-size:.9em;display:inline-block}div.ganttview-hzheader-month,div.ganttview-hzheader-day,div.ganttview-vtheader,div.ganttview-vtheader-item-name,div.ganttview-vtheader-series,div.ganttview-grid,div.ganttview-grid-row-cell{float:left}div.ganttview-hzheader-month,div.ganttview-hzheader-day{text-align:center}div.ganttview-grid-row-cell.last,div.ganttview-hzheader-day.last,div.ganttview-hzheader-month.last{border-right:0}div.ganttview{border:1px solid #999}div.ganttview-hzheader-month{width:60px;height:20px;border-right:1px solid #d0d0d0;line-height:20px;overflow:hidden}div.ganttview-hzheader-day{width:20px;height:20px;border-right:1px solid #f0f0f0;border-top:1px solid #d0d0d0;line-height:20px;color:#777}div.ganttview-vtheader{margin-top:41px;width:400px;overflow:hidden;background-color:#fff}div.ganttview-vtheader-item{color:#666}div.ganttview-vtheader-series-name{width:400px;height:31px;line-height:31px;padding-left:3px;border-top:1px solid #d0d0d0;font-size:.9em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}div.ganttview-vtheader-series-name a{color:#666;text-decoration:none}div.ganttview-vtheader-series-name a:hover{color:#333;text-decoration:underline}div.ganttview-vtheader-series-name a i{color:#000}div.ganttview-vtheader-series-name a:hover i{color:#666}div.ganttview-slide-container{overflow:auto;border-left:1px solid #999}div.ganttview-grid-row-cell{width:20px;height:31px;border-right:1px solid #f0f0f0;border-top:1px solid #f0f0f0}div.ganttview-grid-row-cell.ganttview-weekend{background-color:#fafafa}div.ganttview-blocks{margin-top:40px}div.ganttview-block-container{height:28px;padding-top:4px}div.ganttview-block{position:relative;height:25px;background-color:#e5ecf9;border:1px solid silver;border-radius:3px}.ganttview-block-movable{cursor:move}div.ganttview-block-not-defined{border-color:#000;background-color:#000}div.ganttview-block-text{position:absolute;height:12px;font-size:.7em;color:#999;padding:2px 3px}div.ganttview-block div.ui-resizable-handle.ui-resizable-s{bottom:-0} \ No newline at end of file diff --git a/sources/assets/css/src/dropdown.css b/sources/assets/css/src/dropdown.css index 30e5c22..7839dbc 100644 --- a/sources/assets/css/src/dropdown.css +++ b/sources/assets/css/src/dropdown.css @@ -31,6 +31,7 @@ ul.dropdown-submenu-open { padding-bottom: 8px; font-size: 0.85em; border-bottom: 1px solid #f8f8f8; + cursor: pointer; } .dropdown-submenu-open li:last-child { diff --git a/sources/assets/js/app.js b/sources/assets/js/app.js index d5e9085..d942b64 100644 --- a/sources/assets/js/app.js +++ b/sources/assets/js/app.js @@ -51,4 +51,4 @@ c,a,e),l[d.key][c?"unshift":"push"]({callback:b,modifiers:d.modifiers,action:d.a unbind:function(a,b){return m.bind(a,function(){},b)},trigger:function(a,b){if(q[a+":"+b])q[a+":"+b]({},a);return this},reset:function(){l={};q={};return this},stopCallback:function(a,b){return-1<(" "+b.className+" ").indexOf(" mousetrap ")?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable},handleKey:function(a,b,d){var c=C(a,b,d),e;b={};var f=0,g=!1;for(e=0;eel día",eventLimitText:"más"})});!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};r.prototype.open=function(w){var v=this;v.app.dropdown.close();$.get(w,function(x){$("body").append('
    '+x+"
    ");v.app.refresh();v.router.dispatch(this.app);v.afterOpen()})};r.prototype.close=function(v){if(this.isOpen()){if(v){v.preventDefault()}$("#popover-container").remove()}};r.prototype.onClick=function(w){w.preventDefault();w.stopPropagation();var v=w.target.getAttribute("href");if(!v){v=w.target.getAttribute("data-href")}if(v){this.open(v)}};r.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(v){v.stopPropagation()})};r.prototype.afterOpen=function(){var v=this;var w=$("#task-form");if(w){w.on("submit",function(x){x.preventDefault();$.ajax({type:"POST",url:w.attr("action"),data:w.serialize(),success:function(z,A,y){if(y.getResponseHeader("X-Ajax-Redirect")){window.location=y.getResponseHeader("X-Ajax-Redirect")}else{$("#popover-content").html(z);v.afterOpen()}}})})}};function p(){}p.prototype.listen=function(){var v=this;$(document).on("click",function(){v.close()});$(document).on("click",".dropdown-menu",function(z){z.preventDefault();z.stopImmediatePropagation();v.close();var x=$(this).next("ul");var y=240;var A=$(this).offset();var w=$(this).height();$("body").append(jQuery("
    ",{id:"dropdown"}));x.clone().appendTo("#dropdown");var B=$("#dropdown ul");B.css("left",A.left);if(A.top+y-$(window).scrollTop()>$(window).height()){B.css("top",A.top-y-w)}else{B.css("top",A.top+w)}B.addClass("dropdown-submenu-open")})};p.prototype.close=function(){$("#dropdown").remove()};function o(v){this.app=v}o.prototype.listen=function(){var v=this;$(".tooltip").tooltip({track:false,show:false,hide:false,position:{my:"left-20 top",at:"center bottom+9",using:function(w,x){$(this).css(w);var y=x.target.left+x.target.width/2-x.element.left-20;$("
    ").addClass("tooltip-arrow").addClass(x.vertical).addClass(y<1?"align-left":"align-right").appendTo(this)}},content:function(){var y=this;var w=$(this).attr("data-href");if(!w){return'
    '+$(this).attr("title")+"
    "}$.get(w,function x(B){var A=$(".ui-tooltip:visible");$(".ui-tooltip-content:visible").html(B);A.css({top:"",left:""});A.children(".tooltip-arrow").remove();var z=$(y).tooltip("option","position");z.of=$(y);A.position(z);$("#tooltip-subtasks a").not(".popover").click(function(C){C.preventDefault();C.stopPropagation();if($(this).hasClass("popover-subtask-restriction")){v.app.popover.open($(this).attr("href"));$(y).tooltip("close")}else{$.get($(this).attr("href"),x)}})});return''}}).on("mouseenter",function(){var w=this;$(this).tooltip("open");$(".ui-tooltip").on("mouseleave",function(){$(w).tooltip("close")})}).on("mouseleave focusout",function(w){w.stopImmediatePropagation();var x=this;setTimeout(function(){if(!$(".ui-tooltip:hover").length){$(x).tooltip("close")}},100)})};function k(){}k.prototype.showPreview=function(z){z.preventDefault();var w=$(".write-area");var y=$(".preview-area");var v=$("textarea");$("#markdown-write").parent().removeClass("form-tab-selected");$("#markdown-preview").parent().addClass("form-tab-selected");var x=$.ajax({url:$("body").data("markdown-preview-url"),contentType:"application/json",type:"POST",processData:false,dataType:"html",data:JSON.stringify({text:v.val()})});x.done(function(A){y.find(".markdown").html(A);y.css("height",v.css("height"));y.css("width",v.css("width"));w.hide();y.show()})};k.prototype.showWriter=function(v){v.preventDefault();$("#markdown-write").parent().addClass("form-tab-selected");$("#markdown-preview").parent().removeClass("form-tab-selected");$(".write-area").show();$(".preview-area").hide()};k.prototype.listen=function(){$(document).on("click","#markdown-preview",this.showPreview.bind(this));$(document).on("click","#markdown-write",this.showWriter.bind(this))};function b(){}b.prototype.expand=function(v){v.preventDefault();$(".sidebar-container").removeClass("sidebar-collapsed");$(".sidebar-collapse").show();$(".sidebar h2").show();$(".sidebar ul").show();$(".sidebar-expand").hide()};b.prototype.collapse=function(v){v.preventDefault();$(".sidebar-container").addClass("sidebar-collapsed");$(".sidebar-expand").show();$(".sidebar h2").hide();$(".sidebar ul").hide();$(".sidebar-collapse").hide()};b.prototype.listen=function(){$(document).on("click",".sidebar-collapse",this.collapse);$(document).on("click",".sidebar-expand",this.expand)};function f(v){this.app=v;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 v=this;$(document).on("click",".filter-helper",function(y){y.preventDefault();var x=$(this).data("filter");var w=$(this).data("append-filter");if(w){x=$("#form-search").val()+" "+w}$("#form-search").val(x);if($("#board").length){v.app.board.reloadFilters(x)}else{$("form.search").submit()}})};f.prototype.keyboardShortcuts=function(){var v=this;Mousetrap.bind("v b",function(x){var w=$(".view-board");if(w.length){window.location=w.attr("href")}});Mousetrap.bind("v c",function(x){var w=$(".view-calendar");if(w.length){window.location=w.attr("href")}});Mousetrap.bind("v l",function(x){var w=$(".view-listing");if(w.length){window.location=w.attr("href")}});Mousetrap.bind("v g",function(x){var w=$(".view-gantt");if(w.length){window.location=w.attr("href")}});Mousetrap.bind("f",function(x){x.preventDefault();var w=document.getElementById("form-search");if(w){w.focus()}});Mousetrap.bind("r",function(x){x.preventDefault();var w=$(".filter-reset").data("filter");$("#form-search").val(w);if($("#board").length){v.app.board.reloadFilters(w)}else{$("form.search").submit()}})};function l(){this.board=new j(this);this.markdown=new k();this.sidebar=new b();this.search=new f(this);this.swimlane=new g();this.dropdown=new p();this.tooltip=new o(this);this.popover=new r(this);this.task=new a();this.keyboardShortcuts();this.chosen();this.poll();$(".alert-fade-out").delay(4000).fadeOut(800,function(){$(this).remove()});var v=false;$("select.task-reload-project-destination").change(function(){if(!v){$(".loading-icon").show();v=true;window.location=$(this).data("redirect").replace(/PROJECT_ID/g,$(this).val())}})}l.prototype.listen=function(){this.popover.listen();this.markdown.listen();this.sidebar.listen();this.tooltip.listen();this.dropdown.listen();this.search.listen();this.task.listen();this.swimlane.listen();this.search.focus();this.taskAutoComplete();this.datePicker();this.focus()};l.prototype.refresh=function(){$(document).off();this.listen()};l.prototype.focus=function(){$("[autofocus]").each(function(v,w){$(this).focus()});$(document).on("focus",".auto-select",function(){$(this).select()});$(document).on("mouseup",".auto-select",function(v){v.preventDefault()})};l.prototype.poll=function(){window.setInterval(this.checkSession,60000)};l.prototype.keyboardShortcuts=function(){var v=this;Mousetrap.bindGlobal("mod+enter",function(){$("form").submit()});Mousetrap.bind("b",function(w){w.preventDefault();$("#board-selector").trigger("chosen:open")});Mousetrap.bindGlobal("esc",function(){v.popover.close();v.dropdown.close()})};l.prototype.checkSession=function(){if(!$(".form-login").length){$.ajax({cache:false,url:$("body").data("status-url"),statusCode:{401:function(){window.location=$("body").data("login-url")}}})}};l.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});$(".hasDatepicker").on("blur",function(v){$(this).datepicker("hide")})};l.prototype.taskAutoComplete=function(){if($(".task-autocomplete").length){if($(".opposite_task_id").val()==""){$(".task-autocomplete").parent().find("input[type=submit]").attr("disabled","disabled")}$(".task-autocomplete").autocomplete({source:$(".task-autocomplete").data("search-url"),minLength:1,select:function(v,w){var x=$(".task-autocomplete").data("dst-field");$("input[name="+x+"]").val(w.item.id);$(".task-autocomplete").parent().find("input[type=submit]").removeAttr("disabled")}})}};l.prototype.chosen=function(){$(".chosen-select").chosen({width:"180px",no_results_text:$(".chosen-select").data("notfound"),disable_search_threshold:10});$(".select-auto-redirect").change(function(){var v=new RegExp($(this).data("redirect-regex"),"g");window.location=$(this).data("redirect-url").replace(v,$(this).val())})};l.prototype.showLoadingIcon=function(){$("body").append(' ')};l.prototype.hideLoadingIcon=function(){$("#app-loading-icon").remove()};l.prototype.isVisible=function(){var v="";if(typeof document.hidden!=="undefined"){v="visibilityState"}else{if(typeof document.mozHidden!=="undefined"){v="mozVisibilityState"}else{if(typeof document.msHidden!=="undefined"){v="msVisibilityState"}else{if(typeof document.webkitHidden!=="undefined"){v="webkitVisibilityState"}}}}if(v!=""){return document[v]=="visible"}return true};l.prototype.formatDuration=function(v){if(v>=86400){return Math.round(v/86400)+"d"}else{if(v>=3600){return Math.round(v/3600)+"h"}else{if(v>=60){return Math.round(v/60)+"m"}}}return v+"s"};function e(){this.pasteCatcher=null}e.prototype.execute=function(){this.initialize()};e.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))};e.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};e.prototype.setFocus=function(){if(this.pasteCatcher!==null){this.pasteCatcher.focus()}};e.prototype.pasteHandler=function(A){if(A.clipboardData&&A.clipboardData.items){var y=A.clipboardData.items;if(y){for(var z=0;z0){this.checkInterval=window.setInterval(this.check.bind(this),v*1000)}};j.prototype.reloadFilters=function(v){this.app.showLoadingIcon();$.ajax({cache:false,url:$("#board").data("reload-url"),contentType:"application/json",type:"POST",processData:false,data:JSON.stringify({search:v}),success:this.refresh.bind(this),error:this.app.hideLoadingIcon.bind(this)})};j.prototype.check=function(){if(this.app.isVisible()){var v=this;this.app.showLoadingIcon();$.ajax({cache:false,url:$("#board").data("check-url"),statusCode:{200:function(w){v.refresh(w)},304:function(){v.app.hideLoadingIcon()}}})}};j.prototype.save=function(x,y,v,w){this.app.showLoadingIcon();$.ajax({cache:false,url:$("#board").data("save-url"),contentType:"application/json",type:"POST",processData:false,data:JSON.stringify({task_id:x,column_id:y,swimlane_id:w,position:v}),success:this.refresh.bind(this),error:this.app.hideLoadingIcon.bind(this)})};j.prototype.refresh=function(v){$("#board-container").replaceWith(v);this.app.refresh();this.app.swimlane.refresh();this.columnScrolling();this.app.hideLoadingIcon();this.listen();this.dragAndDrop();this.compactView();this.restoreColumnViewMode()};j.prototype.dragAndDrop=function(){var v=this;var w={forcePlaceholderSize:true,tolerance:"pointer",connectWith:".board-task-list",placeholder:"draggable-placeholder",items:".draggable-item",stop:function(x,y){y.item.removeClass("draggable-item-selected");v.save(y.item.attr("data-task-id"),y.item.parent().attr("data-column-id"),y.item.index()+1,y.item.parent().attr("data-swimlane-id"))},start:function(x,y){y.item.addClass("draggable-item-selected");y.placeholder.height(y.item.height())}};if($.support.touch){$(".task-board-sort-handle").css("display","inline");w.handle=".task-board-sort-handle"}$(".board-task-list").sortable(w)};j.prototype.listen=function(){var v=this;$(document).on("click",".task-board",function(w){if(w.target.tagName!="A"){window.location=$(this).data("task-url")}});$(document).on("click",".filter-toggle-scrolling",function(w){w.preventDefault();v.toggleCompactView()});$(document).on("click",".filter-toggle-height",function(w){w.preventDefault();v.toggleColumnScrolling()});$(document).on("click",".board-column-title",function(){v.toggleColumnViewMode($(this).data("column-id"))})};j.prototype.toggleColumnScrolling=function(){var v=localStorage.getItem("column_scroll")||1;localStorage.setItem("column_scroll",v==0?1:0);this.columnScrolling()};j.prototype.columnScrolling=function(){if(localStorage.getItem("column_scroll")==0){$(".filter-max-height").show();$(".filter-min-height").hide();$(".board-task-list").each(function(){$(this).css("min-height",80);$(this).css("height","");$(".board-rotation-wrapper").css("min-height","")})}else{$(".filter-max-height").hide();$(".filter-min-height").show();if($(".board-swimlane").length>1){$(".board-task-list").each(function(){if($(this).height()>500){$(this).css("height",500)}else{$(this).css("min-height",320);$(".board-rotation-wrapper").css("min-height",320)}})}else{var v=$(window).height()-145;$(".board-task-list").css("height",v);$(".board-rotation-wrapper").css("min-height",v)}}};j.prototype.toggleCompactView=function(){var v=localStorage.getItem("horizontal_scroll")||1;localStorage.setItem("horizontal_scroll",v==0?1:0);this.compactView()};j.prototype.compactView=function(){if(localStorage.getItem("horizontal_scroll")==0){$(".filter-wide").show();$(".filter-compact").hide();$("#board-container").addClass("board-container-compact");$("#board th:not(.board-column-header-collapsed)").addClass("board-column-compact")}else{$(".filter-wide").hide();$(".filter-compact").show();$("#board-container").removeClass("board-container-compact");$("#board th").removeClass("board-column-compact")}};j.prototype.toggleCollapsedMode=function(){var v=this;this.app.showLoadingIcon();$.ajax({cache:false,url:$('.filter-display-mode:not([style="display: none;"]) a').attr("href"),success:function(w){$(".filter-display-mode").toggle();v.refresh(w)}})};j.prototype.restoreColumnViewMode=function(){var v=this;$(".board-column-header").each(function(){var w=$(this).data("column-id");if(localStorage.getItem("hidden_column_"+w)){v.hideColumn(w)}})};j.prototype.toggleColumnViewMode=function(v){if(localStorage.getItem("hidden_column_"+v)){this.showColumn(v)}else{this.hideColumn(v)}};j.prototype.hideColumn=function(v){$(".board-column-"+v+" .board-column-expanded").hide();$(".board-column-"+v+" .board-column-collapsed").show();$(".board-column-header-"+v+" .board-column-expanded").hide();$(".board-column-header-"+v+" .board-column-collapsed").show();$(".board-column-header-"+v).each(function(){$(this).removeClass("board-column-compact");$(this).addClass("board-column-header-collapsed")});$(".board-column-"+v).each(function(){$(this).addClass("board-column-task-collapsed")});$(".board-column-"+v+" .board-rotation").each(function(){$(this).css("width",$(".board-column-"+v+"").height())});localStorage.setItem("hidden_column_"+v,1)};j.prototype.showColumn=function(v){$(".board-column-"+v+" .board-column-expanded").show();$(".board-column-"+v+" .board-column-collapsed").hide();$(".board-column-header-"+v+" .board-column-expanded").show();$(".board-column-header-"+v+" .board-column-collapsed").hide();$(".board-column-header-"+v).removeClass("board-column-header-collapsed");$(".board-column-"+v).removeClass("board-column-task-collapsed");if(localStorage.getItem("horizontal_scroll")==0){$(".board-column-header-"+v).addClass("board-column-compact")}localStorage.removeItem("hidden_column_"+v)};j.prototype.keyboardShortcuts=function(){var v=this;Mousetrap.bind("c",function(){v.toggleCompactView()});Mousetrap.bind("s",function(){v.toggleCollapsedMode()});Mousetrap.bind("n",function(){v.app.popover.open($("#board").data("task-creation-url"))})};function g(){}g.prototype.getStorageKey=function(){return"hidden_swimlanes_"+$("#board").data("project-id")};g.prototype.expand=function(w){var x=this.getAllCollapsed();var v=x.indexOf(w);if(v>-1){x.splice(v,1)}localStorage.setItem(this.getStorageKey(),JSON.stringify(x));$(".board-swimlane-columns-"+w).css("display","table-row");$(".board-swimlane-tasks-"+w).css("display","table-row");$(".hide-icon-swimlane-"+w).css("display","inline");$(".show-icon-swimlane-"+w).css("display","none")};g.prototype.collapse=function(v){var w=this.getAllCollapsed();if(w.indexOf(v)<0){w.push(v);localStorage.setItem(this.getStorageKey(),JSON.stringify(w))}$(".board-swimlane-columns-"+v+":not(:first-child)").css("display","none");$(".board-swimlane-tasks-"+v).css("display","none");$(".hide-icon-swimlane-"+v).css("display","none");$(".show-icon-swimlane-"+v).css("display","inline")};g.prototype.isCollapsed=function(v){return this.getAllCollapsed().indexOf(v)>-1};g.prototype.getAllCollapsed=function(){return JSON.parse(localStorage.getItem(this.getStorageKey()))||[]};g.prototype.refresh=function(){var w=this.getAllCollapsed();for(var v=0;v",{"class":"ganttview"});z.append(this.renderVerticalHeader());z.append(this.renderSlider(v,A));w.append(z);jQuery("div.ganttview-grid-row div.ganttview-grid-row-cell:last-child",w).addClass("last");jQuery("div.ganttview-hzheader-days div.ganttview-hzheader-day:last-child",w).addClass("last");jQuery("div.ganttview-hzheader-months div.ganttview-hzheader-month:last-child",w).addClass("last");if(!$(this.options.container).data("readonly")){this.listenForBlockResize(v);this.listenForBlockMove(v)}else{this.options.allowResizes=false;this.options.allowMoves=false}};c.prototype.renderVerticalHeader=function(){var z=jQuery("
    ",{"class":"ganttview-vtheader"});var w=jQuery("
    ",{"class":"ganttview-vtheader-item"});var y=jQuery("
    ",{"class":"ganttview-vtheader-series"});for(var v=0;v").append(jQuery("",{"class":"fa fa-info-circle tooltip",title:this.getVerticalHeaderTooltip(this.data[v])})).append(" ");if(this.data[v].type=="task"){x.append(jQuery("",{href:this.data[v].link,target:"_blank",title:this.data[v].title}).append(this.data[v].title))}else{x.append(jQuery("",{href:this.data[v].board_link,target:"_blank",title:$(this.options.container).data("label-board-link")}).append('')).append(" ").append(jQuery("",{href:this.data[v].gantt_link,target:"_blank",title:$(this.options.container).data("label-gantt-link")}).append('')).append(" ").append(jQuery("",{href:this.data[v].link,target:"_blank"}).append(this.data[v].title))}y.append(jQuery("
    ",{"class":"ganttview-vtheader-series-name"}).append(x))}w.append(y);z.append(w);return z};c.prototype.renderSlider=function(w,y){var v=jQuery("
    ",{"class":"ganttview-slide-container"});var x=this.getDates(w,y);v.append(this.renderHorizontalHeader(x));v.append(this.renderGrid(x));v.append(this.addBlockContainers());this.addBlocks(v,w);return v};c.prototype.renderHorizontalHeader=function(v){var D=jQuery("
    ",{"class":"ganttview-hzheader"});var B=jQuery("
    ",{"class":"ganttview-hzheader-months"});var A=jQuery("
    ",{"class":"ganttview-hzheader-days"});var z=0;for(var E in v){for(var x in v[E]){var F=v[E][x].length*this.options.cellWidth;z=z+F;B.append(jQuery("
    ",{"class":"ganttview-hzheader-month",css:{width:(F-1)+"px"}}).append($.datepicker.regional[$("body").data("js-lang")].monthNames[x]+" "+E));for(var C in v[E][x]){A.append(jQuery("
    ",{"class":"ganttview-hzheader-day"}).append(v[E][x][C].getDate()))}}}B.css("width",z+"px");A.css("width",z+"px");D.append(B).append(A);return D};c.prototype.renderGrid=function(v){var F=jQuery("
    ",{"class":"ganttview-grid"});var A=jQuery("
    ",{"class":"ganttview-grid-row"});for(var D in v){for(var x in v[D]){for(var C in v[D][x]){var z=jQuery("
    ",{"class":"ganttview-grid-row-cell"});if(this.options.showWeekends&&this.isWeekend(v[D][x][C])){z.addClass("ganttview-weekend")}A.append(z)}}}var E=jQuery("div.ganttview-grid-row-cell",A).length*this.options.cellWidth;A.css("width",E+"px");F.css("width",E+"px");for(var B=0;B",{"class":"ganttview-blocks"});for(var v=0;v",{"class":"ganttview-block-container"}))}return w};c.prototype.addBlocks=function(w,v){var D=jQuery("div.ganttview-blocks div.ganttview-block-container",w);var x=0;for(var A=0;A",{"class":"ganttview-block-text"});var y=jQuery("
    ",{"class":"ganttview-block tooltip"+(this.options.allowMoves?" ganttview-block-movable":""),title:this.getBarTooltip(this.data[A]),css:{width:((E*this.options.cellWidth)-9)+"px","margin-left":(z*this.options.cellWidth)+"px"}}).append(C);if(E>=2){C.append(this.data[A].progress)}y.data("record",this.data[A]);this.setBarColor(y,this.data[A]);y.append(jQuery("
    ",{css:{"z-index":0,position:"absolute",top:0,bottom:0,"background-color":B.color.border,width:B.progress,opacity:0.4}}));jQuery(D[x]).append(y);x=x+1}};c.prototype.getVerticalHeaderTooltip=function(w){var B="";if(w.type=="task"){B=""+w.column_title+" ("+w.progress+")
    "+w.title}else{var y=["managers","members"];for(var x in y){var z=y[x];if(!jQuery.isEmptyObject(w.users[z])){var A=jQuery("
      ");for(var v in w.users[z]){A.append(jQuery("
    • ").append(w.users[z][v]))}B+="

      "+$(this.options.container).data("label-"+z)+"

      "+A[0].outerHTML}}}return B};c.prototype.getBarTooltip=function(v){var w="";if(v.not_defined){w=$(this.options.container).data("label-not-defined")}else{if(v.type=="task"){w=""+v.progress+"
      "+$(this.options.container).data("label-assignee")+" "+(v.assignee?v.assignee:"")+"
      "}w+=$(this.options.container).data("label-start-date")+" "+$.datepicker.formatDate("yy-mm-dd",v.start)+"
      ";w+=$(this.options.container).data("label-end-date")+" "+$.datepicker.formatDate("yy-mm-dd",v.end)}return w};c.prototype.setBarColor=function(w,v){if(v.not_defined){w.addClass("ganttview-block-not-defined")}else{w.css("background-color",v.color.background);w.css("border-color",v.color.border)}};c.prototype.listenForBlockResize=function(v){var w=this;jQuery("div.ganttview-block",this.options.container).resizable({grid:this.options.cellWidth,handles:"e,w",delay:300,stop:function(){var x=jQuery(this);w.updateDataAndPosition(x,v);w.saveRecord(x.data("record"))}})};c.prototype.listenForBlockMove=function(v){var w=this;jQuery("div.ganttview-block",this.options.container).draggable({axis:"x",delay:300,grid:[this.options.cellWidth,this.options.cellWidth],stop:function(){var x=jQuery(this);w.updateDataAndPosition(x,v);w.saveRecord(x.data("record"))}})};c.prototype.updateDataAndPosition=function(A,y){var v=jQuery("div.ganttview-slide-container",this.options.container);var E=v.scrollLeft();var B=A.offset().left-v.offset().left-1+E;var D=A.data("record");D.not_defined=false;this.setBarColor(A,D);var x=Math.round(B/this.options.cellWidth);var C=this.addDays(this.cloneDate(y),x);D.start=C;var w=A.outerWidth();var z=Math.round(w/this.options.cellWidth)-1;D.end=this.addDays(this.cloneDate(C),z);if(D.type==="task"&&z>0){jQuery("div.ganttview-block-text",A).text(D.progress)}A.attr("title",this.getBarTooltip(D));A.data("record",D);A.css("top","").css("left","").css("position","relative").css("margin-left",B+"px")};c.prototype.getDates=function(z,v){var y=[];y[z.getFullYear()]=[];y[z.getFullYear()][z.getMonth()]=[z];var x=z;while(this.compareDate(x,v)==-1){var w=this.addDays(this.cloneDate(x),1);if(!y[w.getFullYear()]){y[w.getFullYear()]=[]}if(!y[w.getFullYear()][w.getMonth()]){y[w.getFullYear()][w.getMonth()]=[]}y[w.getFullYear()][w.getMonth()].push(w);x=w}return y};c.prototype.prepareData=function(x){for(var w=0;wv)?1:0}else{throw new TypeError(w+" - "+v)}}};function a(){}a.prototype.listen=function(){$(document).on("click",".color-square",function(){$(".color-square-selected").removeClass("color-square-selected");$(this).addClass("color-square-selected");$("#form-color_id").val($(this).data("color-id"))})};function q(){}q.prototype.execute=function(){var x=$("#chart").data("metrics");var w=[];for(var v=0;v0){v.push(B[z][x])}}else{A[x].push(B[z][x]);if(x==0){w.push(C(y.parse(B[z][x])))}}}}c3.generate({data:{columns:A,type:"area-spline",groups:[v]},axis:{x:{type:"category",categories:w}}})};function m(){}m.prototype.execute=function(){var A=$("#chart").data("metrics");var z=[[$("#chart").data("label-total")]];var v=[];var x=d3.time.format("%Y-%m-%d");var B=d3.time.format($("#chart").data("date-format"));for(var y=0;y0){if(z[0][y]==undefined){z[0].push(0)}z[0][y]+=A[y][w]}if(w==0){v.push(B(x.parse(A[y][w])))}}}}c3.generate({data:{columns:z},axis:{x:{type:"category",categories:v}}})};function h(v){this.app=v}h.prototype.execute=function(){var x=$("#chart").data("metrics");var y=[$("#chart").data("label")];var v=[];for(var w in x){y.push(x[w].average);v.push(x[w].title)}c3.generate({data:{columns:[y],type:"bar"},bar:{width:{ratio:0.5}},axis:{x:{type:"category",categories:v},y:{tick:{format:this.app.formatDuration}}},legend:{show:false}})};function u(v){this.app=v}u.prototype.execute=function(){var x=$("#chart").data("metrics");var y=[$("#chart").data("label")];var v=[];for(var w=0;w1&&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){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};r.prototype.open=function(w){var v=this;v.app.dropdown.close();$.get(w,function(x){$("body").append('
      '+x+"
      ");v.app.refresh();v.router.dispatch(this.app);v.afterOpen()})};r.prototype.close=function(v){if(this.isOpen()){if(v){v.preventDefault()}$("#popover-container").remove()}};r.prototype.onClick=function(w){w.preventDefault();w.stopPropagation();var v=w.target.getAttribute("href");if(!v){v=w.target.getAttribute("data-href")}if(v){this.open(v)}};r.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(v){v.stopPropagation()})};r.prototype.afterOpen=function(){var v=this;var w=$("#task-form");if(w){w.on("submit",function(x){x.preventDefault();$.ajax({type:"POST",url:w.attr("action"),data:w.serialize(),success:function(z,A,y){if(y.getResponseHeader("X-Ajax-Redirect")){window.location=y.getResponseHeader("X-Ajax-Redirect")}else{$("#popover-content").html(z);v.afterOpen()}}})})}};function p(){}p.prototype.listen=function(){var v=this;$(document).on("click",function(){v.close()});$(document).on("click",".dropdown-menu",function(z){z.preventDefault();z.stopImmediatePropagation();v.close();var x=$(this).next("ul");var y=240;var A=$(this).offset();var w=$(this).height();$("body").append(jQuery("
      ",{id:"dropdown"}));x.clone().appendTo("#dropdown");var B=$("#dropdown ul");B.css("left",A.left);if(A.top+y-$(window).scrollTop()>$(window).height()){B.css("top",A.top-y-w)}else{B.css("top",A.top+w)}B.addClass("dropdown-submenu-open")});$(document).on("click",".dropdown-submenu-open li",function(w){if($(w.target).is("li")){$(this).find("a:visible")[0].click()}})};p.prototype.close=function(){$("#dropdown").remove()};function o(v){this.app=v}o.prototype.listen=function(){var v=this;$(".tooltip").tooltip({track:false,show:false,hide:false,position:{my:"left-20 top",at:"center bottom+9",using:function(w,x){$(this).css(w);var y=x.target.left+x.target.width/2-x.element.left-20;$("
      ").addClass("tooltip-arrow").addClass(x.vertical).addClass(y<1?"align-left":"align-right").appendTo(this)}},content:function(){var y=this;var w=$(this).attr("data-href");if(!w){return'
      '+$(this).attr("title")+"
      "}$.get(w,function x(B){var A=$(".ui-tooltip:visible");$(".ui-tooltip-content:visible").html(B);A.css({top:"",left:""});A.children(".tooltip-arrow").remove();var z=$(y).tooltip("option","position");z.of=$(y);A.position(z);$("#tooltip-subtasks a").not(".popover").click(function(C){C.preventDefault();C.stopPropagation();if($(this).hasClass("popover-subtask-restriction")){v.app.popover.open($(this).attr("href"));$(y).tooltip("close")}else{$.get($(this).attr("href"),x)}})});return''}}).on("mouseenter",function(){var w=this;$(this).tooltip("open");$(".ui-tooltip").on("mouseleave",function(){$(w).tooltip("close")})}).on("mouseleave focusout",function(w){w.stopImmediatePropagation();var x=this;setTimeout(function(){if(!$(".ui-tooltip:hover").length){$(x).tooltip("close")}},100)})};function k(){}k.prototype.showPreview=function(z){z.preventDefault();var w=$(".write-area");var y=$(".preview-area");var v=$("textarea");$("#markdown-write").parent().removeClass("form-tab-selected");$("#markdown-preview").parent().addClass("form-tab-selected");var x=$.ajax({url:$("body").data("markdown-preview-url"),contentType:"application/json",type:"POST",processData:false,dataType:"html",data:JSON.stringify({text:v.val()})});x.done(function(A){y.find(".markdown").html(A);y.css("height",v.css("height"));y.css("width",v.css("width"));w.hide();y.show()})};k.prototype.showWriter=function(v){v.preventDefault();$("#markdown-write").parent().addClass("form-tab-selected");$("#markdown-preview").parent().removeClass("form-tab-selected");$(".write-area").show();$(".preview-area").hide()};k.prototype.listen=function(){$(document).on("click","#markdown-preview",this.showPreview.bind(this));$(document).on("click","#markdown-write",this.showWriter.bind(this))};function b(){}b.prototype.expand=function(v){v.preventDefault();$(".sidebar-container").removeClass("sidebar-collapsed");$(".sidebar-collapse").show();$(".sidebar h2").show();$(".sidebar ul").show();$(".sidebar-expand").hide()};b.prototype.collapse=function(v){v.preventDefault();$(".sidebar-container").addClass("sidebar-collapsed");$(".sidebar-expand").show();$(".sidebar h2").hide();$(".sidebar ul").hide();$(".sidebar-collapse").hide()};b.prototype.listen=function(){$(document).on("click",".sidebar-collapse",this.collapse);$(document).on("click",".sidebar-expand",this.expand)};function f(v){this.app=v;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 v=this;$(document).on("click",".filter-helper",function(y){y.preventDefault();var x=$(this).data("filter");var w=$(this).data("append-filter");if(w){x=$("#form-search").val()+" "+w}$("#form-search").val(x);if($("#board").length){v.app.board.reloadFilters(x)}else{$("form.search").submit()}})};f.prototype.keyboardShortcuts=function(){var v=this;Mousetrap.bind("v b",function(x){var w=$(".view-board");if(w.length){window.location=w.attr("href")}});Mousetrap.bind("v c",function(x){var w=$(".view-calendar");if(w.length){window.location=w.attr("href")}});Mousetrap.bind("v l",function(x){var w=$(".view-listing");if(w.length){window.location=w.attr("href")}});Mousetrap.bind("v g",function(x){var w=$(".view-gantt");if(w.length){window.location=w.attr("href")}});Mousetrap.bind("f",function(x){x.preventDefault();var w=document.getElementById("form-search");if(w){w.focus()}});Mousetrap.bind("r",function(x){x.preventDefault();var w=$(".filter-reset").data("filter");$("#form-search").val(w);if($("#board").length){v.app.board.reloadFilters(w)}else{$("form.search").submit()}})};function l(){this.board=new j(this);this.markdown=new k();this.sidebar=new b();this.search=new f(this);this.swimlane=new g();this.dropdown=new p();this.tooltip=new o(this);this.popover=new r(this);this.task=new a();this.keyboardShortcuts();this.chosen();this.poll();$(".alert-fade-out").delay(4000).fadeOut(800,function(){$(this).remove()});var v=false;$("select.task-reload-project-destination").change(function(){if(!v){$(".loading-icon").show();v=true;window.location=$(this).data("redirect").replace(/PROJECT_ID/g,$(this).val())}})}l.prototype.listen=function(){this.popover.listen();this.markdown.listen();this.sidebar.listen();this.tooltip.listen();this.dropdown.listen();this.search.listen();this.task.listen();this.swimlane.listen();this.search.focus();this.taskAutoComplete();this.datePicker();this.focus()};l.prototype.refresh=function(){$(document).off();this.listen()};l.prototype.focus=function(){$("[autofocus]").each(function(v,w){$(this).focus()});$(document).on("focus",".auto-select",function(){$(this).select()});$(document).on("mouseup",".auto-select",function(v){v.preventDefault()})};l.prototype.poll=function(){window.setInterval(this.checkSession,60000)};l.prototype.keyboardShortcuts=function(){var v=this;Mousetrap.bindGlobal("mod+enter",function(){$("form").submit()});Mousetrap.bind("b",function(w){w.preventDefault();$("#board-selector").trigger("chosen:open")});Mousetrap.bindGlobal("esc",function(){v.popover.close();v.dropdown.close()})};l.prototype.checkSession=function(){if(!$(".form-login").length){$.ajax({cache:false,url:$("body").data("status-url"),statusCode:{401:function(){window.location=$("body").data("login-url")}}})}};l.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})};l.prototype.taskAutoComplete=function(){if($(".task-autocomplete").length){if($(".opposite_task_id").val()==""){$(".task-autocomplete").parent().find("input[type=submit]").attr("disabled","disabled")}$(".task-autocomplete").autocomplete({source:$(".task-autocomplete").data("search-url"),minLength:1,select:function(v,w){var x=$(".task-autocomplete").data("dst-field");$("input[name="+x+"]").val(w.item.id);$(".task-autocomplete").parent().find("input[type=submit]").removeAttr("disabled")}})}};l.prototype.chosen=function(){$(".chosen-select").chosen({width:"180px",no_results_text:$(".chosen-select").data("notfound"),disable_search_threshold:10});$(".select-auto-redirect").change(function(){var v=new RegExp($(this).data("redirect-regex"),"g");window.location=$(this).data("redirect-url").replace(v,$(this).val())})};l.prototype.showLoadingIcon=function(){$("body").append(' ')};l.prototype.hideLoadingIcon=function(){$("#app-loading-icon").remove()};l.prototype.isVisible=function(){var v="";if(typeof document.hidden!=="undefined"){v="visibilityState"}else{if(typeof document.mozHidden!=="undefined"){v="mozVisibilityState"}else{if(typeof document.msHidden!=="undefined"){v="msVisibilityState"}else{if(typeof document.webkitHidden!=="undefined"){v="webkitVisibilityState"}}}}if(v!=""){return document[v]=="visible"}return true};l.prototype.formatDuration=function(v){if(v>=86400){return Math.round(v/86400)+"d"}else{if(v>=3600){return Math.round(v/3600)+"h"}else{if(v>=60){return Math.round(v/60)+"m"}}}return v+"s"};function e(){this.pasteCatcher=null}e.prototype.execute=function(){this.initialize()};e.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))};e.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};e.prototype.setFocus=function(){if(this.pasteCatcher!==null){this.pasteCatcher.focus()}};e.prototype.pasteHandler=function(A){if(A.clipboardData&&A.clipboardData.items){var y=A.clipboardData.items;if(y){for(var z=0;z0){this.checkInterval=window.setInterval(this.check.bind(this),v*1000)}};j.prototype.reloadFilters=function(v){this.app.showLoadingIcon();$.ajax({cache:false,url:$("#board").data("reload-url"),contentType:"application/json",type:"POST",processData:false,data:JSON.stringify({search:v}),success:this.refresh.bind(this),error:this.app.hideLoadingIcon.bind(this)})};j.prototype.check=function(){if(this.app.isVisible()){var v=this;this.app.showLoadingIcon();$.ajax({cache:false,url:$("#board").data("check-url"),statusCode:{200:function(w){v.refresh(w)},304:function(){v.app.hideLoadingIcon()}}})}};j.prototype.save=function(x,y,v,w){this.app.showLoadingIcon();$.ajax({cache:false,url:$("#board").data("save-url"),contentType:"application/json",type:"POST",processData:false,data:JSON.stringify({task_id:x,column_id:y,swimlane_id:w,position:v}),success:this.refresh.bind(this),error:this.app.hideLoadingIcon.bind(this)})};j.prototype.refresh=function(v){$("#board-container").replaceWith(v);this.app.refresh();this.app.swimlane.refresh();this.columnScrolling();this.app.hideLoadingIcon();this.listen();this.dragAndDrop();this.compactView();this.restoreColumnViewMode()};j.prototype.dragAndDrop=function(){var v=this;var w={forcePlaceholderSize:true,tolerance:"pointer",connectWith:".board-task-list",placeholder:"draggable-placeholder",items:".draggable-item",stop:function(x,y){y.item.removeClass("draggable-item-selected");v.save(y.item.attr("data-task-id"),y.item.parent().attr("data-column-id"),y.item.index()+1,y.item.parent().attr("data-swimlane-id"))},start:function(x,y){y.item.addClass("draggable-item-selected");y.placeholder.height(y.item.height())}};if($.support.touch){$(".task-board-sort-handle").css("display","inline");w.handle=".task-board-sort-handle"}$(".board-task-list").sortable(w)};j.prototype.listen=function(){var v=this;$(document).on("click",".task-board",function(w){if(w.target.tagName!="A"){window.location=$(this).data("task-url")}});$(document).on("click",".filter-toggle-scrolling",function(w){w.preventDefault();v.toggleCompactView()});$(document).on("click",".filter-toggle-height",function(w){w.preventDefault();v.toggleColumnScrolling()});$(document).on("click",".board-column-title",function(){v.toggleColumnViewMode($(this).data("column-id"))})};j.prototype.toggleColumnScrolling=function(){var v=localStorage.getItem("column_scroll")||1;localStorage.setItem("column_scroll",v==0?1:0);this.columnScrolling()};j.prototype.columnScrolling=function(){if(localStorage.getItem("column_scroll")==0){$(".filter-max-height").show();$(".filter-min-height").hide();$(".board-task-list").each(function(){$(this).css("min-height",80);$(this).css("height","");$(".board-rotation-wrapper").css("min-height","")})}else{$(".filter-max-height").hide();$(".filter-min-height").show();if($(".board-swimlane").length>1){$(".board-task-list").each(function(){if($(this).height()>500){$(this).css("height",500)}else{$(this).css("min-height",320);$(".board-rotation-wrapper").css("min-height",320)}})}else{var v=$(window).height()-145;$(".board-task-list").css("height",v);$(".board-rotation-wrapper").css("min-height",v)}}};j.prototype.toggleCompactView=function(){var v=localStorage.getItem("horizontal_scroll")||1;localStorage.setItem("horizontal_scroll",v==0?1:0);this.compactView()};j.prototype.compactView=function(){if(localStorage.getItem("horizontal_scroll")==0){$(".filter-wide").show();$(".filter-compact").hide();$("#board-container").addClass("board-container-compact");$("#board th:not(.board-column-header-collapsed)").addClass("board-column-compact")}else{$(".filter-wide").hide();$(".filter-compact").show();$("#board-container").removeClass("board-container-compact");$("#board th").removeClass("board-column-compact")}};j.prototype.toggleCollapsedMode=function(){var v=this;this.app.showLoadingIcon();$.ajax({cache:false,url:$('.filter-display-mode:not([style="display: none;"]) a').attr("href"),success:function(w){$(".filter-display-mode").toggle();v.refresh(w)}})};j.prototype.restoreColumnViewMode=function(){var v=this;$(".board-column-header").each(function(){var w=$(this).data("column-id");if(localStorage.getItem("hidden_column_"+w)){v.hideColumn(w)}})};j.prototype.toggleColumnViewMode=function(v){if(localStorage.getItem("hidden_column_"+v)){this.showColumn(v)}else{this.hideColumn(v)}};j.prototype.hideColumn=function(v){$(".board-column-"+v+" .board-column-expanded").hide();$(".board-column-"+v+" .board-column-collapsed").show();$(".board-column-header-"+v+" .board-column-expanded").hide();$(".board-column-header-"+v+" .board-column-collapsed").show();$(".board-column-header-"+v).each(function(){$(this).removeClass("board-column-compact");$(this).addClass("board-column-header-collapsed")});$(".board-column-"+v).each(function(){$(this).addClass("board-column-task-collapsed")});$(".board-column-"+v+" .board-rotation").each(function(){$(this).css("width",$(".board-column-"+v+"").height())});localStorage.setItem("hidden_column_"+v,1)};j.prototype.showColumn=function(v){$(".board-column-"+v+" .board-column-expanded").show();$(".board-column-"+v+" .board-column-collapsed").hide();$(".board-column-header-"+v+" .board-column-expanded").show();$(".board-column-header-"+v+" .board-column-collapsed").hide();$(".board-column-header-"+v).removeClass("board-column-header-collapsed");$(".board-column-"+v).removeClass("board-column-task-collapsed");if(localStorage.getItem("horizontal_scroll")==0){$(".board-column-header-"+v).addClass("board-column-compact")}localStorage.removeItem("hidden_column_"+v)};j.prototype.keyboardShortcuts=function(){var v=this;Mousetrap.bind("c",function(){v.toggleCompactView()});Mousetrap.bind("s",function(){v.toggleCollapsedMode()});Mousetrap.bind("n",function(){v.app.popover.open($("#board").data("task-creation-url"))})};function g(){}g.prototype.getStorageKey=function(){return"hidden_swimlanes_"+$("#board").data("project-id")};g.prototype.expand=function(w){var x=this.getAllCollapsed();var v=x.indexOf(w);if(v>-1){x.splice(v,1)}localStorage.setItem(this.getStorageKey(),JSON.stringify(x));$(".board-swimlane-columns-"+w).css("display","table-row");$(".board-swimlane-tasks-"+w).css("display","table-row");$(".hide-icon-swimlane-"+w).css("display","inline");$(".show-icon-swimlane-"+w).css("display","none")};g.prototype.collapse=function(v){var w=this.getAllCollapsed();if(w.indexOf(v)<0){w.push(v);localStorage.setItem(this.getStorageKey(),JSON.stringify(w))}$(".board-swimlane-columns-"+v+":not(:first-child)").css("display","none");$(".board-swimlane-tasks-"+v).css("display","none");$(".hide-icon-swimlane-"+v).css("display","none");$(".show-icon-swimlane-"+v).css("display","inline")};g.prototype.isCollapsed=function(v){return this.getAllCollapsed().indexOf(v)>-1};g.prototype.getAllCollapsed=function(){return JSON.parse(localStorage.getItem(this.getStorageKey()))||[]};g.prototype.refresh=function(){var w=this.getAllCollapsed();for(var v=0;v",{"class":"ganttview"});z.append(this.renderVerticalHeader());z.append(this.renderSlider(v,A));w.append(z);jQuery("div.ganttview-grid-row div.ganttview-grid-row-cell:last-child",w).addClass("last");jQuery("div.ganttview-hzheader-days div.ganttview-hzheader-day:last-child",w).addClass("last");jQuery("div.ganttview-hzheader-months div.ganttview-hzheader-month:last-child",w).addClass("last");if(!$(this.options.container).data("readonly")){this.listenForBlockResize(v);this.listenForBlockMove(v)}else{this.options.allowResizes=false;this.options.allowMoves=false}};c.prototype.renderVerticalHeader=function(){var z=jQuery("
      ",{"class":"ganttview-vtheader"});var w=jQuery("
      ",{"class":"ganttview-vtheader-item"});var y=jQuery("
      ",{"class":"ganttview-vtheader-series"});for(var v=0;v").append(jQuery("",{"class":"fa fa-info-circle tooltip",title:this.getVerticalHeaderTooltip(this.data[v])})).append(" ");if(this.data[v].type=="task"){x.append(jQuery("",{href:this.data[v].link,target:"_blank",title:this.data[v].title}).append(this.data[v].title))}else{x.append(jQuery("",{href:this.data[v].board_link,target:"_blank",title:$(this.options.container).data("label-board-link")}).append('')).append(" ").append(jQuery("",{href:this.data[v].gantt_link,target:"_blank",title:$(this.options.container).data("label-gantt-link")}).append('')).append(" ").append(jQuery("",{href:this.data[v].link,target:"_blank"}).append(this.data[v].title))}y.append(jQuery("
      ",{"class":"ganttview-vtheader-series-name"}).append(x))}w.append(y);z.append(w);return z};c.prototype.renderSlider=function(w,y){var v=jQuery("
      ",{"class":"ganttview-slide-container"});var x=this.getDates(w,y);v.append(this.renderHorizontalHeader(x));v.append(this.renderGrid(x));v.append(this.addBlockContainers());this.addBlocks(v,w);return v};c.prototype.renderHorizontalHeader=function(v){var D=jQuery("
      ",{"class":"ganttview-hzheader"});var B=jQuery("
      ",{"class":"ganttview-hzheader-months"});var A=jQuery("
      ",{"class":"ganttview-hzheader-days"});var z=0;for(var E in v){for(var x in v[E]){var F=v[E][x].length*this.options.cellWidth;z=z+F;B.append(jQuery("
      ",{"class":"ganttview-hzheader-month",css:{width:(F-1)+"px"}}).append($.datepicker.regional[$("body").data("js-lang")].monthNames[x]+" "+E));for(var C in v[E][x]){A.append(jQuery("
      ",{"class":"ganttview-hzheader-day"}).append(v[E][x][C].getDate()))}}}B.css("width",z+"px");A.css("width",z+"px");D.append(B).append(A);return D};c.prototype.renderGrid=function(v){var F=jQuery("
      ",{"class":"ganttview-grid"});var A=jQuery("
      ",{"class":"ganttview-grid-row"});for(var D in v){for(var x in v[D]){for(var C in v[D][x]){var z=jQuery("
      ",{"class":"ganttview-grid-row-cell"});if(this.options.showWeekends&&this.isWeekend(v[D][x][C])){z.addClass("ganttview-weekend")}A.append(z)}}}var E=jQuery("div.ganttview-grid-row-cell",A).length*this.options.cellWidth;A.css("width",E+"px");F.css("width",E+"px");for(var B=0;B",{"class":"ganttview-blocks"});for(var v=0;v",{"class":"ganttview-block-container"}))}return w};c.prototype.addBlocks=function(w,v){var D=jQuery("div.ganttview-blocks div.ganttview-block-container",w);var x=0;for(var A=0;A",{"class":"ganttview-block-text"});var y=jQuery("
      ",{"class":"ganttview-block tooltip"+(this.options.allowMoves?" ganttview-block-movable":""),title:this.getBarTooltip(this.data[A]),css:{width:((E*this.options.cellWidth)-9)+"px","margin-left":(z*this.options.cellWidth)+"px"}}).append(C);if(E>=2){C.append(this.data[A].progress)}y.data("record",this.data[A]);this.setBarColor(y,this.data[A]);y.append(jQuery("
      ",{css:{"z-index":0,position:"absolute",top:0,bottom:0,"background-color":B.color.border,width:B.progress,opacity:0.4}}));jQuery(D[x]).append(y);x=x+1}};c.prototype.getVerticalHeaderTooltip=function(w){var B="";if(w.type=="task"){B=""+w.column_title+" ("+w.progress+")
      "+w.title}else{var y=["managers","members"];for(var x in y){var z=y[x];if(!jQuery.isEmptyObject(w.users[z])){var A=jQuery("
        ");for(var v in w.users[z]){A.append(jQuery("
      • ").append(w.users[z][v]))}B+="

        "+$(this.options.container).data("label-"+z)+"

        "+A[0].outerHTML}}}return B};c.prototype.getBarTooltip=function(v){var w="";if(v.not_defined){w=$(this.options.container).data("label-not-defined")}else{if(v.type=="task"){w=""+v.progress+"
        "+$(this.options.container).data("label-assignee")+" "+(v.assignee?v.assignee:"")+"
        "}w+=$(this.options.container).data("label-start-date")+" "+$.datepicker.formatDate("yy-mm-dd",v.start)+"
        ";w+=$(this.options.container).data("label-end-date")+" "+$.datepicker.formatDate("yy-mm-dd",v.end)}return w};c.prototype.setBarColor=function(w,v){if(v.not_defined){w.addClass("ganttview-block-not-defined")}else{w.css("background-color",v.color.background);w.css("border-color",v.color.border)}};c.prototype.listenForBlockResize=function(v){var w=this;jQuery("div.ganttview-block",this.options.container).resizable({grid:this.options.cellWidth,handles:"e,w",delay:300,stop:function(){var x=jQuery(this);w.updateDataAndPosition(x,v);w.saveRecord(x.data("record"))}})};c.prototype.listenForBlockMove=function(v){var w=this;jQuery("div.ganttview-block",this.options.container).draggable({axis:"x",delay:300,grid:[this.options.cellWidth,this.options.cellWidth],stop:function(){var x=jQuery(this);w.updateDataAndPosition(x,v);w.saveRecord(x.data("record"))}})};c.prototype.updateDataAndPosition=function(A,y){var v=jQuery("div.ganttview-slide-container",this.options.container);var E=v.scrollLeft();var B=A.offset().left-v.offset().left-1+E;var D=A.data("record");D.not_defined=false;this.setBarColor(A,D);var x=Math.round(B/this.options.cellWidth);var C=this.addDays(this.cloneDate(y),x);D.start=C;var w=A.outerWidth();var z=Math.round(w/this.options.cellWidth)-1;D.end=this.addDays(this.cloneDate(C),z);if(D.type==="task"&&z>0){jQuery("div.ganttview-block-text",A).text(D.progress)}A.attr("title",this.getBarTooltip(D));A.data("record",D);A.css("top","").css("left","").css("position","relative").css("margin-left",B+"px")};c.prototype.getDates=function(z,v){var y=[];y[z.getFullYear()]=[];y[z.getFullYear()][z.getMonth()]=[z];var x=z;while(this.compareDate(x,v)==-1){var w=this.addDays(this.cloneDate(x),1);if(!y[w.getFullYear()]){y[w.getFullYear()]=[]}if(!y[w.getFullYear()][w.getMonth()]){y[w.getFullYear()][w.getMonth()]=[]}y[w.getFullYear()][w.getMonth()].push(w);x=w}return y};c.prototype.prepareData=function(x){for(var w=0;wv)?1:0}else{throw new TypeError(w+" - "+v)}}};function a(){}a.prototype.listen=function(){$(document).on("click",".color-square",function(){$(".color-square-selected").removeClass("color-square-selected");$(this).addClass("color-square-selected");$("#form-color_id").val($(this).data("color-id"))})};function q(){}q.prototype.execute=function(){var x=$("#chart").data("metrics");var w=[];for(var v=0;v0){v.push(B[z][x])}}else{A[x].push(B[z][x]);if(x==0){w.push(C(y.parse(B[z][x])))}}}}c3.generate({data:{columns:A,type:"area-spline",groups:[v]},axis:{x:{type:"category",categories:w}}})};function m(){}m.prototype.execute=function(){var A=$("#chart").data("metrics");var z=[[$("#chart").data("label-total")]];var v=[];var x=d3.time.format("%Y-%m-%d");var B=d3.time.format($("#chart").data("date-format"));for(var y=0;y0){if(z[0][y]==undefined){z[0].push(0)}z[0][y]+=A[y][w]}if(w==0){v.push(B(x.parse(A[y][w])))}}}}c3.generate({data:{columns:z},axis:{x:{type:"category",categories:v}}})};function h(v){this.app=v}h.prototype.execute=function(){var x=$("#chart").data("metrics");var y=[$("#chart").data("label")];var v=[];for(var w in x){y.push(x[w].average);v.push(x[w].title)}c3.generate({data:{columns:[y],type:"bar"},bar:{width:{ratio:0.5}},axis:{x:{type:"category",categories:v},y:{tick:{format:this.app.formatDuration}}},legend:{show:false}})};function u(v){this.app=v}u.prototype.execute=function(){var x=$("#chart").data("metrics");var y=[$("#chart").data("label")];var v=[];for(var w=0;w $baseDir . '/app/Action/CommentCreation.php', 'Kanboard\\Action\\TaskAssignCategoryColor' => $baseDir . '/app/Action/TaskAssignCategoryColor.php', 'Kanboard\\Action\\TaskAssignCategoryLabel' => $baseDir . '/app/Action/TaskAssignCategoryLabel.php', + 'Kanboard\\Action\\TaskAssignCategoryLink' => $baseDir . '/app/Action/TaskAssignCategoryLink.php', 'Kanboard\\Action\\TaskAssignColorCategory' => $baseDir . '/app/Action/TaskAssignColorCategory.php', 'Kanboard\\Action\\TaskAssignColorColumn' => $baseDir . '/app/Action/TaskAssignColorColumn.php', 'Kanboard\\Action\\TaskAssignColorLink' => $baseDir . '/app/Action/TaskAssignColorLink.php', @@ -192,7 +193,10 @@ return array( 'Kanboard\\Core\\Csv' => $baseDir . '/app/Core/Csv.php', 'Kanboard\\Core\\DateParser' => $baseDir . '/app/Core/DateParser.php', 'Kanboard\\Core\\Helper' => $baseDir . '/app/Core/Helper.php', - 'Kanboard\\Core\\HttpClient' => $baseDir . '/app/Core/HttpClient.php', + 'Kanboard\\Core\\Http\\Client' => $baseDir . '/app/Core/Http/Client.php', + 'Kanboard\\Core\\Http\\Request' => $baseDir . '/app/Core/Http/Request.php', + 'Kanboard\\Core\\Http\\Response' => $baseDir . '/app/Core/Http/Response.php', + 'Kanboard\\Core\\Http\\Router' => $baseDir . '/app/Core/Http/Router.php', 'Kanboard\\Core\\Lexer' => $baseDir . '/app/Core/Lexer.php', 'Kanboard\\Core\\Mail\\Client' => $baseDir . '/app/Core/Mail/Client.php', 'Kanboard\\Core\\Mail\\ClientInterface' => $baseDir . '/app/Core/Mail/ClientInterface.php', @@ -208,11 +212,10 @@ return array( 'Kanboard\\Core\\Plugin\\Base' => $baseDir . '/app/Core/Plugin/Base.php', 'Kanboard\\Core\\Plugin\\Hook' => $baseDir . '/app/Core/Plugin/Hook.php', 'Kanboard\\Core\\Plugin\\Loader' => $baseDir . '/app/Core/Plugin/Loader.php', - 'Kanboard\\Core\\Request' => $baseDir . '/app/Core/Request.php', - 'Kanboard\\Core\\Response' => $baseDir . '/app/Core/Response.php', - 'Kanboard\\Core\\Router' => $baseDir . '/app/Core/Router.php', - 'Kanboard\\Core\\Security' => $baseDir . '/app/Core/Security.php', - 'Kanboard\\Core\\Session' => $baseDir . '/app/Core/Session.php', + 'Kanboard\\Core\\Security\\Token' => $baseDir . '/app/Core/Security/Token.php', + 'Kanboard\\Core\\Session\\FlashMessage' => $baseDir . '/app/Core/Session/FlashMessage.php', + 'Kanboard\\Core\\Session\\SessionManager' => $baseDir . '/app/Core/Session/SessionManager.php', + 'Kanboard\\Core\\Session\\SessionStorage' => $baseDir . '/app/Core/Session/SessionStorage.php', 'Kanboard\\Core\\Template' => $baseDir . '/app/Core/Template.php', 'Kanboard\\Core\\Tool' => $baseDir . '/app/Core/Tool.php', 'Kanboard\\Core\\Translator' => $baseDir . '/app/Core/Translator.php', @@ -311,6 +314,7 @@ return array( 'Kanboard\\ServiceProvider\\DatabaseProvider' => $baseDir . '/app/ServiceProvider/DatabaseProvider.php', 'Kanboard\\ServiceProvider\\EventDispatcherProvider' => $baseDir . '/app/ServiceProvider/EventDispatcherProvider.php', 'Kanboard\\ServiceProvider\\LoggingProvider' => $baseDir . '/app/ServiceProvider/LoggingProvider.php', + 'Kanboard\\ServiceProvider\\SessionProvider' => $baseDir . '/app/ServiceProvider/SessionProvider.php', 'Kanboard\\Subscriber\\AuthSubscriber' => $baseDir . '/app/Subscriber/AuthSubscriber.php', 'Kanboard\\Subscriber\\BootstrapSubscriber' => $baseDir . '/app/Subscriber/BootstrapSubscriber.php', 'Kanboard\\Subscriber\\NotificationSubscriber' => $baseDir . '/app/Subscriber/NotificationSubscriber.php', diff --git a/sources/vendor/composer/autoload_real.php b/sources/vendor/composer/autoload_real.php index aab7557..b758860 100644 --- a/sources/vendor/composer/autoload_real.php +++ b/sources/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitfedc82edf7e371a21d453e88d769a28b +class ComposerAutoloaderInita25e89ea30b7b9b184f2a86b0c780282 { private static $loader; @@ -19,9 +19,9 @@ class ComposerAutoloaderInitfedc82edf7e371a21d453e88d769a28b return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInitfedc82edf7e371a21d453e88d769a28b', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInita25e89ea30b7b9b184f2a86b0c780282', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInitfedc82edf7e371a21d453e88d769a28b', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInita25e89ea30b7b9b184f2a86b0c780282', 'loadClassLoader')); $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -42,14 +42,14 @@ class ComposerAutoloaderInitfedc82edf7e371a21d453e88d769a28b $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $file) { - composerRequirefedc82edf7e371a21d453e88d769a28b($file); + composerRequirea25e89ea30b7b9b184f2a86b0c780282($file); } return $loader; } } -function composerRequirefedc82edf7e371a21d453e88d769a28b($file) +function composerRequirea25e89ea30b7b9b184f2a86b0c780282($file) { require $file; }