diff options
187 files changed, 3566 insertions, 1414 deletions
diff --git a/.dockerignore b/.dockerignore index 19c8e14b..8662306f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -12,7 +12,6 @@ Makefile *.sh app.json bower.json -nitrous.json package.json Vagrantfile web.config @@ -6,21 +6,21 @@ RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [QSA,L] + + ############################ + ## Uncomment the two lines below to enable force HTTPS capabilities + ############################ + + # RewriteCond %{HTTPS} !=on + # RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L] + + ########################### + ## Notes: + ## The first directive will check to make sure the connection is not already HTTPS + ## + ## The second directive will redirect users from their original location, to the same location but using HTTPS. + ## i.e. http://www.example.com/foo/ to https://www.example.com/foo/ + ## The leading slash is made optional so that this will work either in httpd.conf + ## or .htaccess context + ############################ </IfModule> - -<FilesMatch "(kanboard|config.php|config.default.php)"> - <IfModule mod_version.c> - <IfVersion >= 2.3> - Require all denied - </IfVersion> - <IfVersion < 2.3> - Order allow,deny - Deny from all - </IfVersion> - </IfModule> - - <IfModule !mod_version.c> - Order allow,deny - Deny from all - </IfModule> -</FilesMatch> diff --git a/.travis.yml b/.travis.yml index c5300575..8c78bf8b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,8 @@ before_script: - if [[ $TRAVIS_PHP_VERSION != 7.x ]]; then phpenv config-rm xdebug.ini; fi - phpenv config-add tests/php.ini - composer install + - npm install + - ./node_modules/.bin/jshint assets/js/{core,components} script: - phpunit -c tests/units.$DB.xml diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 3a976930..b19698a8 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -14,9 +14,11 @@ Contributors: - [Anton](https://github.com/tester22) - [Ashbike](https://github.com/ashbike) - [Ashish Kulkarni](https://github.com/ashkulz) +- [António Pereira](https://github.com/Shaxine) - [Biniou180](https://github.com/Biniou180) - [Bitcoin 333](https://github.com/bitcoin333) - [Busfreak](https://github.com/Busfreak) +- [Carlos Ferreira](https://github.com/acs-ferreira) - [Christian González](https://github.com/nerdoc) - [Christopher Geelen](https://github.com/cdgeelen) - [Chorgroup](https://github.com/chorgroup) @@ -32,9 +34,11 @@ Contributors: - [Damian](https://github.com/dromek) - [Daniel Raknes](https://github.com/danielraknes) - [David-Norris](https://github.com/David-Norris) +- [Diego Betto](https://github.com/diego-betto) - [Dmitry](https://github.com/dmkcv) - [Dj Padzensky](https://github.com/djpadz) - [Draza (bdpsoft)](https://github.com/bdpsoft) +- [erpnedir](https://github.com/erpnedir) - [Eskiso](https://github.com/eSkiSo) - [Esteban Monge](https://github.com/EstebanMonge) - [Eugene (JohnBat26)](https://github.com/JohnBat26) @@ -46,6 +50,7 @@ Contributors: - [Floaltvater](https://github.com/floaltvater) - [Gavlepeter](https://github.com/gavlepeter) - [Gerardo Zamudio](https://github.com/gerardozamudio) +- [Girish Ramakrishnan](https://github.com/gramakri) - [Goofy](https://github.com/goofy-bz) - [Hairetdin](https://github.com/hairetdin) - [Hendrik Stocker](https://github.com/hendrik-stoker) @@ -58,8 +63,9 @@ Contributors: - [Jeff Guillou](https://github.com/jf-guillou) - [Jesusaplsoft](https://github.com/jesusaplsoft) - [Jesús MarÃn](https://github.com/alu0100502114) +- [Jonas Oliveira Francisco](https://github.com/jonasof) - [Jules Verhaeren](https://github.com/julesverhaeren) -- [JunglaCODE]https://github.com/junglaCODE) +- [JunglaCODE](https://github.com/junglaCODE) - [Karol J](https://github.com/dzudek) - [Kiswa](https://github.com/kiswa) - [Kralo](https://github.com/kralo) @@ -85,6 +91,7 @@ Contributors: - [Moraxy](https://github.com/moraxy) - [Muhaimin](https://github.com/infacq) - [Nala Ginrut](https://github.com/NalaGinrut) +- [Napier](https://github.com/napiera) - [Nekohayo](https://github.com/nekohayo) - [Ngtech](https://github.com/ngtech) - [Nicolas LÅ“uillet](https://github.com/nicosomb) @@ -106,6 +113,7 @@ Contributors: - [Perburn](https://github.com/perburn) - [Peripatetic-sojourner](https://github.com/peripatetic-sojourner) - [Petja Touru](https://github.com/Petja) +- [PhilLAL](https://github.com/PhilLAL) - [Pierre-Alexis de Solminihac](https://github.com/pa-de-solminihac) - [Piotr ZÄ™gota](https://github.com/ZegalPL) - [Rafaelrossa](https://github.com/rafaelrossa) @@ -132,6 +140,7 @@ Contributors: - [Torsten](https://github.com/misterfu) - [Troloo](https://github.com/troloo) - [Typz](https://github.com/Typz) +- [Valentino Pistis](https://github.com/vpistis) - [Vedovator](https://github.com/vedovator) - [Vitaliy S. Orlov](https://github.com/orlov0562) - [Vladimir Babin](https://github.com/Chiliec) @@ -1,9 +1,36 @@ Version 1.0.35 (not released yet) -------------------------------- +New features: + +* Add external tasks plugin interfaces +* Add personal API access token for users +* Rewrite of Markdown editor (remove CodeMirror) +* Suggest menu for task ID and user mentions in Markdown editor +* Add config parameter to disable automatic SQL migrations + Improvements: * Add button to close inline popups +* Simplify `.htaccess` to avoid potential issues with possible specific Apache configurations +* Replace notifications Javascript code by CSS +* Refactoring of user mentions job +* Remove Nitrous installer +* Update translations +* Rewrite some components in Vanilla Javascript +* Started Javascript code refactoring to avoid to much dependencies on jQuery +* Remove dependency on VueJS and CoreMirror +* Add P3P headers to avoid potential issues with IE + +Breaking changes: + +* Rename command line tool `./kanboard` to `./cli` + +Bug fixes: + +* Change column type for application settings value (field too small) +* Fix link generation when user mention is followed by a punctuation mark +* Make user mentions works again Version 1.0.34 (11 Oct 2016) --------------------------- @@ -9,6 +9,10 @@ static: clean @ npm install @ ./node_modules/.bin/gulp bower @ ./node_modules/.bin/gulp vendor js css + @ ./node_modules/.bin/jshint assets/js/{core,components,polyfills} + +jshint: + @ ./node_modules/.bin/jshint assets/js/{core,components,polyfills} archive: @ echo "Build archive: version=${version}, destination=${dst}" @@ -32,7 +36,6 @@ archive: @ rm -rf ${BUILD_DIR}/kanboard/*.js @ rm -rf ${BUILD_DIR}/kanboard/.dockerignore @ rm -rf ${BUILD_DIR}/kanboard/docker - @ rm -rf ${BUILD_DIR}/kanboard/nitrous* @ cd ${BUILD_DIR}/kanboard && find ./vendor -name doc -type d -exec rm -rf {} +; @ cd ${BUILD_DIR}/kanboard && find ./vendor -name notes -type d -exec rm -rf {} +; @ cd ${BUILD_DIR}/kanboard && find ./vendor -name test -type d -exec rm -rf {} +; @@ -60,8 +63,6 @@ test-mysql: test-postgres: @ ./vendor/bin/phpunit -c tests/units.postgres.xml -unittest: test-sqlite test-mysql test-postgres - test-browser: @ ./vendor/bin/phpunit -c tests/acceptance.xml @@ -104,6 +105,8 @@ sql: @ let pg_version=`psql -U postgres -A -c 'copy(select version from schema_version) to stdout;' kanboard` ;\ echo "INSERT INTO schema_version VALUES ('$$pg_version');" >> app/Schema/Sql/postgres.sql + @ grep -v "SET idle_in_transaction_session_timeout = 0;" app/Schema/Sql/postgres.sql > temp && mv temp app/Schema/Sql/postgres.sql + docker-image: @ docker build -t kanboard/kanboard:latest . diff --git a/app/Api/Middleware/AuthenticationMiddleware.php b/app/Api/Middleware/AuthenticationMiddleware.php index 8e309593..c4fa874a 100644 --- a/app/Api/Middleware/AuthenticationMiddleware.php +++ b/app/Api/Middleware/AuthenticationMiddleware.php @@ -28,6 +28,7 @@ class AuthenticationMiddleware extends Base implements MiddlewareInterface public function execute($username, $password, $procedureName) { $this->dispatcher->dispatch('app.bootstrap'); + $this->sessionStorage->scope = 'API'; if ($this->isUserAuthenticated($username, $password)) { $this->userSession->initialize($this->userModel->getByUsername($username)); diff --git a/app/Auth/ApiAccessTokenAuth.php b/app/Auth/ApiAccessTokenAuth.php new file mode 100644 index 00000000..12ab21a7 --- /dev/null +++ b/app/Auth/ApiAccessTokenAuth.php @@ -0,0 +1,119 @@ +<?php + +namespace Kanboard\Auth; + +use Kanboard\Core\Base; +use Kanboard\Core\Security\PasswordAuthenticationProviderInterface; +use Kanboard\Model\UserModel; +use Kanboard\User\DatabaseUserProvider; + +/** + * API Access Token Authentication Provider + * + * @package Kanboard\Auth + * @author Frederic Guillot + */ +class ApiAccessTokenAuth extends Base implements PasswordAuthenticationProviderInterface +{ + /** + * User properties + * + * @access protected + * @var array + */ + protected $userInfo = array(); + + /** + * Username + * + * @access protected + * @var string + */ + protected $username = ''; + + /** + * Password + * + * @access protected + * @var string + */ + protected $password = ''; + + /** + * Get authentication provider name + * + * @access public + * @return string + */ + public function getName() + { + return 'API Access Token'; + } + + /** + * Authenticate the user + * + * @access public + * @return boolean + */ + public function authenticate() + { + if (! isset($this->sessionStorage->scope) || $this->sessionStorage->scope !== 'API') { + $this->logger->debug(__METHOD__.': Authentication provider skipped because invalid scope'); + return false; + } + + $user = $this->db + ->table(UserModel::TABLE) + ->columns('id', 'password') + ->eq('username', $this->username) + ->eq('api_access_token', $this->password) + ->notNull('api_access_token') + ->eq('is_active', 1) + ->findOne(); + + if (! empty($user)) { + $this->userInfo = $user; + return true; + } + + return false; + } + + /** + * Get user object + * + * @access public + * @return \Kanboard\User\DatabaseUserProvider + */ + public function getUser() + { + if (empty($this->userInfo)) { + return null; + } + + return new DatabaseUserProvider($this->userInfo); + } + + /** + * Set username + * + * @access public + * @param string $username + */ + public function setUsername($username) + { + $this->username = $username; + } + + /** + * Set password + * + * @access public + * @param string $password + */ + public function setPassword($password) + { + $this->password = $password; + } +} diff --git a/app/Auth/DatabaseAuth.php b/app/Auth/DatabaseAuth.php index ecb42c17..84a1e019 100644 --- a/app/Auth/DatabaseAuth.php +++ b/app/Auth/DatabaseAuth.php @@ -11,7 +11,7 @@ use Kanboard\User\DatabaseUserProvider; /** * Database Authentication Provider * - * @package auth + * @package Kanboard\Auth * @author Frederic Guillot */ class DatabaseAuth extends Base implements PasswordAuthenticationProviderInterface, SessionCheckProviderInterface diff --git a/app/Auth/LdapAuth.php b/app/Auth/LdapAuth.php index a8dcfcb6..05ffbebf 100644 --- a/app/Auth/LdapAuth.php +++ b/app/Auth/LdapAuth.php @@ -12,7 +12,7 @@ use Kanboard\Core\Security\PasswordAuthenticationProviderInterface; /** * LDAP Authentication Provider * - * @package auth + * @package Kanboard\Auth * @author Frederic Guillot */ class LdapAuth extends Base implements PasswordAuthenticationProviderInterface diff --git a/app/Auth/RememberMeAuth.php b/app/Auth/RememberMeAuth.php index 5d0a8b2e..e0f4ceb6 100644 --- a/app/Auth/RememberMeAuth.php +++ b/app/Auth/RememberMeAuth.php @@ -7,9 +7,9 @@ use Kanboard\Core\Security\PreAuthenticationProviderInterface; use Kanboard\User\DatabaseUserProvider; /** - * Rember Me Cookie Authentication Provider + * RememberMe Cookie Authentication Provider * - * @package auth + * @package Kanboard\Auth * @author Frederic Guillot */ class RememberMeAuth extends Base implements PreAuthenticationProviderInterface diff --git a/app/Auth/ReverseProxyAuth.php b/app/Auth/ReverseProxyAuth.php index fdf936b1..02afc302 100644 --- a/app/Auth/ReverseProxyAuth.php +++ b/app/Auth/ReverseProxyAuth.php @@ -10,7 +10,7 @@ use Kanboard\User\ReverseProxyUserProvider; /** * Reverse-Proxy Authentication Provider * - * @package auth + * @package Kanboard\Auth * @author Frederic Guillot */ class ReverseProxyAuth extends Base implements PreAuthenticationProviderInterface, SessionCheckProviderInterface diff --git a/app/Auth/TotpAuth.php b/app/Auth/TotpAuth.php index 8e1ebe35..abfb2168 100644 --- a/app/Auth/TotpAuth.php +++ b/app/Auth/TotpAuth.php @@ -11,7 +11,7 @@ use Kanboard\Core\Security\PostAuthenticationProviderInterface; /** * TOTP Authentication Provider * - * @package auth + * @package Kanboard\Auth * @author Frederic Guillot */ class TotpAuth extends Base implements PostAuthenticationProviderInterface diff --git a/app/Console/DatabaseMigrationCommand.php b/app/Console/DatabaseMigrationCommand.php new file mode 100644 index 00000000..252d4369 --- /dev/null +++ b/app/Console/DatabaseMigrationCommand.php @@ -0,0 +1,23 @@ +<?php + +namespace Kanboard\Console; + +use Kanboard\ServiceProvider\DatabaseProvider; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class DatabaseMigrationCommand extends DatabaseVersionCommand +{ + protected function configure() + { + $this + ->setName('db:migrate') + ->setDescription('Execute SQL migrations'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + parent::execute($input, $output); + DatabaseProvider::runMigrations($this->container['db']); + } +} diff --git a/app/Console/DatabaseVersionCommand.php b/app/Console/DatabaseVersionCommand.php new file mode 100644 index 00000000..5b1f1ed1 --- /dev/null +++ b/app/Console/DatabaseVersionCommand.php @@ -0,0 +1,23 @@ +<?php + +namespace Kanboard\Console; + +use Kanboard\ServiceProvider\DatabaseProvider; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class DatabaseVersionCommand extends BaseCommand +{ + protected function configure() + { + $this + ->setName('db:version') + ->setDescription('Show database schema version'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $output->writeln('<info>Current version: '.DatabaseProvider::getSchemaVersion($this->container['db']).'</info>'); + $output->writeln('<info>Last version: '.\Schema\VERSION.'</info>'); + } +} diff --git a/app/Controller/CommentController.php b/app/Controller/CommentController.php index c61a0602..526bd2bf 100644 --- a/app/Controller/CommentController.php +++ b/app/Controller/CommentController.php @@ -48,6 +48,7 @@ class CommentController extends BaseController */ public function create(array $values = array(), array $errors = array()) { + $project = $this->getProject(); $task = $this->getTask(); if (empty($values)) { @@ -57,10 +58,13 @@ class CommentController extends BaseController ); } - $this->response->html($this->template->render('comment/create', array( + $values['project_id'] = $task['project_id']; + + $this->response->html($this->helper->layout->task('comment/create', array( 'values' => $values, 'errors' => $errors, 'task' => $task, + 'project' => $project, ))); } @@ -103,8 +107,14 @@ class CommentController extends BaseController $task = $this->getTask(); $comment = $this->getComment(); + if (empty($values)) { + $values = $comment; + } + + $values['project_id'] = $task['project_id']; + $this->response->html($this->template->render('comment/edit', array( - 'values' => empty($values) ? $comment : $values, + 'values' => $values, 'errors' => $errors, 'comment' => $comment, 'task' => $task, diff --git a/app/Controller/TaskAjaxController.php b/app/Controller/TaskAjaxController.php index f9feff15..609dd23c 100644 --- a/app/Controller/TaskAjaxController.php +++ b/app/Controller/TaskAjaxController.php @@ -5,8 +5,12 @@ namespace Kanboard\Controller; use Kanboard\Filter\TaskIdExclusionFilter; use Kanboard\Filter\TaskIdFilter; use Kanboard\Filter\TaskProjectsFilter; +use Kanboard\Filter\TaskStartsWithIdFilter; +use Kanboard\Filter\TaskStatusFilter; use Kanboard\Filter\TaskTitleFilter; use Kanboard\Formatter\TaskAutoCompleteFormatter; +use Kanboard\Formatter\TaskSuggestMenuFormatter; +use Kanboard\Model\TaskModel; /** * Task Ajax Controller @@ -19,7 +23,6 @@ class TaskAjaxController extends BaseController /** * Task auto-completion (Ajax) * - * @access public */ public function autocomplete() { @@ -46,4 +49,24 @@ class TaskAjaxController extends BaseController $this->response->json($filter->format(new TaskAutoCompleteFormatter($this->container))); } } + + /** + * Task ID suggest menu + */ + public function suggest() + { + $taskId = $this->request->getIntegerParam('search'); + $projectIds = $this->projectPermissionModel->getActiveProjectIds($this->userSession->getId()); + + if (empty($projectIds)) { + $this->response->json(array()); + } else { + $filter = $this->taskQuery + ->withFilter(new TaskProjectsFilter($projectIds)) + ->withFilter(new TaskStatusFilter(TaskModel::STATUS_OPEN)) + ->withFilter(new TaskStartsWithIdFilter($taskId)); + + $this->response->json($filter->format(new TaskSuggestMenuFormatter($this->container))); + } + } } diff --git a/app/Controller/UserAjaxController.php b/app/Controller/UserAjaxController.php index ed180471..d93bfe9a 100644 --- a/app/Controller/UserAjaxController.php +++ b/app/Controller/UserAjaxController.php @@ -4,6 +4,7 @@ namespace Kanboard\Controller; use Kanboard\Filter\UserNameFilter; use Kanboard\Formatter\UserAutoCompleteFormatter; +use Kanboard\Formatter\UserMentionFormatter; use Kanboard\Model\UserModel; /** @@ -35,9 +36,14 @@ class UserAjaxController extends BaseController public function mention() { $project_id = $this->request->getStringParam('project_id'); - $query = $this->request->getStringParam('q'); + $query = $this->request->getStringParam('search'); $users = $this->projectPermissionModel->findUsernames($project_id, $query); - $this->response->json($users); + + $this->response->json( + UserMentionFormatter::getInstance($this->container) + ->withUsers($users) + ->format() + ); } /** diff --git a/app/Controller/UserApiAccessController.php b/app/Controller/UserApiAccessController.php new file mode 100644 index 00000000..e03514d5 --- /dev/null +++ b/app/Controller/UserApiAccessController.php @@ -0,0 +1,50 @@ +<?php + +namespace Kanboard\Controller; + +use Kanboard\Core\Security\Token; + +/** + * Class UserApiAccessController + * + * @package Kanboard\Controller + * @author Frederic Guillot + */ +class UserApiAccessController extends BaseController +{ + public function show() + { + $user = $this->getUser(); + + return $this->response->html($this->helper->layout->user('user_api_access/show', array( + 'user' => $user, + 'title' => t('API User Access'), + ))); + } + + public function generate() + { + $user = $this->getUser(); + $this->checkCSRFParam(); + + $this->userModel->update(array( + 'id' => $user['id'], + 'api_access_token' => Token::getToken(), + )); + + $this->response->redirect($this->helper->url->to('UserApiAccessController', 'show', array('user_id' => $user['id']))); + } + + public function remove() + { + $user = $this->getUser(); + $this->checkCSRFParam(); + + $this->userModel->update(array( + 'id' => $user['id'], + 'api_access_token' => null, + )); + + $this->response->redirect($this->helper->url->to('UserApiAccessController', 'show', array('user_id' => $user['id']))); + } +}
\ No newline at end of file diff --git a/app/Core/Base.php b/app/Core/Base.php index 3dbf47f9..e7ccafaa 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -126,7 +126,6 @@ use Pimple\Container; * @property \Kanboard\Model\TransitionModel $transitionModel * @property \Kanboard\Model\UserModel $userModel * @property \Kanboard\Model\UserLockingModel $userLockingModel - * @property \Kanboard\Model\UserMentionModel $userMentionModel * @property \Kanboard\Model\UserNotificationModel $userNotificationModel * @property \Kanboard\Model\UserNotificationTypeModel $userNotificationTypeModel * @property \Kanboard\Model\UserNotificationFilterModel $userNotificationFilterModel @@ -178,6 +177,7 @@ use Pimple\Container; * @property \Kanboard\Job\ProjectFileEventJob $projectFileEventJob * @property \Kanboard\Job\NotificationJob $notificationJob * @property \Kanboard\Job\ProjectMetricJob $projectMetricJob + * @property \Kanboard\Job\UserMentionJob $userMentionJob * @property \Psr\Log\LoggerInterface $logger * @property \PicoDb\Database $db * @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher diff --git a/app/Core/Helper.php b/app/Core/Helper.php index b5c560af..9660c348 100644 --- a/app/Core/Helper.php +++ b/app/Core/Helper.php @@ -12,6 +12,7 @@ use Pimple\Container; * * @property \Kanboard\Helper\AppHelper $app * @property \Kanboard\Helper\AssetHelper $asset + * @property \Kanboard\Helper\AvatarHelper $avatar * @property \Kanboard\Helper\BoardHelper $board * @property \Kanboard\Helper\CalendarHelper $calendar * @property \Kanboard\Helper\DateHelper $dt diff --git a/app/Core/Markdown.php b/app/Core/Markdown.php index b5abe5ed..799aefb4 100644 --- a/app/Core/Markdown.php +++ b/app/Core/Markdown.php @@ -86,7 +86,7 @@ class Markdown extends Parsedown */ protected function inlineUserLink(array $Excerpt) { - if (! $this->isPublicLink && preg_match('/^@([^\s]+)/', $Excerpt['text'], $matches)) { + if (! $this->isPublicLink && preg_match('/^@([^\s,!.:?]+)/', $Excerpt['text'], $matches)) { $user_id = $this->container['userModel']->getIdByUsername($matches[1]); if (! empty($user_id)) { @@ -125,7 +125,10 @@ class Markdown extends Parsedown array( 'token' => $token, 'task_id' => $task_id, - ) + ), + false, + '', + true ); } diff --git a/app/Core/Session/SessionStorage.php b/app/Core/Session/SessionStorage.php index 9e93602c..e6478d8d 100644 --- a/app/Core/Session/SessionStorage.php +++ b/app/Core/Session/SessionStorage.php @@ -19,6 +19,7 @@ namespace Kanboard\Core\Session; * @property bool $hasSubtaskInProgress * @property bool $hasRememberMe * @property bool $boardCollapsed + * @property string $scope * @property bool $twoFactorBeforeCodeCalled * @property string $twoFactorSecret * @property string $oauthState diff --git a/app/Event/GenericEvent.php b/app/Event/GenericEvent.php index 94a51479..e87d9481 100644 --- a/app/Event/GenericEvent.php +++ b/app/Event/GenericEvent.php @@ -14,6 +14,28 @@ class GenericEvent extends BaseEvent implements ArrayAccess $this->container = $values; } + public function getTaskId() + { + if (isset($this->container['task']['id'])) { + return $this->container['task']['id']; + } + + if (isset($this->container['task_id'])) { + return $this->container['task_id']; + } + + return null; + } + + public function getProjectId() + { + if (isset($this->container['task']['project_id'])) { + return $this->container['task']['project_id']; + } + + return null; + } + public function getAll() { return $this->container; diff --git a/app/Event/ProjectFileEvent.php b/app/Event/ProjectFileEvent.php index 5d57e463..e1d29c48 100644 --- a/app/Event/ProjectFileEvent.php +++ b/app/Event/ProjectFileEvent.php @@ -4,4 +4,12 @@ namespace Kanboard\Event; class ProjectFileEvent extends GenericEvent { + public function getProjectId() + { + if (isset($this->container['file']['project_id'])) { + return $this->container['file']['project_id']; + } + + return null; + } } diff --git a/app/Filter/TaskStartsWithIdFilter.php b/app/Filter/TaskStartsWithIdFilter.php new file mode 100644 index 00000000..8b7cc678 --- /dev/null +++ b/app/Filter/TaskStartsWithIdFilter.php @@ -0,0 +1,38 @@ +<?php + +namespace Kanboard\Filter; + +use Kanboard\Core\Filter\FilterInterface; +use Kanboard\Model\TaskModel; + +/** + * Class TaskIdSearchFilter + * + * @package Kanboard\Filter + * @author Frederic Guillot + */ +class TaskStartsWithIdFilter extends BaseFilter implements FilterInterface +{ + /** + * Get search attribute + * + * @access public + * @return string[] + */ + public function getAttributes() + { + return array('starts_with_id'); + } + + /** + * Apply filter + * + * @access public + * @return FilterInterface + */ + public function apply() + { + $this->query->ilike('CAST('.TaskModel::TABLE.'.id AS CHAR(8))', $this->value.'%'); + return $this; + } +} diff --git a/app/Formatter/BaseFormatter.php b/app/Formatter/BaseFormatter.php index 89c48437..0d62628e 100644 --- a/app/Formatter/BaseFormatter.php +++ b/app/Formatter/BaseFormatter.php @@ -4,7 +4,6 @@ namespace Kanboard\Formatter; use Kanboard\Core\Base; use PicoDb\Table; -use Pimple\Container; /** * Class BaseFormatter @@ -23,19 +22,6 @@ abstract class BaseFormatter extends Base protected $query; /** - * Get object instance - * - * @static - * @access public - * @param Container $container - * @return static - */ - public static function getInstance(Container $container) - { - return new static($container); - } - - /** * Set query * * @access public diff --git a/app/Formatter/BaseTaskCalendarFormatter.php b/app/Formatter/BaseTaskCalendarFormatter.php index 8fab3e9a..3d9ead4d 100644 --- a/app/Formatter/BaseTaskCalendarFormatter.php +++ b/app/Formatter/BaseTaskCalendarFormatter.php @@ -2,8 +2,6 @@ namespace Kanboard\Formatter; -use Kanboard\Core\Filter\FormatterInterface; - /** * Common class to handle calendar events * @@ -34,7 +32,7 @@ abstract class BaseTaskCalendarFormatter extends BaseFormatter * @access public * @param string $start_column Column name for the start date * @param string $end_column Column name for the end date - * @return FormatterInterface + * @return $this */ public function setColumns($start_column, $end_column = '') { diff --git a/app/Formatter/TaskAutoCompleteFormatter.php b/app/Formatter/TaskAutoCompleteFormatter.php index 2d9f7341..3a4f1e1a 100644 --- a/app/Formatter/TaskAutoCompleteFormatter.php +++ b/app/Formatter/TaskAutoCompleteFormatter.php @@ -14,6 +14,20 @@ use Kanboard\Model\TaskModel; */ class TaskAutoCompleteFormatter extends BaseFormatter implements FormatterInterface { + protected $limit = 25; + + /** + * Limit number of results + * + * @param $limit + * @return $this + */ + public function withLimit($limit) + { + $this->limit = $limit; + return $this; + } + /** * Apply formatter * @@ -22,11 +36,15 @@ class TaskAutoCompleteFormatter extends BaseFormatter implements FormatterInterf */ public function format() { - $tasks = $this->query->columns( - TaskModel::TABLE.'.id', - TaskModel::TABLE.'.title', - ProjectModel::TABLE.'.name AS project_name' - )->asc(TaskModel::TABLE.'.id')->findAll(); + $tasks = $this->query + ->columns( + TaskModel::TABLE.'.id', + TaskModel::TABLE.'.title', + ProjectModel::TABLE.'.name AS project_name' + ) + ->asc(TaskModel::TABLE.'.id') + ->limit($this->limit) + ->findAll(); foreach ($tasks as &$task) { $task['value'] = $task['title']; diff --git a/app/Formatter/TaskSuggestMenuFormatter.php b/app/Formatter/TaskSuggestMenuFormatter.php new file mode 100644 index 00000000..518f99e6 --- /dev/null +++ b/app/Formatter/TaskSuggestMenuFormatter.php @@ -0,0 +1,63 @@ +<?php + +namespace Kanboard\Formatter; + +use Kanboard\Core\Filter\FormatterInterface; +use Kanboard\Model\ProjectModel; +use Kanboard\Model\TaskModel; + +/** + * Class TaskSuggestMenuFormatter + * + * @package Kanboard\Formatter + * @author Frederic Guillot + */ +class TaskSuggestMenuFormatter extends BaseFormatter implements FormatterInterface +{ + protected $limit = 25; + + /** + * Limit number of results + * + * @param $limit + * @return $this + */ + public function withLimit($limit) + { + $this->limit = $limit; + return $this; + } + + /** + * Apply formatter + * + * @access public + * @return mixed + */ + public function format() + { + $result = array(); + $tasks = $this->query + ->columns( + TaskModel::TABLE.'.id', + TaskModel::TABLE.'.title', + ProjectModel::TABLE.'.name AS project_name' + ) + ->asc(TaskModel::TABLE.'.id') + ->limit($this->limit) + ->findAll(); + + foreach ($tasks as $task) { + $html = '#'.$task['id'].' '; + $html .= $this->helper->text->e($task['title']).' '; + $html .= '<small>'.$this->helper->text->e($task['project_name']).'</small>'; + + $result[] = array( + 'value' => (string) $task['id'], + 'html' => $html, + ); + } + + return $result; + } +} diff --git a/app/Formatter/UserMentionFormatter.php b/app/Formatter/UserMentionFormatter.php new file mode 100644 index 00000000..395fc463 --- /dev/null +++ b/app/Formatter/UserMentionFormatter.php @@ -0,0 +1,60 @@ +<?php + +namespace Kanboard\Formatter; + +/** + * Class UserMentionFormatter + * + * @package Kanboard\Formatter + * @author Frederic Guillot + */ +class UserMentionFormatter extends BaseFormatter +{ + protected $users = array(); + + /** + * Set users + * + * @param array $users + * @return $this + */ + public function withUsers(array $users) { + $this->users = $users; + return $this; + } + + /** + * Apply formatter + * + * @access public + * @return array + */ + public function format() + { + $result = array(); + + foreach ($this->users as $user) { + $html = $this->helper->avatar->small( + $user['id'], + $user['username'], + $user['name'], + $user['email'], + $user['avatar_path'], + 'avatar-inline' + ); + + $html .= ' '.$this->helper->text->e($user['username']); + + if (! empty($user['name'])) { + $html .= ' <small>'.$this->helper->text->e($user['name']).'</small>'; + } + + $result[] = array( + 'value' => $user['username'], + 'html' => $html, + ); + } + + return $result; + } +}
\ No newline at end of file diff --git a/app/Helper/FormHelper.php b/app/Helper/FormHelper.php index 629de9ff..9eabd724 100644 --- a/app/Helper/FormHelper.php +++ b/app/Helper/FormHelper.php @@ -131,16 +131,34 @@ class FormHelper extends Base * Display a checkbox field * * @access public - * @param string $name Field name - * @param string $label Form label - * @param string $value Form value - * @param boolean $checked Field selected or not - * @param string $class CSS class + * @param string $name Field name + * @param string $label Form label + * @param string $value Form value + * @param boolean $checked Field selected or not + * @param string $class CSS class + * @param array $attributes * @return string */ - public function checkbox($name, $label, $value, $checked = false, $class = '') + public function checkbox($name, $label, $value, $checked = false, $class = '', array $attributes = array()) { - return '<label><input type="checkbox" name="'.$name.'" class="'.$class.'" value="'.$this->helper->text->e($value).'" '.($checked ? 'checked="checked"' : '').'> '.$this->helper->text->e($label).'</label>'; + $htmlAttributes = ''; + + if ($checked) { + $attributes['checked'] = 'checked'; + } + + foreach ($attributes as $attribute => $attributeValue) { + $htmlAttributes .= sprintf('%s="%s"', $attribute, $this->helper->text->e($attributeValue)); + } + + return sprintf( + '<label><input type="checkbox" name="%s" class="%s" value="%s" %s> %s</label>', + $name, + $class, + $this->helper->text->e($value), + $htmlAttributes, + $this->helper->text->e($label) + ); } /** @@ -195,15 +213,25 @@ class FormHelper extends Base { $params = array( 'name' => $name, - 'text' => isset($values[$name]) ? $this->helper->text->e($values[$name]) : '', + 'text' => isset($values[$name]) ? $values[$name] : '', 'css' => $this->errorClass($errors, $name), 'required' => isset($attributes['required']) && $attributes['required'], 'tabindex' => isset($attributes['tabindex']) ? $attributes['tabindex'] : '-1', 'labelPreview' => t('Preview'), 'labelWrite' => t('Write'), 'placeholder' => t('Write your text in Markdown'), + 'autofocus' => isset($attributes['autofocus']) && $attributes['autofocus'], + 'suggestOptions' => array( + 'triggers' => array( + '#' => $this->helper->url->to('TaskAjaxController', 'suggest', array('search' => 'SEARCH_TERM')), + ) + ), ); + if (isset($values['project_id'])) { + $params['suggestOptions']['triggers']['@'] = $this->helper->url->to('UserAjaxController', 'mention', array('project_id' => $values['project_id'], 'search' => 'SEARCH_TERM')); + } + $html = '<div class="js-text-editor" data-params=\''.json_encode($params, JSON_HEX_APOS).'\'></div>'; $html .= $this->errorList($errors, $name); diff --git a/app/Job/CommentEventJob.php b/app/Job/CommentEventJob.php index 47cf8020..62fae40a 100644 --- a/app/Job/CommentEventJob.php +++ b/app/Job/CommentEventJob.php @@ -31,7 +31,6 @@ class CommentEventJob extends BaseJob * * @param int $commentId * @param string $eventName - * @return $this */ public function execute($commentId, $eventName) { @@ -43,7 +42,8 @@ class CommentEventJob extends BaseJob $this->dispatcher->dispatch($eventName, $event); if ($eventName === CommentModel::EVENT_CREATE) { - $this->userMentionModel->fireEvents($event['comment']['comment'], CommentModel::EVENT_USER_MENTION, $event); + $userMentionJob = $this->userMentionJob->withParams($event['comment']['comment'], CommentModel::EVENT_USER_MENTION, $event); + $this->queueManager->push($userMentionJob); } } } diff --git a/app/Job/TaskEventJob.php b/app/Job/TaskEventJob.php index 7d026a68..acc7fca3 100644 --- a/app/Job/TaskEventJob.php +++ b/app/Job/TaskEventJob.php @@ -69,7 +69,8 @@ class TaskEventJob extends BaseJob $this->dispatcher->dispatch($eventName, $event); if ($eventName === TaskModel::EVENT_CREATE) { - $this->userMentionModel->fireEvents($event['task']['description'], TaskModel::EVENT_USER_MENTION, $event); + $userMentionJob = $this->userMentionJob->withParams($event['task']['description'], TaskModel::EVENT_USER_MENTION, $event); + $this->queueManager->push($userMentionJob); } } } diff --git a/app/Job/UserMentionJob.php b/app/Job/UserMentionJob.php new file mode 100644 index 00000000..bbb27131 --- /dev/null +++ b/app/Job/UserMentionJob.php @@ -0,0 +1,72 @@ +<?php + +namespace Kanboard\Job; + +use Kanboard\Event\GenericEvent; +use Kanboard\Model\UserModel; + +/** + * Class UserMentionJob + * + * @package Kanboard\Job + * @author Frederic Guillot + */ +class UserMentionJob extends BaseJob +{ + /** + * Set job parameters + * + * @param string $text + * @param string $eventName + * @param GenericEvent $event + * @return $this + */ + public function withParams($text, $eventName, GenericEvent $event) + { + $this->jobParams = array($text, $eventName, $event->getAll()); + return $this; + } + + /** + * Execute job + * + * @param string $text + * @param string $eventName + * @param array $eventData + */ + public function execute($text, $eventName, array $eventData) + { + $event = new GenericEvent($eventData); + $users = $this->getMentionedUsers($text); + + foreach ($users as $user) { + if ($this->projectPermissionModel->isMember($event->getProjectId(), $user['id'])) { + $event['mention'] = $user; + $this->dispatcher->dispatch($eventName, $event); + } + } + } + + /** + * Get list of mentioned users + * + * @access public + * @param string $text + * @return array + */ + public function getMentionedUsers($text) + { + $users = array(); + + if (preg_match_all('/@([^\s,!.:?]+)/', $text, $matches)) { + $users = $this->db->table(UserModel::TABLE) + ->columns('id', 'username', 'name', 'email', 'language') + ->eq('notifications_enabled', 1) + ->neq('id', $this->userSession->getId()) + ->in('username', array_unique($matches[1])) + ->findAll(); + } + + return $users; + } +} diff --git a/app/Locale/bs_BA/translations.php b/app/Locale/bs_BA/translations.php index cb9ad9d5..e27a4501 100644 --- a/app/Locale/bs_BA/translations.php +++ b/app/Locale/bs_BA/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php index 8541f303..5091de00 100644 --- a/app/Locale/cs_CZ/translations.php +++ b/app/Locale/cs_CZ/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 78a6d35e..2ca864e5 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 433b7a2f..950a3b77 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Verschieben einer Aufgabe ist nicht erlaubt', 'This value must be in the range %d to %d' => 'Dieser Wert muss im Bereich %d bis %d sein', 'You are not allowed to move this task.' => 'Sie haben nicht die Berechtigung, diese Aufgabe zu verschieben.', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/el_GR/translations.php b/app/Locale/el_GR/translations.php index ad17b4ed..7b7d855e 100644 --- a/app/Locale/el_GR/translations.php +++ b/app/Locale/el_GR/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index b3a68751..984d42db 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index 733625b6..41e51fa1 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index 59f4609e..daac98ed 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -1279,4 +1279,13 @@ return array( 'Moving a task is not permitted' => 'Déplaçer une tâche n\'est pas autorisé', 'This value must be in the range %d to %d' => 'Cette valeur doit être définie entre %d et %d', 'You are not allowed to move this task.' => 'Vous n\'êtes pas autorisé à déplacer cette tâche.', + 'API User Access' => 'Accès utilisateur de l\'API', + 'Preview' => 'Aperçu', + 'Write' => 'Écrire', + 'Write your text in Markdown' => 'Écrivez votre texte en Markdown', + 'New External Task: %s' => 'Nouvelle tâche externe : %s', + 'No personal API access token registered.' => 'Aucun jeton d\'accès personnel à l\'API enregistré.', + 'Your personal API access token is "%s"' => 'Votre jeton d\'accès personnel à l\'API est « %s »', + 'Remove your token' => 'Supprimer votre jeton', + 'Generate a new token' => 'Générer un nouveau jeton', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index b5a23428..784c27ba 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php index e711a512..9398d51d 100644 --- a/app/Locale/id_ID/translations.php +++ b/app/Locale/id_ID/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index fa5f5105..65defe86 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -297,7 +297,7 @@ return array( 'Display another project' => 'Mostra un altro progetto', 'Created by %s' => 'Creato da %s', 'Tasks Export' => 'Export dei task', - 'Start Date' => 'Data d\'inizio', + 'Start Date' => 'Data di inizio', 'End Date' => 'Data di fine', 'Execute' => 'Esegui', 'Task Id' => 'Id del task', @@ -780,8 +780,8 @@ return array( 'Add task' => 'Aggiungi task', 'Start date:' => 'Data di inizio:', 'Due date:' => 'Data di completamento:', - 'There is no start date or due date for this task.' => 'Nessuna data di inzio o di scadenza per questo task.', - 'Moving or resizing a task will change the start and due date of the task.' => 'Spostando o ridimensionado un task ne modifca la data di inzio e di scadenza.', + 'There is no start date or due date for this task.' => 'Nessuna data di inizio o di scadenza per questo task.', + 'Moving or resizing a task will change the start and due date of the task.' => 'Spostando o ridimensionado un task ne modifca la data di inizio e di scadenza.', 'There is no task in your project.' => 'Non ci sono task nel tuo progetto.', 'Gantt chart' => 'Grafici Gantt', 'People who are project managers' => 'Persone che sono manager di progetto', @@ -1184,7 +1184,7 @@ return array( 'Global tags' => 'Tag globali', 'There is no global tag at the moment.' => 'Non sono definiti tag globali al momento.', 'This field cannot be empty' => 'Questo campo non può essere vuoto', - 'Close a task when there is no activity in an specific column' => 'Chiudi un task quando non vi è alcuna attività in un specifica colonna', + 'Close a task when there is no activity in an specific column' => 'Chiudi un task quando non vi è alcuna attività in una specifica colonna', '%s removed a subtask for the task #%d' => '%s rimosso un subtask per il task #%d', '%s removed a comment on the task #%d' => '%s rimosso un commento nel task #%d', 'Comment removed on task #%d' => 'Commento rimosso nel task #%d', @@ -1234,17 +1234,17 @@ return array( 'Remove this role' => 'Cancella questo ruolo', 'There is no restriction for this role.' => 'Non ci sono restrizioni per questo ruolo.', 'Only moving task between those columns is permitted' => 'È permesso solo muovere i tast tra queste colonne', - 'Close a task in a specific column when not moved during a given period' => 'Chiudi un task in una colonna specifica quando non è mosso per un determinato periodo', + 'Close a task in a specific column when not moved during a given period' => 'Chiudi un task in una colonna specifica quando non viene mosso per un determinato periodo', 'Edit columns' => 'Modifica colonne', 'The column restriction has been created successfully.' => 'La restrizione per le colonne è stata creata correttamente.', 'Unable to create this column restriction.' => 'Impossibile creare questa restrizione per colonne.', 'Column restriction removed successfully.' => 'Restrizione per colonne rimossa correttamente.', 'Unable to remove this restriction.' => 'Impossibile rimuovere questa restrizione.', - 'Your custom project role has been created successfully.' => 'La regola per il progetto personalizzato è stata creata correttamente.', - 'Unable to create custom project role.' => 'Impossibile creare la regola per il progetto personalizzato.', - 'Your custom project role has been updated successfully.' => 'La regola per il progetto personalizzato è stata modificata correttamente.', - 'Unable to update custom project role.' => 'Impossibile modificare correttamente la regola per il progetto personalizzato.', - 'Custom project role removed successfully.' => 'Regola per il progetto personalizzato rimossa correttamente.', + 'Your custom project role has been created successfully.' => 'La regola personalizzata per il progetto è stata creata correttamente.', + 'Unable to create custom project role.' => 'Impossibile creare la regola personalizzata per il progetto.', + 'Your custom project role has been updated successfully.' => 'La regola personalizzata per il progetto è stata modificata correttamente.', + 'Unable to update custom project role.' => 'Impossibile modificare correttamente la regola personalizzata per il progetto.', + 'Custom project role removed successfully.' => 'Regola personalizzata per il progetto rimossa correttamente.', 'Unable to remove this project role.' => 'Impossibile rimuovere questa regola per il progetto.', 'The project restriction has been created successfully.' => 'La restrizione di progetto è stata creata con successo.', 'Unable to create this project restriction.' => 'Impossibile creare la restrizione di progetto.', @@ -1257,10 +1257,10 @@ return array( 'Task creation is not permitted' => 'Creazione task non permessa', 'Closing or opening a task is not permitted' => 'Chiudere o aprire task non è permesso', 'New drag and drop restriction for the role "%s"' => 'Nuova restrizione "drag and drop" per la regola "%s"', - 'People belonging to this role will be able to move tasks only between the source and the destination column.' => 'Gli utenti che appartengono a questa regola saranno in grado di muovere i task solo tra la colonna di origine e quella di destinazione', - 'Remove a column restriction' => 'Rimuovere restrizione colonna', + 'People belonging to this role will be able to move tasks only between the source and the destination column.' => 'Gli utenti che appartengono a questa regola saranno in grado di spostare i task solo tra la colonna di origine e quella di destinazione', + 'Remove a column restriction' => 'Rimuovere una restrizione di colonna', 'Do you really want to remove this column restriction: "%s" to "%s"?' => 'Vuoi davvero rimuovere questa restrizione di colonna: "%s" a "%s"?', - 'New column restriction for the role "%s"' => 'Nuova restrizione colonna per la regola "%s"', + 'New column restriction for the role "%s"' => 'Nuova restrizione di colonna per la regola "%s"', 'Rule' => 'Regola', 'Do you really want to remove this column restriction?' => 'Vuoi davvero rimuovere questa restrizione di colonna?', 'Custom roles' => 'Regole personalizzate', @@ -1273,9 +1273,18 @@ return array( 'Restriction' => 'Restrizione', 'Remove a project restriction' => 'Rimuovi restrizione di progetto', 'Do you really want to remove this project restriction: "%s"?' => 'Vuoi davvero rimuovere questa restrizione di progetto: "%s"?', - 'Duplicate to multiple projects' => 'Dupplica i più progetti', - 'This field is required' => 'Questo campo è richiesto', - 'Moving a task is not permitted' => 'Muovere task non è permesso', + 'Duplicate to multiple projects' => 'Duplica su più progetti', + 'This field is required' => 'Questo campo è obbligatorio', + 'Moving a task is not permitted' => 'Spostare task non è permesso', 'This value must be in the range %d to %d' => 'Questo valore deve essere compreso tra %d e %d', - 'You are not allowed to move this task.' => 'Non ti è permesso muovere questo task.', + 'You are not allowed to move this task.' => 'Non ti è permesso spostare questo task.', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index b9feed07..d0487fb7 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/ko_KR/translations.php b/app/Locale/ko_KR/translations.php index 5339111b..a613b467 100644 --- a/app/Locale/ko_KR/translations.php +++ b/app/Locale/ko_KR/translations.php @@ -402,9 +402,9 @@ return array( 'Refresh interval for private board' => '비공개 ë³´ë“œì˜ ê°±ì‹ ë¹ˆë„', 'Refresh interval for public board' => '공개 ë³´ë“œì˜ ê°±ì‹ ë¹ˆë„', 'Task highlight period' => 'í• ì¼ì˜ 하ì´ë¼ì´íŠ¸ 기간', - // 'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => '', - // 'Frequency in second (60 seconds by default)' => '', - // 'Frequency in second (0 to disable this feature, 10 seconds by default)' => '', + 'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => '최근 ìˆ˜ì •ëœ ìž‘ì—… ê³ ë ¤ 기간(ì´ˆ), (비활성화:0, 기본값:2ì¼)', + 'Frequency in second (60 seconds by default)' => '초당 횟수(기본값:60ì´ˆ)', + 'Frequency in second (0 to disable this feature, 10 seconds by default)' => '초당 횟수(비활성화:0, 기본값:10ì´ˆ)', 'Application URL' => 'ì• í”Œë¦¬ì¼€ì´ì…˜ì˜ URL', 'Token regenerated.' => 'í† í°ì´ 다시 ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤.', 'Date format' => 'ë°ì´í„° í¬ë©§', @@ -555,18 +555,18 @@ return array( 'No results match:' => '결과가 ì¼ì¹˜í•˜ì§€ 않았습니다', 'Currency' => '통화', 'Private project' => 'ê°œì¸ í”„ë¡œì 트', - // 'AUD - Australian Dollar' => '', - // 'CAD - Canadian Dollar' => '', - // 'CHF - Swiss Francs' => '', + 'AUD - Australian Dollar' => 'AUD - 호주 달러', + 'CAD - Canadian Dollar' => 'CAD -ìºë‚˜ë‹¤ 달러', + 'CHF - Swiss Francs' => 'CHF - 스위스 프랑', 'Custom Stylesheet' => '커스텀 ìŠ¤íƒ€ì¼ ì‹œíŠ¸', 'download' => '다운로드', - // 'EUR - Euro' => '', - // 'GBP - British Pound' => '', - // 'INR - Indian Rupee' => '', - // 'JPY - Japanese Yen' => '', - // 'NZD - New Zealand Dollar' => '', - // 'RSD - Serbian dinar' => '', - // 'USD - US Dollar' => '', + 'EUR - Euro' => 'EUR - ìœ ë¡œ', + 'GBP - British Pound' => 'GBP - ì˜êµ 파운드', + 'INR - Indian Rupee' => 'INR - ì¸ë„ 루피', + 'JPY - Japanese Yen' => 'JPY - ì¼ë³¸ ì—”', + 'NZD - New Zealand Dollar' => 'NZD - 뉴질랜드 달러', + 'RSD - Serbian dinar' => 'RSD - 세르비아 디나르', + 'USD - US Dollar' => 'USD - ë¯¸êµ ë‹¬ëŸ¬', 'Destination column' => 'ì´ë™ 후 컬럼', 'Move the task to another column when assigned to a user' => '사용ìžì˜ í• ë‹¹ì„ í•˜ë©´ í• ì¼ì„ 다른 ì»¬ëŸ¼ì— ì´ë™', 'Move the task to another column when assignee is cleared' => '사용ìžì˜ í• ë‹¹ì´ ì—†ì–´ì§€ë©´ í• ì¼ì„ 다른 ì»¬ëŸ¼ì— ì´ë™', @@ -600,12 +600,12 @@ return array( 'Assign a color when the task is moved to a specific column' => 'ìƒì„¸ 컬럼으로 ì´ë™í• í• ì¼ì˜ ìƒ‰ê¹”ì„ ì§€ì •í•˜ì„¸ìš”', '%s via Kanboard' => '%s via E-board', 'Burndown chart' => '번다운 차트', - // 'This chart show the task complexity over the time (Work Remaining).' => '', + 'This chart show the task complexity over the time (Work Remaining).' => 'ì´ ì°¨íŠ¸ëŠ” ì‹œê°„ì— ë”°ë¥¸ í• ì¼ì˜ ë³µìž¡ì„±ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. (남아있는 ì¼)', 'Screenshot taken %s' => '스í¬ë¦°ìƒ·_%s', 'Add a screenshot' => '스í¬ë¦°ìƒ· 추가', 'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => '스í¬ë¦°ìƒ·ì„ CTRL+V í˜¹ì€ âŒ˜+V를 눌러 붙여넣기', 'Screenshot uploaded successfully.' => '스í¬ë¦°ìƒ·ì„ 업로드하였습니다', - // 'SEK - Swedish Krona' => '', + 'SEK - Swedish Krona' => 'SEK - 스위스 í¬ë¡œë‚˜', 'Identifier' => 'ì‹ë³„ìž', 'Disable two factor authentication' => 'ì´ì¤‘ ì¸ì¦ 비활성화', 'Do you really want to disable the two factor authentication for this user: "%s"?' => '"%s" 담당ìžì˜ ì´ì¤‘ ì¸ì¦ì„ 비활성화 í•˜ì‹œê² ìŠµë‹ˆê¹Œ?', @@ -613,7 +613,7 @@ return array( 'Start to type task title...' => 'í• ì¼ ì œëª©ì„ ìž…ë ¥í•˜ì„¸ìš”', 'A task cannot be linked to itself' => 'í• ì¼ì„ ìžê¸°ìžì‹ ì—게 ì—°ê²°í• ìˆ˜ 없습니다', 'The exact same link already exists' => 'ë™ì¼í•œ ë§í¬ê°€ ì´ë¯¸ 존재합니다', - // 'Recurrent task is scheduled to be generated' => '', + 'Recurrent task is scheduled to be generated' => '반복 í• ì¼ì´ ìƒì„±ëœ ì˜ˆì •ìž…ë‹ˆë‹¤.', 'Score' => 'ì 수', 'The identifier must be unique' => 'ì‹ë³„ìžëŠ” ìœ ì¼í•´ì•¼ 합니다', 'This linked task id doesn\'t exists' => 'ì—°ê²°ëœ í• ì¼ IDê°€ 존재하지 않습니다', @@ -626,7 +626,7 @@ return array( 'Base date to calculate new due date' => '새로운 기본 ì¢…ë£Œë‚ ì§œ 계산', 'Action date' => 'ì‹œìž‘ë‚ ì§œ', 'Base date to calculate new due date: ' => '새로운 기본 ì¢…ë£Œë‚ ì§œ 계산: ', - // 'This task has created this child task: ' => '', + 'This task has created this child task: ' => 'ì´ í• ì¼ì€ 하위 í• ì¼ì„ 만들었습니다.', 'Day(s)' => 'ì¼', 'Existing due date' => '기존 ì¢…ë£Œë‚ ì§œ', 'Factor to calculate new due date: ' => '새로운 ì¢…ë£Œë‚ ì§œ 계산: ', @@ -635,7 +635,7 @@ return array( 'This task has been created by: ' => 'í• ì¼ì„ 만들었습니다: ', 'Recurrent task has been generated:' => '반복 í• ì¼ì´ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤', 'Timeframe to calculate new due date: ' => 'ì¢…ë£Œë‚ ì§œ 계산 단위', - // 'Trigger to generate recurrent task: ' => '', + 'Trigger to generate recurrent task: ' => '반복 í• ì¼ ìƒì„± 트리거', 'When task is closed' => 'í• ì¼ì„ 마쳤ì„ë•Œ', 'When task is moved from first column' => 'í• ì¼ì´ 첫번째 컬럼으로 옮겨졌ì„ë•Œ', 'When task is moved to last column' => 'í• ì¼ì´ 마지막 컬럼으로 옮겨졌ì„ë•Œ', @@ -649,7 +649,7 @@ return array( 'Subtasks time tracking' => '서브 í• ì¼ ì‹œê°„ 트래킹', 'User calendar view' => 'ë‹´ë‹¹ìž ë‹¬ë ¥ 보기', 'Automatically update the start date' => '시작ì¼ì— ìžë™ ê°±ì‹ ', - // 'iCal feed' => '', + 'iCal feed' => 'iCal 피드', 'Preferences' => 'ìš°ì„ ê¶Œ', 'Security' => '보안', 'Two factor authentication disabled' => 'ì´ì¤‘ ì¸ì¦ì´ 비활성화 ë˜ì—ˆìŠµë‹ˆë‹¤', @@ -666,7 +666,7 @@ return array( 'Notification' => '알림', '%s moved the task #%d to the first swimlane' => '%sê°€ í• ì¼ #%d를 첫번째 ìŠ¤ì›œë ˆì¸ìœ¼ë¡œ ì´ë™ì‹œì¼°ìŠµë‹ˆë‹¤', 'Swimlane' => 'ìŠ¤ìœ”ë ˆì¸', - // 'Gravatar' => '', + 'Gravatar' => 'Gravatar', '%s moved the task %s to the first swimlane' => '%sê°€ í• ì¼ %s를 첫번째 ìŠ¤ì›œë ˆì¸ìœ¼ë¡œ ì´ë™ì‹œì¼°ìŠµë‹ˆë‹¤', '%s moved the task %s to the swimlane "%s"' => '%sê°€ í• ì¼ %s를 %s ìŠ¤ì›œë ˆì¸ìœ¼ë¡œ ì´ë™ì‹œì¼°ìŠµë‹ˆë‹¤', 'This report contains all subtasks information for the given date range.' => '해당 ê¸°ê°„ì˜ ëª¨ë“ ì„œë¸Œ í• ì¼ ì •ë³´ê°€ ë³´ê³ ì„œì— í¬í•¨ë©ë‹ˆë‹¤', @@ -695,7 +695,7 @@ return array( 'Only for tasks assigned to me' => 'ë‚´ê°€ 담당ìžì¸ ì¼', 'Only for tasks created by me' => 'ë‚´ê°€ ë§Œë“ ì¼', 'Only for tasks created by me and assigned to me' => 'ë‚´ê°€ 만들었거나 ë‚´ê°€ 담당ìžì¸ ì¼', - // '%%Y-%%m-%%d' => '', + '%%Y-%%m-%%d' => '%%Y-%%m-%%d', 'Total for all columns' => 'ëª¨ë“ ì»¬ëŸ¼', 'You need at least 2 days of data to show the chart.' => '차트를 보기 위하여 최소 2ì¼ì˜ ë°ì´í„°ê°€ 필요합니다', '<15m' => '<15분', @@ -781,12 +781,12 @@ return array( 'Start date:' => '시작ì¼:', 'Due date:' => '만기ì¼:', 'There is no start date or due date for this task.' => 'í• ì¼ì˜ ì‹œìž‘ì¼ ë˜ëŠ” 만기ì¼ì´ 없습니다', - // 'Moving or resizing a task will change the start and due date of the task.' => '', - // 'There is no task in your project.' => '', + 'Moving or resizing a task will change the start and due date of the task.' => 'í• ì¼ì˜ ì´ë™ í˜¹ì€ ë¦¬ì‚¬ì´ì§•ìœ¼ë¡œ 시작시간과 마ê°ì‹œê°„ì´ ë³€ê²½ë©ë‹ˆë‹¤.', + 'There is no task in your project.' => '프로ì íŠ¸ì— í• ì¼ì´ 없습니다.', 'Gantt chart' => '간트 차트', 'People who are project managers' => '프로ì 트 ë§¤ë‹ˆì €', 'People who are project members' => '프로ì 트 멤버', - // 'NOK - Norwegian Krone' => '', + 'NOK - Norwegian Krone' => 'NOK - ë…¸ë¥´ì›¨ì´ í¬ë¡œë„¤', 'Show this column' => '컬럼 ë³´ì´ê¸°', 'Hide this column' => '컬럼 숨기기', 'open file' => '열기', @@ -802,14 +802,14 @@ return array( 'End date:' => 'ë‚ ì§œ ìˆ˜ì •', 'There is no start date or end date for this project.' => 'ì´ í”„ë¡œì 트ì—는 ì‹œìž‘ë‚ ì§œì™€ ì¢…ë£Œë‚ ì§œê°€ 없습니다', 'Projects Gantt chart' => '프로ì 트 간트차트', - // 'Change task color when using a specific task link' => '', - // 'Task link creation or modification' => '', + 'Change task color when using a specific task link' => 'íŠ¹ì • í• ì¼ ë§í¬ë¥¼ ì‚¬ìš©í• ë•Œ í• ì¼ì˜ 색깔 변경', + 'Task link creation or modification' => 'í• ì¼ ë§í¬ ìƒì„± í˜¹ì€ ìˆ˜ì •', 'Milestone' => '마ì¼ìŠ¤í†¤', 'Documentation: %s' => '문서: %s', 'Switch to the Gantt chart view' => '간트 차트 보기로 변경', - // 'Reset the search/filter box' => '', + 'Reset the search/filter box' => '찾기/í•„í„° 박스 초기화', 'Documentation' => '문서', - // 'Table of contents' => '', + 'Table of contents' => '목차', 'Gantt' => '간트', 'Author' => '글쓴ì´', 'Version' => 'ë²„ì „', @@ -825,7 +825,7 @@ return array( 'Your custom filter have been updated successfully.' => 'ì‚¬ìš©ìž ì •ì˜ í•„í„°ê°€ 성공ì 으로 ìˆ˜ì •ë˜ì—ˆìŠµë‹ˆë‹¤', 'Unable to update custom filter.' => 'ì •ì˜ í•„í„° ìˆ˜ì • 비활성화', 'Web' => '웹', - // 'New attachment on task #%d: %s' => '', + 'New attachment on task #%d: %s' => 'í• ì¼ #%dì˜ ìƒˆë¡œìš´ 첨부파ì¼: %s', 'New comment on task #%d' => 'í• ì¼ #%dì— ìƒˆë¡œìš´ ëŒ“ê¸€ì´ ë‹¬ë ¸ìŠµë‹ˆë‹¤', 'Comment updated on task #%d' => 'í• ì¼ #%dì— ëŒ“ê¸€ì´ ê°±ì‹ ë˜ì—ˆìŠµë‹ˆë‹¤', 'New subtask on task #%d' => '서브 í• ì¼ #%dì´ ê°±ì‹ ë˜ì—ˆìŠµë‹ˆë‹¤', @@ -843,7 +843,7 @@ return array( 'No new notifications.' => 'ì•Œë¦¼ì´ ì—†ìŠµë‹ˆë‹¤', 'Mark all as read' => 'ëª¨ë‘ ì½ìŒ', 'Mark as read' => 'ì½ìŒ', - // 'Total number of tasks in this column across all swimlanes' => '', + 'Total number of tasks in this column across all swimlanes' => 'ëª¨ë“ ìŠ¤ì›œë¼ì¸ ì¹¼ëŸ¼ì˜ í• ì¼ ìˆ˜', 'Collapse swimlane' => '스웜ë¼ì¸ 붕괴', 'Expand swimlane' => '스웜ë¼ì¸ 확장', 'Add a new filter' => '새로운 í•„í„° 추가', @@ -866,7 +866,7 @@ return array( 'Single Quote' => '따옴표', '%s attached a file to the task #%d' => '%sê°€ í• ì¼ #%dì— íŒŒì¼ì„ 추가하였습니다', 'There is no column or swimlane activated in your project!' => '프로ì íŠ¸ì— í™œì„±í™”ëœ ì»¬ëŸ¼ì´ë‚˜ 스웜ë¼ì¸ì´ 없습니다', - // 'Append filter (instead of replacement)' => '', + 'Append filter (instead of replacement)' => 'í•„í„° (변경 ëŒ€ì‹ )추가', 'Append/Replace' => '추가/변경', 'Append' => '추가', 'Replace' => '변경', @@ -890,7 +890,7 @@ return array( '%s attached a new file to the task %s' => '%sì´ ìƒˆë¡œìš´ 파ì¼ì„ í• ì¼ %sì— ì¶”ê°€í–ˆìŠµë‹ˆë‹¤', 'Link type' => 'ë§í¬ 형ì‹', 'Assign automatically a category based on a link' => 'ë§í¬ 기반 ìžë™ ì¹´í…Œê³ ë¦¬ í• ë‹¹', - // 'BAM - Konvertible Mark' => '', + 'BAM - Konvertible Mark' => 'BAM - 보스니아 마르카', 'Assignee Username' => '담당ìžì˜ 사용ìžì´ë¦„', 'Assignee Name' => 'ë‹¹ìž¥ìž ì´ë¦„', 'Groups' => '그룹', @@ -916,7 +916,7 @@ return array( 'Project Member' => '프로ì 트 멤버', 'Project Viewer' => '프로ì 트 ë·°ì–´', 'Your account is locked for %d minutes' => '%d분 ë™ì•ˆ ê³„ì •ì´ ìž ê¹ë‹ˆë‹¤', - // 'Invalid captcha' => '', + 'Invalid captcha' => 'ìž˜ëª»ëœ ë³´ì•ˆ 문ìž', 'The name must be unique' => 'ì´ë¦„ì€ ìœ ì¼í•´ì•¼ 합니다', 'View all groups' => 'ëª¨ë“ ê·¸ë£¹ë³´ê¸°', 'There is no user available.' => '가능한 사용ìžê°€ 없습니다', @@ -950,14 +950,14 @@ return array( 'Estimated Time' => 'ì˜ˆìƒ ì‹œê°„', 'Actual Time' => 'ì‹¤ì œ 시간', 'Estimated vs actual time' => 'ì˜ˆìƒ vs ì‹¤ì œ 시간', - // 'RUB - Russian Ruble' => '', + 'RUB - Russian Ruble' => 'RUB - 러시아 루블', 'Assign the task to the person who does the action when the column is changed' => 'ì»¬ëŸ¼ì´ ë³€ê²½ë˜ë©´ 액션하지 않는 사람ì—게 í• ì¼ì„ í• ë‹¹í•©ë‹ˆë‹¤', 'Close a task in a specific column' => 'ìƒì„¸ ì»¬ëŸ¼ì˜ í• ì¼ì„ 종료합니다', 'Time-based One-time Password Algorithm' => 'ì‹œê°„ì— ê¸°ë°˜í•œ 1회용 패스워드 ì•Œê³ ë¦¬ì¦˜', 'Two-Factor Provider: ' => 'ì´ì¤‘ ì¸ì¦: ', 'Disable two-factor authentication' => 'ì´ì¤‘ ì¸ì¦ 비활성화', 'Enable two-factor authentication' => 'ì´ì¤‘ ì¸ì¦ 활성화', - // 'There is no integration registered at the moment.' => '', + 'There is no integration registered at the moment.' => '현재 등ë¡ëœ í†µí•©ì´ ì—†ìŠµë‹ˆë‹¤.', 'Password Reset for Kanboard' => 'Kanboardì˜ ë¹„ë°€ë²ˆí˜¸ 초기화', 'Forgot password?' => '비밀번호 찾기', 'Enable "Forget Password"' => '"비밀번호 분실" 활성화', @@ -977,9 +977,9 @@ return array( 'No plugin has registered a project notification method. You can still configure individual notifications in your user profile.' => '프로ì 트 알림 방법으로 플러그ì¸ì´ 등ë¡ë˜ì§€ 않았습니다. ê°ê°ì˜ ì•Œë¦¼ì„ í”„ë¡œíŒŒì¼ì—ì„œ ì„¤ì •í•˜ì‹¤ 수 있습니다', 'My dashboard' => '대시보드', 'My profile' => '프로필', - 'Project owner: ' => '프로ì 트 ì†Œìœ ìž', + 'Project owner: ' => '프로ì 트 ì†Œìœ ìž:', 'The project identifier is optional and must be alphanumeric, example: MYPROJECT.' => '프로ì 트 구분ìžëŠ” ì„ íƒì‚¬í•ì´ë©°, 숫ìžì™€ 문ìžë§Œ 가능합니다. 예: MYPROJECT.', - // 'Project owner' => '', + 'Project owner' => '프로ì 트 ì†Œìœ ìž', 'Those dates are useful for the project Gantt chart.' => 'ì´ ë‚ ì§œëŠ” 프로ì 트 간트 ì°¨íŠ¸ì— ì‚¬ìš©ë©ë‹ˆë‹¤', 'Private projects do not have users and groups management.' => '비밀 프로ì 트는 사용ìžë‚˜ 관리 ê·¸ë£¹ì´ ì†Œìœ í•˜ì§€ 않습니다', 'There is no project member.' => '프로ì 트 맴버가 없습니다', @@ -995,7 +995,7 @@ return array( 'Duration in days' => '기간', 'Send email when there is no activity on a task' => '활ë™ì´ 없는 í• ì¼ì„ ì´ë©”ì¼ë¡œ 보냅니다', 'Unable to fetch link information.' => 'ë§í¬ ì •ë³´ ê°€ì ¸ì˜¤ê¸° 비활성화', - // 'Daily background job for tasks' => '', + 'Daily background job for tasks' => 'í• ì¼ì˜ ì¼ì¼ ë°°ê²½ ìž‘ì—… ', 'Auto' => 'ìžë™', 'Related' => 'ì—°ê´€ëœ', 'Attachment' => '첨부', @@ -1010,7 +1010,7 @@ return array( 'Edit external link' => '외부 ë§í¬ ìˆ˜ì •', 'External link' => '외부 ë§í¬', 'Copy and paste your link here...' => 'ì—¬ê¸°ì— ë§í¬ë¥¼ 복사/붙여넣기', - // 'URL' => '', + 'URL' => 'ì¸í„°ë„· 주소', 'Internal links' => '내부 ë§í¬', 'Assign to me' => '나ì—게 í• ë‹¹', 'Me' => '나', @@ -1047,9 +1047,9 @@ return array( 'Do you really want to remove this custom filter: "%s"?' => 'ì •ì˜ í•„í„°ë¥¼ ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ: "%s"?', 'Remove a custom filter' => 'ì •ì˜ í•„í„° ì‚ì œ', 'User activated successfully.' => '사용ìžê°€ 성공ì 으로 활성화ë˜ì—ˆìŠµë‹ˆë‹¤', - // 'Unable to enable this user.' => '', + 'Unable to enable this user.' => 'ì´ ì‚¬ìš©ìžë¥¼ í™œì„±í™”í• ìˆ˜ 없습니다.', 'User disabled successfully.' => '사용ìžê°€ 성공ì 으로 비활성화ë˜ì—ˆìŠµë‹ˆë‹¤', - // 'Unable to disable this user.' => '', + 'Unable to disable this user.' => 'ì´ ì‚¬ìš©ìžë¥¼ ë¹„í™œì„±í™”í• ìˆ˜ 없습니다.', 'All files have been uploaded successfully.' => 'ëª¨ë“ íŒŒì¼ì´ 성공ì 으로 업로드ë˜ì—ˆìŠµë‹ˆë‹¤', 'View uploaded files' => '업로드 íŒŒì¼ ë³´ê¸°', 'The maximum allowed file size is %sB.' => '업로드 파ì¼ì˜ 최대 í¬ê¸°ëŠ” %sB 입니다', @@ -1093,7 +1093,7 @@ return array( 'Local File' => '로컬 파ì¼', 'Configuration' => '구성', 'PHP version:' => 'PHP ë²„ì „:', - // 'PHP SAPI:' => '', + 'PHP SAPI:' => 'PHP SAPI:', 'OS version:' => 'ìš´ì˜ì²´ì œ ë²„ì „:', 'Database version:' => 'ë°ì´í„°ë² ì´ìŠ¤ ë²„ì „:', 'Browser:' => '브ë¼ìš°ì €:', @@ -1140,7 +1140,7 @@ return array( 'Unable to open plugin archive.' => 'í”ŒëŸ¬ê·¸ì¸ ì•„ì¹´ì´ë¸Œë¥¼ 열수 없습니다.', 'There is no file in the plugin archive.' => 'í”ŒëŸ¬ê·¸ì¸ ì•„ì¹´ì´ë¸Œì— 파ì¼ì´ 존재하지 않습니다.', 'Create tasks in bulk' => 'ëŒ€ëŸ‰ì˜ í• ì¼ ë§Œë“¤ê¸°', - // 'Your Kanboard instance is not configured to install plugins from the user interface.' => '', + 'Your Kanboard instance is not configured to install plugins from the user interface.' => '칸보드 ì¸ìŠ¤í„´ìŠ¤ê°€ ì‚¬ìš©ìž ì¸í„°íŽ˜ì´ìŠ¤ì—ì„œ 플러그ì¸ì„ 설치하ë„ë¡ êµ¬ì„±ë˜ì§€ 않았습니다', 'There is no plugin available.' => '사용 가능한 플러그ì¸ì´ 없습니다.', 'Install' => '설치', 'Update' => 'ê°±ì‹ ', @@ -1212,70 +1212,79 @@ return array( 'Notifications for %s' => '%sì˜ ì•Œë¦¼', 'Subtasks export' => 'ì„œë¸Œí• ì¼ ë‚´ë³´ë‚´ê¸°', 'Tasks exportation' => 'í• ì¼ ë‚´ë³´ë‚´ê¸°', - // 'Assign a color when the task is moved to a specific swimlane' => '', - // 'Assign a priority when the task is moved to a specific swimlane' => '', - // 'User unlocked successfully.' => '', - // 'Unable to unlock the user.' => '', - // 'Move a task to another swimlane' => '', - // 'Creator Name' => '', - // 'Time spent and estimated' => '', - // 'Move position' => '', - // 'Move task to another position on the board' => '', - // 'Insert before this task' => '', - // 'Insert after this task' => '', - // 'Unlock this user' => '', - // 'Custom Project Roles' => '', - // 'Add a new custom role' => '', - // 'Restrictions for the role "%s"' => '', - // 'Add a new project restriction' => '', - // 'Add a new drag and drop restriction' => '', - // 'Add a new column restriction' => '', - // 'Edit this role' => '', - // 'Remove this role' => '', - // 'There is no restriction for this role.' => '', - // 'Only moving task between those columns is permitted' => '', - // 'Close a task in a specific column when not moved during a given period' => '', - // 'Edit columns' => '', - // 'The column restriction has been created successfully.' => '', - // 'Unable to create this column restriction.' => '', - // 'Column restriction removed successfully.' => '', - // 'Unable to remove this restriction.' => '', - // 'Your custom project role has been created successfully.' => '', - // 'Unable to create custom project role.' => '', - // 'Your custom project role has been updated successfully.' => '', - // 'Unable to update custom project role.' => '', - // 'Custom project role removed successfully.' => '', - // 'Unable to remove this project role.' => '', - // 'The project restriction has been created successfully.' => '', - // 'Unable to create this project restriction.' => '', - // 'Project restriction removed successfully.' => '', - // 'You cannot create tasks in this column.' => '', - // 'Task creation is permitted for this column' => '', - // 'Closing or opening a task is permitted for this column' => '', - // 'Task creation is blocked for this column' => '', - // 'Closing or opening a task is blocked for this column' => '', - // 'Task creation is not permitted' => '', - // 'Closing or opening a task is not permitted' => '', - // 'New drag and drop restriction for the role "%s"' => '', - // 'People belonging to this role will be able to move tasks only between the source and the destination column.' => '', - // 'Remove a column restriction' => '', - // 'Do you really want to remove this column restriction: "%s" to "%s"?' => '', - // 'New column restriction for the role "%s"' => '', - // 'Rule' => '', - // 'Do you really want to remove this column restriction?' => '', - // 'Custom roles' => '', - // 'New custom project role' => '', - // 'Edit custom project role' => '', - // 'Remove a custom role' => '', - // 'Do you really want to remove this custom role: "%s"? All people assigned to this role will become project member.' => '', - // 'There is no custom role for this project.' => '', - // 'New project restriction for the role "%s"' => '', - // 'Restriction' => '', - // 'Remove a project restriction' => '', - // 'Do you really want to remove this project restriction: "%s"?' => '', - // 'Duplicate to multiple projects' => '', - // 'This field is required' => '', - // 'Moving a task is not permitted' => '', - // 'This value must be in the range %d to %d' => '', - // 'You are not allowed to move this task.' => '', + 'Assign a color when the task is moved to a specific swimlane' => 'í• ì¼ì´ íŠ¹ì • 스웜ë¼ì¸ìœ¼ë¡œ 옮겨질 ë•Œ ìƒ‰ìƒ ì§€ì •', + 'Assign a priority when the task is moved to a specific swimlane' => 'í• ì¼ì´ íŠ¹ì • 스웜ë¼ì¸ìœ¼ë¡œ 옮겨질 ë•Œ ìš°ì„ ìˆœìœ„ ì§€ì •', + 'User unlocked successfully.' => 'ì‚¬ìš©ìž ìž ê¸ˆ 성공', + 'Unable to unlock the user.' => 'ì‚¬ìš©ìž í•´ì œ 성공', + 'Move a task to another swimlane' => '다른 스웜ë¼ì¸ìœ¼ë¡œ í• ì¼ ì´ë™', + 'Creator Name' => 'ìƒì„±ìž ì´ë¦„', + 'Time spent and estimated' => '소요시간과 예ìƒì‹œê°„', + 'Move position' => 'ì´ë™ 위치', + 'Move task to another position on the board' => 'í• ì¼ì„ ë³´ë“œì˜ ë‹¤ë¥¸ 위치로 ì´ë™', + 'Insert before this task' => 'ì´ í• ì¼ ì´ì „ì— ì‚½ìž…', + 'Insert after this task' => 'ì´ í• ì¼ ì´í›„ì— ì‚½ìž…', + 'Unlock this user' => 'ì‚¬ìš©ìž ìž ê¸ˆ', + 'Custom Project Roles' => 'ì •ì˜ í”„ë¡œì 트 규칙', + 'Add a new custom role' => '새로운 ì •ì˜ ê·œì¹™ 추가', + 'Restrictions for the role "%s"' => '"%s" ì—í• ì˜ ì œì•½', + 'Add a new project restriction' => '새로운 프로ì 트 ì œì•½ 추가', + 'Add a new drag and drop restriction' => '새로운 드래그 앤 ë“œë¡ ì œì•½ 추가', + 'Add a new column restriction' => '새로운 칼럼 ì œì•½ 추가', + 'Edit this role' => 'ì—í• ìˆ˜ì •', + 'Remove this role' => 'ì—í• ì‚ì œ', + 'There is no restriction for this role.' => 'ì—í• ì— ëŒ€í•œ ì œì•½ì´ ì—†ìŠµë‹ˆë‹¤.', + 'Only moving task between those columns is permitted' => '칼럼간 ì´ë™ë§Œ 허용ë©ë‹ˆë‹¤.', + 'Close a task in a specific column when not moved during a given period' => 'íŠ¹ì • 기간ë™ì•ˆ ì´ë™í•˜ì§€ ì•Šì€ íŠ¹ì • ì¹¼ëŸ¼ì˜ í• ì¼ ë§ˆì¹˜ê¸°', + 'Edit columns' => '칼럼 ìˆ˜ì •', + 'The column restriction has been created successfully.' => '칼럼 ì œì•½ì´ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Unable to create this column restriction.' => '칼럼 ì œì•½ì„ ìƒì„±í• 수 없습니다.', + 'Column restriction removed successfully.' => '칼럼 ì œì•½ì´ ì‚ì œë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Unable to remove this restriction.' => '칼럼 ì œì•½ì„ ì‚ì œí• ìˆ˜ 없습니다.', + 'Your custom project role has been created successfully.' => 'ì •ì˜ í”„ë¡œì 트 ì—í• ì´ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Unable to create custom project role.' => 'ì •ì˜ í”„ë¡œì 트 ì—í• ì„ ìƒì„±í• 수 없습니다.', + 'Your custom project role has been updated successfully.' => 'ì •ì˜ í”„ë¡œì 트 ì—í• ì´ ìˆ˜ì •ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Unable to update custom project role.' => 'ì •ì˜ í”„ë¡œì 트 ì—í• ì„ ìˆ˜ì •í• ìˆ˜ 없습니다.', + 'Custom project role removed successfully.' => 'ì •ì˜ í”„ë¡œì 트 ì—í• ì´ ì‚ì œë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Unable to remove this project role.' => 'ì •ì˜ í”„ë¡œì 트 ì—í• ì„ ì‚ì œí• ìˆ˜ 없습니다.', + 'The project restriction has been created successfully.' => '프로ì 트 ì œì•½ì´ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Unable to create this project restriction.' => '프로ì 트 ì œì•½ì„ ìƒì„±í• 수 없습니다.', + 'Project restriction removed successfully.' => '프로ì 트 ì œì•½ì„ ì‚ì œí•˜ì˜€ìŠµë‹ˆë‹¤.', + 'You cannot create tasks in this column.' => 'ì´ ì¹¼ëŸ¼ì˜ í• ì¼ì„ ìƒì„±í• 수 없습니다.', + 'Task creation is permitted for this column' => 'ì´ ì¹¼ëŸ¼ì˜ í• ì¼ ìƒì„±ì´ 허가ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Closing or opening a task is permitted for this column' => 'ì´ ì¹¼ëŸ¼ì˜ í• ì¼ ì—´ê¸° í˜¹ì€ ë‹«ê¸°ê°€ 허가ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Task creation is blocked for this column' => 'ì´ ì¹¼ëŸ¼ì˜ í• ì¼ ìƒì„±ì´ 거부ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Closing or opening a task is blocked for this column' => 'ì´ ì¹¼ëŸ¼ì˜ í• ì¼ ì—´ê¸° í˜¹ì€ ë‹«ê¸°ê°€ 거부ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Task creation is not permitted' => 'í• ì¼ ìƒì„±ì´ 거부ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'Closing or opening a task is not permitted' => 'í• ì¼ ì—´ê¸° í˜¹ì€ ë‹«ê¸°ê°€ 거부ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'New drag and drop restriction for the role "%s"' => '"%s" ì—í• ì˜ ìƒˆë¡œìš´ 드래그 앤 ë“œë¡ ì œì•½', + 'People belonging to this role will be able to move tasks only between the source and the destination column.' => 'ì´ ì—í• ì— ì†í•œ 사용ìžëŠ” ì›ë³¸ ë° ëŒ€ìƒ ì¹¼ëŸ¼ 사ì´ì—서만 í• ì¼ì„ ì´ë™í• 수 있습니다', + 'Remove a column restriction' => '칼럼 ì œì•½ ì‚ì œ', + 'Do you really want to remove this column restriction: "%s" to "%s"?' => '칼럼 ì œì•½ì„ "%s" ì—ì„œ "%s"ë¡œ ì´ë™í•˜ì‹œê² 습니까?', + 'New column restriction for the role "%s"' => '"%s" ì—í• ì˜ ìƒˆë¡œìš´ 칼럼 ì œì•½', + 'Rule' => 'ì—í• ', + 'Do you really want to remove this column restriction?' => '칼럼 ì œì•½ì„ ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?', + 'Custom roles' => 'ì •ì˜ ì—í• ', + 'New custom project role' => '새로운 ì •ì˜ í”„ë¡œì 트 ì—í• ', + 'Edit custom project role' => 'ì •ì˜ í”„ë¡œì 트 ì—í• ìˆ˜ì •', + 'Remove a custom role' => 'ì •ì˜ ì—í• ì‚ì œ', + 'Do you really want to remove this custom role: "%s"? All people assigned to this role will become project member.' => '"%s" ì •ì˜ ì—í• ì„ ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ? ì´ ì—í• ì— í• ë‹¹ ëœ ëª¨ë“ ì‚¬ëžŒë“¤ì´ í”„ë¡œì 트 멤버가ë©ë‹ˆë‹¤.', + 'There is no custom role for this project.' => 'ì´ í”„ë¡œì 트ì—는 ì •ì˜ ì—í• ì´ ì—†ìŠµë‹ˆë‹¤.', + 'New project restriction for the role "%s"' => '"%s" ì—í• ì˜ ìƒˆë¡œìš´ 프로ì 트 ì œì•½', + 'Restriction' => 'ì œì•½', + 'Remove a project restriction' => '프로ì 트 ì œì•½ ì‚ì œ', + 'Do you really want to remove this project restriction: "%s"?' => '"%s" 프로ì 트 ì œì•½ì„ ì‚ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?', + 'Duplicate to multiple projects' => 'ë‹¤ìˆ˜ì˜ í”„ë¡œì 트 ë³µì œ', + 'This field is required' => 'ì´ í•„ë“œëŠ” 필수 í•ëª©ìž…니다.', + 'Moving a task is not permitted' => 'í• ì¼ ì´ë™ì´ 거부ë˜ì—ˆìŠµë‹ˆë‹¤.', + 'This value must be in the range %d to %d' => 'ê°’ì˜ ë²”ìœ„ëŠ” %d 부터 %d 까지 입니다.', + 'You are not allowed to move this task.' => 'ë‹¹ì‹ ì€ í• ì¼ ì´ë™ì´ 거부ë˜ì—ˆìŠµë‹ˆë‹¤.', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/my_MY/translations.php b/app/Locale/my_MY/translations.php index 048d8b4b..be335dec 100644 --- a/app/Locale/my_MY/translations.php +++ b/app/Locale/my_MY/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php index 0d2a340d..6b49545c 100644 --- a/app/Locale/nb_NO/translations.php +++ b/app/Locale/nb_NO/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index e1745c14..44434a4e 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index 164abe0c..51c0fef8 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index 637de30e..c0fa2387 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Mover uma tarefa não é permitido', 'This value must be in the range %d to %d' => 'Este valor precisa estar no intervalo %d até %d', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php index 3b8975d9..47763d30 100644 --- a/app/Locale/pt_PT/translations.php +++ b/app/Locale/pt_PT/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Não é permitido mover uma tarefa', 'This value must be in the range %d to %d' => 'Este valor deve estar entre %d e %d', 'You are not allowed to move this task.' => 'Não lhe é permitido mover esta tarefa.', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index 1e5c02c2..4d821f6a 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Перемещение задачи не разрешено', 'This value must be in the range %d to %d' => 'Значение должно находитьÑÑ Ð² диапазоне от %d до %d', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index 2f061260..470e3390 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index f32728e7..2ec4fa82 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index 4025714a..5e0912fc 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index 24399891..1a648bbf 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Görev taşımaya izin verilmemiÅŸ', 'This value must be in the range %d to %d' => 'Bu deÄŸer ÅŸu aralıkta olmalı: "%d" "%d"', 'You are not allowed to move this task.' => 'Bu görevi taşımaya izniniz yok.', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index e27a8a56..c87adbec 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'ç¦æ¢ç§»åŠ¨ä»»åŠ¡', 'This value must be in the range %d to %d' => '输入值必须在%d到%d之间', 'You are not allowed to move this task.' => 'ä½ ä¸èƒ½ç§»åŠ¨æ¤ä»»åŠ¡', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Model/ProjectPermissionModel.php b/app/Model/ProjectPermissionModel.php index 25b6a382..dabd406c 100644 --- a/app/Model/ProjectPermissionModel.php +++ b/app/Model/ProjectPermissionModel.php @@ -62,17 +62,33 @@ class ProjectPermissionModel extends Base ->withFilter(new ProjectUserRoleProjectFilter($project_id)) ->withFilter(new ProjectUserRoleUsernameFilter($input)) ->getQuery() - ->findAllByColumn('username'); + ->columns( + UserModel::TABLE.'.id', + UserModel::TABLE.'.username', + UserModel::TABLE.'.name', + UserModel::TABLE.'.email', + UserModel::TABLE.'.avatar_path' + ) + ->findAll(); $groupMembers = $this->projectGroupRoleQuery ->withFilter(new ProjectGroupRoleProjectFilter($project_id)) ->withFilter(new ProjectGroupRoleUsernameFilter($input)) ->getQuery() - ->findAllByColumn('username'); + ->columns( + UserModel::TABLE.'.id', + UserModel::TABLE.'.username', + UserModel::TABLE.'.name', + UserModel::TABLE.'.email', + UserModel::TABLE.'.avatar_path' + ) + ->findAll(); - $members = array_unique(array_merge($userMembers, $groupMembers)); + $userMembers = array_column_index_unique($userMembers, 'username'); + $groupMembers = array_column_index_unique($groupMembers, 'username'); + $members = array_merge($userMembers, $groupMembers); - sort($members); + ksort($members); return $members; } diff --git a/app/Model/UserMentionModel.php b/app/Model/UserMentionModel.php deleted file mode 100644 index cdb9949e..00000000 --- a/app/Model/UserMentionModel.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php - -namespace Kanboard\Model; - -use Kanboard\Core\Base; -use Kanboard\Event\GenericEvent; - -/** - * User Mention - * - * @package Kanboard\Model - * @author Frederic Guillot - */ -class UserMentionModel extends Base -{ - /** - * Get list of mentioned users - * - * @access public - * @param string $content - * @return array - */ - public function getMentionedUsers($content) - { - $users = array(); - - if (preg_match_all('/@([^\s]+)/', $content, $matches)) { - $users = $this->db->table(UserModel::TABLE) - ->columns('id', 'username', 'name', 'email', 'language') - ->eq('notifications_enabled', 1) - ->neq('id', $this->userSession->getId()) - ->in('username', array_unique($matches[1])) - ->findAll(); - } - - return $users; - } - - /** - * Fire events for user mentions - * - * @access public - * @param string $content - * @param string $eventName - * @param GenericEvent $event - */ - public function fireEvents($content, $eventName, GenericEvent $event) - { - if (empty($event['project_id'])) { - $event['project_id'] = $this->taskFinderModel->getProjectId($event['task_id']); - } - - $users = $this->getMentionedUsers($content); - - foreach ($users as $user) { - if ($this->projectPermissionModel->isMember($event['project_id'], $user['id'])) { - $event['mention'] = $user; - $this->dispatcher->dispatch($eventName, $event); - } - } - } -} diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index b50164ca..fac8688a 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -6,7 +6,17 @@ use PDO; use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; -const VERSION = 116; +const VERSION = 118; + +function version_118(PDO $pdo) +{ + $pdo->exec('ALTER TABLE `users` ADD COLUMN `api_access_token` VARCHAR(255) DEFAULT NULL'); +} + +function version_117(PDO $pdo) +{ + $pdo->exec("ALTER TABLE `settings` MODIFY `value` TEXT"); +} function version_116(PDO $pdo) { diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index 83926f19..32a7a744 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -6,7 +6,17 @@ use PDO; use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; -const VERSION = 95; +const VERSION = 97; + +function version_97(PDO $pdo) +{ + $pdo->exec('ALTER TABLE "users" ADD COLUMN api_access_token VARCHAR(255) DEFAULT NULL'); +} + +function version_96(PDO $pdo) +{ + $pdo->exec('ALTER TABLE "settings" ALTER COLUMN "value" TYPE TEXT'); +} function version_95(PDO $pdo) { diff --git a/app/Schema/Sql/mysql.sql b/app/Schema/Sql/mysql.sql index 8d494dcf..0ee88d88 100644 --- a/app/Schema/Sql/mysql.sql +++ b/app/Schema/Sql/mysql.sql @@ -35,6 +35,44 @@ CREATE TABLE `actions` ( CONSTRAINT `actions_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `column_has_move_restrictions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `column_has_move_restrictions` ( + `restriction_id` int(11) NOT NULL AUTO_INCREMENT, + `project_id` int(11) NOT NULL, + `role_id` int(11) NOT NULL, + `src_column_id` int(11) NOT NULL, + `dst_column_id` int(11) NOT NULL, + PRIMARY KEY (`restriction_id`), + UNIQUE KEY `role_id` (`role_id`,`src_column_id`,`dst_column_id`), + KEY `project_id` (`project_id`), + KEY `src_column_id` (`src_column_id`), + KEY `dst_column_id` (`dst_column_id`), + CONSTRAINT `column_has_move_restrictions_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE, + CONSTRAINT `column_has_move_restrictions_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `project_has_roles` (`role_id`) ON DELETE CASCADE, + CONSTRAINT `column_has_move_restrictions_ibfk_3` FOREIGN KEY (`src_column_id`) REFERENCES `columns` (`id`) ON DELETE CASCADE, + CONSTRAINT `column_has_move_restrictions_ibfk_4` FOREIGN KEY (`dst_column_id`) REFERENCES `columns` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `column_has_restrictions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `column_has_restrictions` ( + `restriction_id` int(11) NOT NULL AUTO_INCREMENT, + `project_id` int(11) NOT NULL, + `role_id` int(11) NOT NULL, + `column_id` int(11) NOT NULL, + `rule` varchar(255) NOT NULL, + PRIMARY KEY (`restriction_id`), + UNIQUE KEY `role_id` (`role_id`,`column_id`,`rule`), + KEY `project_id` (`project_id`), + KEY `column_id` (`column_id`), + CONSTRAINT `column_has_restrictions_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE, + CONSTRAINT `column_has_restrictions_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `project_has_roles` (`role_id`) ON DELETE CASCADE, + CONSTRAINT `column_has_restrictions_ibfk_3` FOREIGN KEY (`column_id`) REFERENCES `columns` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `columns`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -260,7 +298,7 @@ DROP TABLE IF EXISTS `project_has_groups`; CREATE TABLE `project_has_groups` ( `group_id` int(11) NOT NULL, `project_id` int(11) NOT NULL, - `role` varchar(25) NOT NULL, + `role` varchar(255) NOT NULL, UNIQUE KEY `group_id` (`group_id`,`project_id`), KEY `project_id` (`project_id`), CONSTRAINT `project_has_groups_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE, @@ -292,19 +330,46 @@ CREATE TABLE `project_has_notification_types` ( CONSTRAINT `project_has_notification_types_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `project_has_roles`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `project_has_roles` ( + `role_id` int(11) NOT NULL AUTO_INCREMENT, + `role` varchar(255) NOT NULL, + `project_id` int(11) NOT NULL, + PRIMARY KEY (`role_id`), + UNIQUE KEY `project_id` (`project_id`,`role`), + CONSTRAINT `project_has_roles_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `project_has_users`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `project_has_users` ( `project_id` int(11) NOT NULL, `user_id` int(11) NOT NULL, - `role` varchar(25) NOT NULL DEFAULT 'project-viewer', + `role` varchar(255) NOT NULL, UNIQUE KEY `idx_project_user` (`project_id`,`user_id`), KEY `user_id` (`user_id`), CONSTRAINT `project_has_users_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE, CONSTRAINT `project_has_users_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `project_role_has_restrictions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `project_role_has_restrictions` ( + `restriction_id` int(11) NOT NULL AUTO_INCREMENT, + `project_id` int(11) NOT NULL, + `role_id` int(11) NOT NULL, + `rule` varchar(255) NOT NULL, + PRIMARY KEY (`restriction_id`), + UNIQUE KEY `role_id` (`role_id`,`rule`), + KEY `project_id` (`project_id`), + CONSTRAINT `project_role_has_restrictions_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE, + CONSTRAINT `project_role_has_restrictions_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `project_has_roles` (`role_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `projects`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; @@ -359,7 +424,7 @@ DROP TABLE IF EXISTS `settings`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `settings` ( `option` varchar(100) NOT NULL, - `value` varchar(255) DEFAULT '', + `value` text, `changed_by` int(11) NOT NULL DEFAULT '0', `changed_on` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`option`) @@ -537,6 +602,8 @@ CREATE TABLE `tasks` ( `recurrence_parent` int(11) DEFAULT NULL, `recurrence_child` int(11) DEFAULT NULL, `priority` int(11) DEFAULT '0', + `external_provider` varchar(255) DEFAULT NULL, + `external_uri` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_task_active` (`is_active`), KEY `column_id` (`column_id`), @@ -648,6 +715,7 @@ CREATE TABLE `users` ( `role` varchar(25) NOT NULL DEFAULT 'app-user', `is_active` tinyint(1) DEFAULT '1', `avatar_path` varchar(255) DEFAULT NULL, + `api_access_token` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `users_username_idx` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -671,7 +739,7 @@ CREATE TABLE `users` ( LOCK TABLES `settings` WRITE; /*!40000 ALTER TABLE `settings` DISABLE KEYS */; -INSERT INTO `settings` VALUES ('api_token','4064ef3d26efa9a0ff78fa7067d8bb9d99323455128edd89e9dc7c53ed76',0,0),('application_currency','USD',0,0),('application_date_format','m/d/Y',0,0),('application_language','en_US',0,0),('application_stylesheet','',0,0),('application_timezone','UTC',0,0),('application_url','',0,0),('board_columns','',0,0),('board_highlight_period','172800',0,0),('board_private_refresh_interval','10',0,0),('board_public_refresh_interval','60',0,0),('calendar_project_tasks','date_started',0,0),('calendar_user_subtasks_time_tracking','0',0,0),('calendar_user_tasks','date_started',0,0),('cfd_include_closed_tasks','1',0,0),('default_color','yellow',0,0),('integration_gravatar','0',0,0),('password_reset','1',0,0),('project_categories','',0,0),('subtask_restriction','0',0,0),('subtask_time_tracking','1',0,0),('webhook_token','c8f53c0bcd8aead902ad04f180ffafd7889b9c0062c2d510e2297ef543b8',0,0),('webhook_url','',0,0); +INSERT INTO `settings` VALUES ('api_token','f149956cb60c88d01123a28964fc035b1ce4513be454f2a85fe6b4ca3758',0,0),('application_currency','USD',0,0),('application_date_format','m/d/Y',0,0),('application_language','en_US',0,0),('application_stylesheet','',0,0),('application_timezone','UTC',0,0),('application_url','',0,0),('board_columns','',0,0),('board_highlight_period','172800',0,0),('board_private_refresh_interval','10',0,0),('board_public_refresh_interval','60',0,0),('calendar_project_tasks','date_started',0,0),('calendar_user_subtasks_time_tracking','0',0,0),('calendar_user_tasks','date_started',0,0),('cfd_include_closed_tasks','1',0,0),('default_color','yellow',0,0),('integration_gravatar','0',0,0),('password_reset','1',0,0),('project_categories','',0,0),('subtask_restriction','0',0,0),('subtask_time_tracking','1',0,0),('webhook_token','47d1d896b6612234c7543eb3f3a09a0a669f77a079d13ad3d810ccb79896',0,0),('webhook_url','',0,0); /*!40000 ALTER TABLE `settings` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -700,4 +768,4 @@ UNLOCK TABLES; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -INSERT INTO users (username, password, role) VALUES ('admin', '$2y$10$yUJ9QnhG.f47yO.YvWKo3eMAHULukpluDNTOF9.Z7QQg0vOfFRB6u', 'app-admin');INSERT INTO schema_version VALUES ('112'); +INSERT INTO users (username, password, role) VALUES ('admin', '$2y$10$R1zYk04d96KcHRpd9.r5I.5I6mgKIgUdsaISZYmaDLPIJCUO0FFJG', 'app-admin');INSERT INTO schema_version VALUES ('118'); diff --git a/app/Schema/Sql/postgres.sql b/app/Schema/Sql/postgres.sql index 0add9c91..578b0c75 100644 --- a/app/Schema/Sql/postgres.sql +++ b/app/Schema/Sql/postgres.sql @@ -2,8 +2,8 @@ -- PostgreSQL database dump -- --- Dumped from database version 9.5.2 --- Dumped by pg_dump version 9.5.2 +-- Dumped from database version 9.6.1 +-- Dumped by pg_dump version 9.6.1 SET statement_timeout = 0; SET lock_timeout = 0; @@ -89,6 +89,70 @@ ALTER SEQUENCE "actions_id_seq" OWNED BY "actions"."id"; -- +-- Name: column_has_move_restrictions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE "column_has_move_restrictions" ( + "restriction_id" integer NOT NULL, + "project_id" integer NOT NULL, + "role_id" integer NOT NULL, + "src_column_id" integer NOT NULL, + "dst_column_id" integer NOT NULL +); + + +-- +-- Name: column_has_move_restrictions_restriction_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE "column_has_move_restrictions_restriction_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: column_has_move_restrictions_restriction_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE "column_has_move_restrictions_restriction_id_seq" OWNED BY "column_has_move_restrictions"."restriction_id"; + + +-- +-- Name: column_has_restrictions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE "column_has_restrictions" ( + "restriction_id" integer NOT NULL, + "project_id" integer NOT NULL, + "role_id" integer NOT NULL, + "column_id" integer NOT NULL, + "rule" character varying(255) NOT NULL +); + + +-- +-- Name: column_has_restrictions_restriction_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE "column_has_restrictions_restriction_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: column_has_restrictions_restriction_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE "column_has_restrictions_restriction_id_seq" OWNED BY "column_has_restrictions"."restriction_id"; + + +-- -- Name: columns; Type: TABLE; Schema: public; Owner: - -- @@ -499,7 +563,7 @@ ALTER SEQUENCE "project_has_files_id_seq" OWNED BY "project_has_files"."id"; CREATE TABLE "project_has_groups" ( "group_id" integer NOT NULL, "project_id" integer NOT NULL, - "role" character varying(25) NOT NULL + "role" character varying(255) NOT NULL ); @@ -547,17 +611,78 @@ ALTER SEQUENCE "project_has_notification_types_id_seq" OWNED BY "project_has_not -- +-- Name: project_has_roles; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE "project_has_roles" ( + "role_id" integer NOT NULL, + "role" character varying(255) NOT NULL, + "project_id" integer NOT NULL +); + + +-- +-- Name: project_has_roles_role_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE "project_has_roles_role_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: project_has_roles_role_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE "project_has_roles_role_id_seq" OWNED BY "project_has_roles"."role_id"; + + +-- -- Name: project_has_users; Type: TABLE; Schema: public; Owner: - -- CREATE TABLE "project_has_users" ( "project_id" integer NOT NULL, "user_id" integer NOT NULL, - "role" character varying(25) DEFAULT 'project-viewer'::character varying NOT NULL + "role" character varying(255) DEFAULT 'project-viewer'::character varying NOT NULL +); + + +-- +-- Name: project_role_has_restrictions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE "project_role_has_restrictions" ( + "restriction_id" integer NOT NULL, + "project_id" integer NOT NULL, + "role_id" integer NOT NULL, + "rule" character varying(255) NOT NULL ); -- +-- Name: project_role_has_restrictions_restriction_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE "project_role_has_restrictions_restriction_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: project_role_has_restrictions_restriction_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE "project_role_has_restrictions_restriction_id_seq" OWNED BY "project_role_has_restrictions"."restriction_id"; + + +-- -- Name: projects; Type: TABLE; Schema: public; Owner: - -- @@ -652,7 +777,7 @@ CREATE TABLE "schema_version" ( CREATE TABLE "settings" ( "option" character varying(100) NOT NULL, - "value" character varying(255) DEFAULT ''::character varying, + "value" "text" DEFAULT ''::character varying, "changed_by" integer DEFAULT 0 NOT NULL, "changed_on" integer DEFAULT 0 NOT NULL ); @@ -948,7 +1073,9 @@ CREATE TABLE "tasks" ( "recurrence_basedate" integer DEFAULT 0 NOT NULL, "recurrence_parent" integer, "recurrence_child" integer, - "priority" integer DEFAULT 0 + "priority" integer DEFAULT 0, + "external_provider" character varying(255), + "external_uri" character varying(255) ); @@ -1117,7 +1244,8 @@ CREATE TABLE "users" ( "gitlab_id" integer, "role" character varying(25) DEFAULT 'app-user'::character varying NOT NULL, "is_active" boolean DEFAULT true, - "avatar_path" character varying(255) + "avatar_path" character varying(255), + "api_access_token" character varying(255) DEFAULT NULL::character varying ); @@ -1141,203 +1269,231 @@ ALTER SEQUENCE "users_id_seq" OWNED BY "users"."id"; -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: action_has_params id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "action_has_params" ALTER COLUMN "id" SET DEFAULT "nextval"('"action_has_params_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: actions id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "actions" ALTER COLUMN "id" SET DEFAULT "nextval"('"actions_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: column_has_move_restrictions restriction_id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_move_restrictions" ALTER COLUMN "restriction_id" SET DEFAULT "nextval"('"column_has_move_restrictions_restriction_id_seq"'::"regclass"); + + +-- +-- Name: column_has_restrictions restriction_id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_restrictions" ALTER COLUMN "restriction_id" SET DEFAULT "nextval"('"column_has_restrictions_restriction_id_seq"'::"regclass"); + + +-- +-- Name: columns id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "columns" ALTER COLUMN "id" SET DEFAULT "nextval"('"columns_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: comments id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "comments" ALTER COLUMN "id" SET DEFAULT "nextval"('"comments_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: custom_filters id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "custom_filters" ALTER COLUMN "id" SET DEFAULT "nextval"('"custom_filters_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: groups id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "groups" ALTER COLUMN "id" SET DEFAULT "nextval"('"groups_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: last_logins id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "last_logins" ALTER COLUMN "id" SET DEFAULT "nextval"('"last_logins_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: links id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "links" ALTER COLUMN "id" SET DEFAULT "nextval"('"links_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: project_activities id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_activities" ALTER COLUMN "id" SET DEFAULT "nextval"('"project_activities_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: project_daily_column_stats id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_daily_column_stats" ALTER COLUMN "id" SET DEFAULT "nextval"('"project_daily_summaries_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: project_daily_stats id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_daily_stats" ALTER COLUMN "id" SET DEFAULT "nextval"('"project_daily_stats_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: project_has_categories id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_categories" ALTER COLUMN "id" SET DEFAULT "nextval"('"project_has_categories_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: project_has_files id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_files" ALTER COLUMN "id" SET DEFAULT "nextval"('"project_has_files_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: project_has_notification_types id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_notification_types" ALTER COLUMN "id" SET DEFAULT "nextval"('"project_has_notification_types_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: project_has_roles role_id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "project_has_roles" ALTER COLUMN "role_id" SET DEFAULT "nextval"('"project_has_roles_role_id_seq"'::"regclass"); + + +-- +-- Name: project_role_has_restrictions restriction_id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "project_role_has_restrictions" ALTER COLUMN "restriction_id" SET DEFAULT "nextval"('"project_role_has_restrictions_restriction_id_seq"'::"regclass"); + + +-- +-- Name: projects id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "projects" ALTER COLUMN "id" SET DEFAULT "nextval"('"projects_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: remember_me id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "remember_me" ALTER COLUMN "id" SET DEFAULT "nextval"('"remember_me_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: subtask_time_tracking id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "subtask_time_tracking" ALTER COLUMN "id" SET DEFAULT "nextval"('"subtask_time_tracking_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: subtasks id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "subtasks" ALTER COLUMN "id" SET DEFAULT "nextval"('"task_has_subtasks_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: swimlanes id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "swimlanes" ALTER COLUMN "id" SET DEFAULT "nextval"('"swimlanes_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: tags id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "tags" ALTER COLUMN "id" SET DEFAULT "nextval"('"tags_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: task_has_external_links id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_external_links" ALTER COLUMN "id" SET DEFAULT "nextval"('"task_has_external_links_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: task_has_files id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_files" ALTER COLUMN "id" SET DEFAULT "nextval"('"task_has_files_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: task_has_links id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_links" ALTER COLUMN "id" SET DEFAULT "nextval"('"task_has_links_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: tasks id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "tasks" ALTER COLUMN "id" SET DEFAULT "nextval"('"tasks_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: transitions id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "transitions" ALTER COLUMN "id" SET DEFAULT "nextval"('"transitions_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: user_has_notification_types id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_notification_types" ALTER COLUMN "id" SET DEFAULT "nextval"('"user_has_notification_types_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: user_has_unread_notifications id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_unread_notifications" ALTER COLUMN "id" SET DEFAULT "nextval"('"user_has_unread_notifications_id_seq"'::"regclass"); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: users id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY "users" ALTER COLUMN "id" SET DEFAULT "nextval"('"users_id_seq"'::"regclass"); -- --- Name: action_has_params_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: action_has_params action_has_params_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "action_has_params" @@ -1345,7 +1501,7 @@ ALTER TABLE ONLY "action_has_params" -- --- Name: actions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: actions actions_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "actions" @@ -1353,7 +1509,39 @@ ALTER TABLE ONLY "actions" -- --- Name: columns_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: column_has_move_restrictions column_has_move_restrictions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_move_restrictions" + ADD CONSTRAINT "column_has_move_restrictions_pkey" PRIMARY KEY ("restriction_id"); + + +-- +-- Name: column_has_move_restrictions column_has_move_restrictions_role_id_src_column_id_dst_colu_key; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_move_restrictions" + ADD CONSTRAINT "column_has_move_restrictions_role_id_src_column_id_dst_colu_key" UNIQUE ("role_id", "src_column_id", "dst_column_id"); + + +-- +-- Name: column_has_restrictions column_has_restrictions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_restrictions" + ADD CONSTRAINT "column_has_restrictions_pkey" PRIMARY KEY ("restriction_id"); + + +-- +-- Name: column_has_restrictions column_has_restrictions_role_id_column_id_rule_key; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_restrictions" + ADD CONSTRAINT "column_has_restrictions_role_id_column_id_rule_key" UNIQUE ("role_id", "column_id", "rule"); + + +-- +-- Name: columns columns_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "columns" @@ -1361,7 +1549,7 @@ ALTER TABLE ONLY "columns" -- --- Name: columns_title_project_id_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: columns columns_title_project_id_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "columns" @@ -1369,7 +1557,7 @@ ALTER TABLE ONLY "columns" -- --- Name: comments_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: comments comments_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "comments" @@ -1377,7 +1565,7 @@ ALTER TABLE ONLY "comments" -- --- Name: currencies_currency_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: currencies currencies_currency_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "currencies" @@ -1385,7 +1573,7 @@ ALTER TABLE ONLY "currencies" -- --- Name: custom_filters_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: custom_filters custom_filters_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "custom_filters" @@ -1393,7 +1581,7 @@ ALTER TABLE ONLY "custom_filters" -- --- Name: group_has_users_group_id_user_id_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: group_has_users group_has_users_group_id_user_id_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "group_has_users" @@ -1401,7 +1589,7 @@ ALTER TABLE ONLY "group_has_users" -- --- Name: groups_name_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: groups groups_name_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "groups" @@ -1409,7 +1597,7 @@ ALTER TABLE ONLY "groups" -- --- Name: groups_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: groups groups_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "groups" @@ -1417,7 +1605,7 @@ ALTER TABLE ONLY "groups" -- --- Name: last_logins_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: last_logins last_logins_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "last_logins" @@ -1425,7 +1613,7 @@ ALTER TABLE ONLY "last_logins" -- --- Name: links_label_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: links links_label_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "links" @@ -1433,7 +1621,7 @@ ALTER TABLE ONLY "links" -- --- Name: links_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: links links_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "links" @@ -1441,7 +1629,7 @@ ALTER TABLE ONLY "links" -- --- Name: password_reset_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: password_reset password_reset_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "password_reset" @@ -1449,7 +1637,7 @@ ALTER TABLE ONLY "password_reset" -- --- Name: plugin_schema_versions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: plugin_schema_versions plugin_schema_versions_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "plugin_schema_versions" @@ -1457,7 +1645,7 @@ ALTER TABLE ONLY "plugin_schema_versions" -- --- Name: project_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_activities project_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_activities" @@ -1465,7 +1653,7 @@ ALTER TABLE ONLY "project_activities" -- --- Name: project_daily_stats_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_daily_stats project_daily_stats_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_daily_stats" @@ -1473,7 +1661,7 @@ ALTER TABLE ONLY "project_daily_stats" -- --- Name: project_daily_summaries_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_daily_column_stats project_daily_summaries_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_daily_column_stats" @@ -1481,7 +1669,7 @@ ALTER TABLE ONLY "project_daily_column_stats" -- --- Name: project_has_categories_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_categories project_has_categories_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_categories" @@ -1489,7 +1677,7 @@ ALTER TABLE ONLY "project_has_categories" -- --- Name: project_has_categories_project_id_name_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_categories project_has_categories_project_id_name_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_categories" @@ -1497,7 +1685,7 @@ ALTER TABLE ONLY "project_has_categories" -- --- Name: project_has_files_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_files project_has_files_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_files" @@ -1505,7 +1693,7 @@ ALTER TABLE ONLY "project_has_files" -- --- Name: project_has_groups_group_id_project_id_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_groups project_has_groups_group_id_project_id_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_groups" @@ -1513,7 +1701,7 @@ ALTER TABLE ONLY "project_has_groups" -- --- Name: project_has_metadata_project_id_name_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_metadata project_has_metadata_project_id_name_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_metadata" @@ -1521,7 +1709,7 @@ ALTER TABLE ONLY "project_has_metadata" -- --- Name: project_has_notification_types_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_notification_types project_has_notification_types_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_notification_types" @@ -1529,7 +1717,7 @@ ALTER TABLE ONLY "project_has_notification_types" -- --- Name: project_has_notification_types_project_id_notification_type_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_notification_types project_has_notification_types_project_id_notification_type_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_notification_types" @@ -1537,7 +1725,23 @@ ALTER TABLE ONLY "project_has_notification_types" -- --- Name: project_has_users_project_id_user_id_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_roles project_has_roles_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "project_has_roles" + ADD CONSTRAINT "project_has_roles_pkey" PRIMARY KEY ("role_id"); + + +-- +-- Name: project_has_roles project_has_roles_project_id_role_key; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "project_has_roles" + ADD CONSTRAINT "project_has_roles_project_id_role_key" UNIQUE ("project_id", "role"); + + +-- +-- Name: project_has_users project_has_users_project_id_user_id_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_users" @@ -1545,7 +1749,23 @@ ALTER TABLE ONLY "project_has_users" -- --- Name: projects_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: project_role_has_restrictions project_role_has_restrictions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "project_role_has_restrictions" + ADD CONSTRAINT "project_role_has_restrictions_pkey" PRIMARY KEY ("restriction_id"); + + +-- +-- Name: project_role_has_restrictions project_role_has_restrictions_role_id_rule_key; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "project_role_has_restrictions" + ADD CONSTRAINT "project_role_has_restrictions_role_id_rule_key" UNIQUE ("role_id", "rule"); + + +-- +-- Name: projects projects_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "projects" @@ -1553,7 +1773,7 @@ ALTER TABLE ONLY "projects" -- --- Name: remember_me_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: remember_me remember_me_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "remember_me" @@ -1561,7 +1781,7 @@ ALTER TABLE ONLY "remember_me" -- --- Name: settings_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: settings settings_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "settings" @@ -1569,7 +1789,7 @@ ALTER TABLE ONLY "settings" -- --- Name: subtask_time_tracking_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: subtask_time_tracking subtask_time_tracking_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "subtask_time_tracking" @@ -1577,7 +1797,7 @@ ALTER TABLE ONLY "subtask_time_tracking" -- --- Name: swimlanes_name_project_id_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: swimlanes swimlanes_name_project_id_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "swimlanes" @@ -1585,7 +1805,7 @@ ALTER TABLE ONLY "swimlanes" -- --- Name: swimlanes_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: swimlanes swimlanes_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "swimlanes" @@ -1593,7 +1813,7 @@ ALTER TABLE ONLY "swimlanes" -- --- Name: tags_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: tags tags_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "tags" @@ -1601,7 +1821,7 @@ ALTER TABLE ONLY "tags" -- --- Name: tags_project_id_name_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: tags tags_project_id_name_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "tags" @@ -1609,7 +1829,7 @@ ALTER TABLE ONLY "tags" -- --- Name: task_has_external_links_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_external_links task_has_external_links_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_external_links" @@ -1617,7 +1837,7 @@ ALTER TABLE ONLY "task_has_external_links" -- --- Name: task_has_files_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_files task_has_files_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_files" @@ -1625,7 +1845,7 @@ ALTER TABLE ONLY "task_has_files" -- --- Name: task_has_links_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_links task_has_links_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_links" @@ -1633,7 +1853,7 @@ ALTER TABLE ONLY "task_has_links" -- --- Name: task_has_metadata_task_id_name_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_metadata task_has_metadata_task_id_name_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_metadata" @@ -1641,7 +1861,7 @@ ALTER TABLE ONLY "task_has_metadata" -- --- Name: task_has_subtasks_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: subtasks task_has_subtasks_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "subtasks" @@ -1649,7 +1869,7 @@ ALTER TABLE ONLY "subtasks" -- --- Name: task_has_tags_tag_id_task_id_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_tags task_has_tags_tag_id_task_id_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_tags" @@ -1657,7 +1877,7 @@ ALTER TABLE ONLY "task_has_tags" -- --- Name: tasks_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: tasks tasks_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "tasks" @@ -1665,7 +1885,7 @@ ALTER TABLE ONLY "tasks" -- --- Name: transitions_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: transitions transitions_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "transitions" @@ -1673,7 +1893,7 @@ ALTER TABLE ONLY "transitions" -- --- Name: user_has_metadata_user_id_name_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: user_has_metadata user_has_metadata_user_id_name_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_metadata" @@ -1681,7 +1901,7 @@ ALTER TABLE ONLY "user_has_metadata" -- --- Name: user_has_notification_types_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: user_has_notification_types user_has_notification_types_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_notification_types" @@ -1689,7 +1909,7 @@ ALTER TABLE ONLY "user_has_notification_types" -- --- Name: user_has_notifications_project_id_user_id_key; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: user_has_notifications user_has_notifications_project_id_user_id_key; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_notifications" @@ -1697,7 +1917,7 @@ ALTER TABLE ONLY "user_has_notifications" -- --- Name: user_has_unread_notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: user_has_unread_notifications user_has_unread_notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_unread_notifications" @@ -1705,7 +1925,7 @@ ALTER TABLE ONLY "user_has_unread_notifications" -- --- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "users" @@ -1839,7 +2059,7 @@ CREATE UNIQUE INDEX "users_username_idx" ON "users" USING "btree" ("username"); -- --- Name: action_has_params_action_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: action_has_params action_has_params_action_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "action_has_params" @@ -1847,7 +2067,7 @@ ALTER TABLE ONLY "action_has_params" -- --- Name: actions_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: actions actions_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "actions" @@ -1855,7 +2075,63 @@ ALTER TABLE ONLY "actions" -- --- Name: columns_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: column_has_move_restrictions column_has_move_restrictions_dst_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_move_restrictions" + ADD CONSTRAINT "column_has_move_restrictions_dst_column_id_fkey" FOREIGN KEY ("dst_column_id") REFERENCES "columns"("id") ON DELETE CASCADE; + + +-- +-- Name: column_has_move_restrictions column_has_move_restrictions_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_move_restrictions" + ADD CONSTRAINT "column_has_move_restrictions_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE; + + +-- +-- Name: column_has_move_restrictions column_has_move_restrictions_role_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_move_restrictions" + ADD CONSTRAINT "column_has_move_restrictions_role_id_fkey" FOREIGN KEY ("role_id") REFERENCES "project_has_roles"("role_id") ON DELETE CASCADE; + + +-- +-- Name: column_has_move_restrictions column_has_move_restrictions_src_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_move_restrictions" + ADD CONSTRAINT "column_has_move_restrictions_src_column_id_fkey" FOREIGN KEY ("src_column_id") REFERENCES "columns"("id") ON DELETE CASCADE; + + +-- +-- Name: column_has_restrictions column_has_restrictions_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_restrictions" + ADD CONSTRAINT "column_has_restrictions_column_id_fkey" FOREIGN KEY ("column_id") REFERENCES "columns"("id") ON DELETE CASCADE; + + +-- +-- Name: column_has_restrictions column_has_restrictions_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_restrictions" + ADD CONSTRAINT "column_has_restrictions_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE; + + +-- +-- Name: column_has_restrictions column_has_restrictions_role_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "column_has_restrictions" + ADD CONSTRAINT "column_has_restrictions_role_id_fkey" FOREIGN KEY ("role_id") REFERENCES "project_has_roles"("role_id") ON DELETE CASCADE; + + +-- +-- Name: columns columns_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "columns" @@ -1863,7 +2139,7 @@ ALTER TABLE ONLY "columns" -- --- Name: comments_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: comments comments_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "comments" @@ -1871,7 +2147,7 @@ ALTER TABLE ONLY "comments" -- --- Name: group_has_users_group_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: group_has_users group_has_users_group_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "group_has_users" @@ -1879,7 +2155,7 @@ ALTER TABLE ONLY "group_has_users" -- --- Name: group_has_users_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: group_has_users group_has_users_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "group_has_users" @@ -1887,7 +2163,7 @@ ALTER TABLE ONLY "group_has_users" -- --- Name: last_logins_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: last_logins last_logins_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "last_logins" @@ -1895,7 +2171,7 @@ ALTER TABLE ONLY "last_logins" -- --- Name: password_reset_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: password_reset password_reset_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "password_reset" @@ -1903,7 +2179,7 @@ ALTER TABLE ONLY "password_reset" -- --- Name: project_activities_creator_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_activities project_activities_creator_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_activities" @@ -1911,7 +2187,7 @@ ALTER TABLE ONLY "project_activities" -- --- Name: project_activities_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_activities project_activities_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_activities" @@ -1919,7 +2195,7 @@ ALTER TABLE ONLY "project_activities" -- --- Name: project_activities_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_activities project_activities_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_activities" @@ -1927,7 +2203,7 @@ ALTER TABLE ONLY "project_activities" -- --- Name: project_daily_stats_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_daily_stats project_daily_stats_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_daily_stats" @@ -1935,7 +2211,7 @@ ALTER TABLE ONLY "project_daily_stats" -- --- Name: project_daily_summaries_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_daily_column_stats project_daily_summaries_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_daily_column_stats" @@ -1943,7 +2219,7 @@ ALTER TABLE ONLY "project_daily_column_stats" -- --- Name: project_daily_summaries_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_daily_column_stats project_daily_summaries_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_daily_column_stats" @@ -1951,7 +2227,7 @@ ALTER TABLE ONLY "project_daily_column_stats" -- --- Name: project_has_categories_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_categories project_has_categories_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_categories" @@ -1959,7 +2235,7 @@ ALTER TABLE ONLY "project_has_categories" -- --- Name: project_has_files_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_files project_has_files_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_files" @@ -1967,7 +2243,7 @@ ALTER TABLE ONLY "project_has_files" -- --- Name: project_has_groups_group_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_groups project_has_groups_group_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_groups" @@ -1975,7 +2251,7 @@ ALTER TABLE ONLY "project_has_groups" -- --- Name: project_has_groups_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_groups project_has_groups_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_groups" @@ -1983,7 +2259,7 @@ ALTER TABLE ONLY "project_has_groups" -- --- Name: project_has_metadata_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_metadata project_has_metadata_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_metadata" @@ -1991,7 +2267,7 @@ ALTER TABLE ONLY "project_has_metadata" -- --- Name: project_has_notification_types_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_notification_types project_has_notification_types_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_notification_types" @@ -1999,7 +2275,15 @@ ALTER TABLE ONLY "project_has_notification_types" -- --- Name: project_has_users_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_roles project_has_roles_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "project_has_roles" + ADD CONSTRAINT "project_has_roles_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE; + + +-- +-- Name: project_has_users project_has_users_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_users" @@ -2007,7 +2291,7 @@ ALTER TABLE ONLY "project_has_users" -- --- Name: project_has_users_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_has_users project_has_users_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "project_has_users" @@ -2015,7 +2299,23 @@ ALTER TABLE ONLY "project_has_users" -- --- Name: remember_me_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: project_role_has_restrictions project_role_has_restrictions_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "project_role_has_restrictions" + ADD CONSTRAINT "project_role_has_restrictions_project_id_fkey" FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE CASCADE; + + +-- +-- Name: project_role_has_restrictions project_role_has_restrictions_role_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY "project_role_has_restrictions" + ADD CONSTRAINT "project_role_has_restrictions_role_id_fkey" FOREIGN KEY ("role_id") REFERENCES "project_has_roles"("role_id") ON DELETE CASCADE; + + +-- +-- Name: remember_me remember_me_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "remember_me" @@ -2023,7 +2323,7 @@ ALTER TABLE ONLY "remember_me" -- --- Name: subtask_time_tracking_subtask_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: subtask_time_tracking subtask_time_tracking_subtask_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "subtask_time_tracking" @@ -2031,7 +2331,7 @@ ALTER TABLE ONLY "subtask_time_tracking" -- --- Name: subtask_time_tracking_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: subtask_time_tracking subtask_time_tracking_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "subtask_time_tracking" @@ -2039,7 +2339,7 @@ ALTER TABLE ONLY "subtask_time_tracking" -- --- Name: swimlanes_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: swimlanes swimlanes_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "swimlanes" @@ -2047,7 +2347,7 @@ ALTER TABLE ONLY "swimlanes" -- --- Name: task_has_external_links_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_external_links task_has_external_links_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_external_links" @@ -2055,7 +2355,7 @@ ALTER TABLE ONLY "task_has_external_links" -- --- Name: task_has_files_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_files task_has_files_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_files" @@ -2063,7 +2363,7 @@ ALTER TABLE ONLY "task_has_files" -- --- Name: task_has_links_link_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_links task_has_links_link_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_links" @@ -2071,7 +2371,7 @@ ALTER TABLE ONLY "task_has_links" -- --- Name: task_has_links_opposite_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_links task_has_links_opposite_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_links" @@ -2079,7 +2379,7 @@ ALTER TABLE ONLY "task_has_links" -- --- Name: task_has_links_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_links task_has_links_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_links" @@ -2087,7 +2387,7 @@ ALTER TABLE ONLY "task_has_links" -- --- Name: task_has_metadata_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_metadata task_has_metadata_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_metadata" @@ -2095,7 +2395,7 @@ ALTER TABLE ONLY "task_has_metadata" -- --- Name: task_has_subtasks_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: subtasks task_has_subtasks_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "subtasks" @@ -2103,7 +2403,7 @@ ALTER TABLE ONLY "subtasks" -- --- Name: task_has_tags_tag_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_tags task_has_tags_tag_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_tags" @@ -2111,7 +2411,7 @@ ALTER TABLE ONLY "task_has_tags" -- --- Name: task_has_tags_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: task_has_tags task_has_tags_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "task_has_tags" @@ -2119,7 +2419,7 @@ ALTER TABLE ONLY "task_has_tags" -- --- Name: tasks_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: tasks tasks_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "tasks" @@ -2127,7 +2427,7 @@ ALTER TABLE ONLY "tasks" -- --- Name: tasks_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: tasks tasks_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "tasks" @@ -2135,7 +2435,7 @@ ALTER TABLE ONLY "tasks" -- --- Name: transitions_dst_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: transitions transitions_dst_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "transitions" @@ -2143,7 +2443,7 @@ ALTER TABLE ONLY "transitions" -- --- Name: transitions_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: transitions transitions_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "transitions" @@ -2151,7 +2451,7 @@ ALTER TABLE ONLY "transitions" -- --- Name: transitions_src_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: transitions transitions_src_column_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "transitions" @@ -2159,7 +2459,7 @@ ALTER TABLE ONLY "transitions" -- --- Name: transitions_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: transitions transitions_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "transitions" @@ -2167,7 +2467,7 @@ ALTER TABLE ONLY "transitions" -- --- Name: transitions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: transitions transitions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "transitions" @@ -2175,7 +2475,7 @@ ALTER TABLE ONLY "transitions" -- --- Name: user_has_metadata_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: user_has_metadata user_has_metadata_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_metadata" @@ -2183,7 +2483,7 @@ ALTER TABLE ONLY "user_has_metadata" -- --- Name: user_has_notification_types_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: user_has_notification_types user_has_notification_types_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_notification_types" @@ -2191,7 +2491,7 @@ ALTER TABLE ONLY "user_has_notification_types" -- --- Name: user_has_notifications_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: user_has_notifications user_has_notifications_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_notifications" @@ -2199,7 +2499,7 @@ ALTER TABLE ONLY "user_has_notifications" -- --- Name: user_has_notifications_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: user_has_notifications user_has_notifications_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_notifications" @@ -2207,7 +2507,7 @@ ALTER TABLE ONLY "user_has_notifications" -- --- Name: user_has_unread_notifications_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: user_has_unread_notifications user_has_unread_notifications_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY "user_has_unread_notifications" @@ -2222,8 +2522,8 @@ ALTER TABLE ONLY "user_has_unread_notifications" -- PostgreSQL database dump -- --- Dumped from database version 9.5.2 --- Dumped by pg_dump version 9.5.2 +-- Dumped from database version 9.6.1 +-- Dumped by pg_dump version 9.6.1 SET statement_timeout = 0; SET lock_timeout = 0; @@ -2243,8 +2543,8 @@ INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('board_high INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('board_public_refresh_interval', '60', 0, 0); INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('board_private_refresh_interval', '10', 0, 0); INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('board_columns', '', 0, 0); -INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('webhook_token', 'c9a7c2a4523f1724b2ca047c5685f8e2b26bba47eb69baf4f22d5d50d837', 0, 0); -INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('api_token', 'c57a6cb1789269547b616454e4e2f06d3de0514f83baf8fa5b5a8af44a08', 0, 0); +INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('webhook_token', 'b64911d9b61ea71adada348105281e16470e268fce7cb9bf1895958d4bbc', 0, 0); +INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('api_token', 'f63bd25c2e952d78b70f178fd96b4207ef29315ca73d308af37c02d8d51f', 0, 0); INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('application_language', 'en_US', 0, 0); INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('application_timezone', 'UTC', 0, 0); INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('application_url', '', 0, 0); @@ -2272,8 +2572,8 @@ INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('password_r -- PostgreSQL database dump -- --- Dumped from database version 9.5.2 --- Dumped by pg_dump version 9.5.2 +-- Dumped from database version 9.6.1 +-- Dumped by pg_dump version 9.6.1 SET statement_timeout = 0; SET lock_timeout = 0; @@ -2313,4 +2613,4 @@ SELECT pg_catalog.setval('links_id_seq', 11, true); -- PostgreSQL database dump complete -- -INSERT INTO users (username, password, role) VALUES ('admin', '$2y$10$yUJ9QnhG.f47yO.YvWKo3eMAHULukpluDNTOF9.Z7QQg0vOfFRB6u', 'app-admin');INSERT INTO schema_version VALUES ('91'); +INSERT INTO users (username, password, role) VALUES ('admin', '$2y$10$0.8BJyhOEBHGqfwD3nIJHuxObqTlZGJ/KRNDVHfSu7RGd42rEbSa.', 'app-admin');INSERT INTO schema_version VALUES ('97'); diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index edf6ce63..11dcd537 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -6,7 +6,12 @@ use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; use PDO; -const VERSION = 107; +const VERSION = 108; + +function version_108(PDO $pdo) +{ + $pdo->exec('ALTER TABLE users ADD COLUMN api_access_token VARCHAR(255) DEFAULT NULL'); +} function version_107(PDO $pdo) { diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php index adff1e63..c2dad0e6 100644 --- a/app/ServiceProvider/AuthenticationProvider.php +++ b/app/ServiceProvider/AuthenticationProvider.php @@ -2,6 +2,7 @@ namespace Kanboard\ServiceProvider; +use Kanboard\Auth\ApiAccessTokenAuth; use Pimple\Container; use Pimple\ServiceProviderInterface; use Kanboard\Core\Security\AuthenticationManager; @@ -44,6 +45,8 @@ class AuthenticationProvider implements ServiceProviderInterface $container['authenticationManager']->register(new LdapAuth($container)); } + $container['authenticationManager']->register(new ApiAccessTokenAuth($container)); + $container['projectAccessMap'] = $this->getProjectAccessMap(); $container['applicationAccessMap'] = $this->getApplicationAccessMap(); $container['apiAccessMap'] = $this->getApiAccessMap(); diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index c5bf0678..8d471b79 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -91,7 +91,6 @@ class ClassProvider implements ServiceProviderInterface 'TransitionModel', 'UserModel', 'UserLockingModel', - 'UserMentionModel', 'UserNotificationModel', 'UserNotificationFilterModel', 'UserUnreadNotificationModel', diff --git a/app/ServiceProvider/CommandProvider.php b/app/ServiceProvider/CommandProvider.php index 55c2712b..c9abb294 100644 --- a/app/ServiceProvider/CommandProvider.php +++ b/app/ServiceProvider/CommandProvider.php @@ -3,6 +3,8 @@ namespace Kanboard\ServiceProvider; use Kanboard\Console\CronjobCommand; +use Kanboard\Console\DatabaseMigrationCommand; +use Kanboard\Console\DatabaseVersionCommand; use Kanboard\Console\LocaleComparatorCommand; use Kanboard\Console\LocaleSyncCommand; use Kanboard\Console\PluginInstallCommand; @@ -55,6 +57,8 @@ class CommandProvider implements ServiceProviderInterface $application->add(new PluginUpgradeCommand($container)); $application->add(new PluginInstallCommand($container)); $application->add(new PluginUninstallCommand($container)); + $application->add(new DatabaseMigrationCommand($container)); + $application->add(new DatabaseVersionCommand($container)); $container['cli'] = $application; return $container; diff --git a/app/ServiceProvider/DatabaseProvider.php b/app/ServiceProvider/DatabaseProvider.php index a3f57457..9998ac43 100644 --- a/app/ServiceProvider/DatabaseProvider.php +++ b/app/ServiceProvider/DatabaseProvider.php @@ -27,6 +27,10 @@ class DatabaseProvider implements ServiceProviderInterface { $container['db'] = $this->getInstance(); + if (DB_RUN_MIGRATIONS) { + self::runMigrations($container['db']); + } + if (DEBUG) { $container['db']->getStatementHandler() ->withLogging() @@ -38,7 +42,7 @@ class DatabaseProvider implements ServiceProviderInterface } /** - * Setup the database driver and execute schema migration + * Setup the database driver * * @access public * @return \PicoDb\Database @@ -59,12 +63,39 @@ class DatabaseProvider implements ServiceProviderInterface throw new LogicException('Database driver not supported'); } - if ($db->schema()->check(\Schema\VERSION)) { - return $db; - } else { + return $db; + } + + /** + * Get current database version + * + * @static + * @access public + * @param Database $db + * @return int + */ + public static function getSchemaVersion(Database $db) + { + return $db->getDriver()->getSchemaVersion(); + } + + /** + * Execute database migrations + * + * @static + * @access public + * @throws RuntimeException + * @param Database $db + * @return bool + */ + public static function runMigrations(Database $db) + { + if (! $db->schema()->check(\Schema\VERSION)) { $messages = $db->getLogMessages(); throw new RuntimeException('Unable to run SQL migrations: '.implode(', ', $messages).' (You may have to fix it manually)'); } + + return true; } /** @@ -79,7 +110,7 @@ class DatabaseProvider implements ServiceProviderInterface return new Database(array( 'driver' => 'sqlite', - 'filename' => DB_FILENAME + 'filename' => DB_FILENAME, )); } diff --git a/app/ServiceProvider/JobProvider.php b/app/ServiceProvider/JobProvider.php index 2194b11c..4e5e0f1a 100644 --- a/app/ServiceProvider/JobProvider.php +++ b/app/ServiceProvider/JobProvider.php @@ -10,6 +10,7 @@ use Kanboard\Job\SubtaskEventJob; use Kanboard\Job\TaskEventJob; use Kanboard\Job\TaskFileEventJob; use Kanboard\Job\TaskLinkEventJob; +use Kanboard\Job\UserMentionJob; use Pimple\Container; use Pimple\ServiceProviderInterface; @@ -62,6 +63,10 @@ class JobProvider implements ServiceProviderInterface return new ProjectMetricJob($c); }); + $container['userMentionJob'] = $container->factory(function ($c) { + return new UserMentionJob($c); + }); + return $container; } } diff --git a/app/ServiceProvider/RouteProvider.php b/app/ServiceProvider/RouteProvider.php index 0d1a7931..52687647 100644 --- a/app/ServiceProvider/RouteProvider.php +++ b/app/ServiceProvider/RouteProvider.php @@ -158,6 +158,7 @@ class RouteProvider implements ServiceProviderInterface $container['route']->addRoute('user/:user_id/authentication', 'UserCredentialController', 'changeAuthentication'); $container['route']->addRoute('user/:user_id/2fa', 'TwoFactorController', 'index'); $container['route']->addRoute('user/:user_id/avatar', 'AvatarFileController', 'show'); + $container['route']->addRoute('user/:user_id/api', 'UserApiAccessController', 'show'); // Groups $container['route']->addRoute('groups', 'GroupListController', 'index'); diff --git a/app/Subscriber/NotificationSubscriber.php b/app/Subscriber/NotificationSubscriber.php index 7cc68b26..ad16685b 100644 --- a/app/Subscriber/NotificationSubscriber.php +++ b/app/Subscriber/NotificationSubscriber.php @@ -15,25 +15,25 @@ class NotificationSubscriber extends BaseSubscriber implements EventSubscriberIn public static function getSubscribedEvents() { return array( - TaskModel::EVENT_USER_MENTION => 'handleEvent', - TaskModel::EVENT_CREATE => 'handleEvent', - TaskModel::EVENT_UPDATE => 'handleEvent', - TaskModel::EVENT_CLOSE => 'handleEvent', - TaskModel::EVENT_OPEN => 'handleEvent', - TaskModel::EVENT_MOVE_COLUMN => 'handleEvent', - TaskModel::EVENT_MOVE_POSITION => 'handleEvent', - TaskModel::EVENT_MOVE_SWIMLANE => 'handleEvent', - TaskModel::EVENT_ASSIGNEE_CHANGE => 'handleEvent', - SubtaskModel::EVENT_CREATE => 'handleEvent', - SubtaskModel::EVENT_UPDATE => 'handleEvent', - SubtaskModel::EVENT_DELETE => 'handleEvent', - CommentModel::EVENT_CREATE => 'handleEvent', - CommentModel::EVENT_UPDATE => 'handleEvent', - CommentModel::EVENT_DELETE => 'handleEvent', - CommentModel::EVENT_USER_MENTION => 'handleEvent', - TaskFileModel::EVENT_CREATE => 'handleEvent', - TaskLinkModel::EVENT_CREATE_UPDATE => 'handleEvent', - TaskLinkModel::EVENT_DELETE => 'handleEvent', + TaskModel::EVENT_USER_MENTION => 'handleEvent', + TaskModel::EVENT_CREATE => 'handleEvent', + TaskModel::EVENT_UPDATE => 'handleEvent', + TaskModel::EVENT_CLOSE => 'handleEvent', + TaskModel::EVENT_OPEN => 'handleEvent', + TaskModel::EVENT_MOVE_COLUMN => 'handleEvent', + TaskModel::EVENT_MOVE_POSITION => 'handleEvent', + TaskModel::EVENT_MOVE_SWIMLANE => 'handleEvent', + TaskModel::EVENT_ASSIGNEE_CHANGE => 'handleEvent', + SubtaskModel::EVENT_CREATE => 'handleEvent', + SubtaskModel::EVENT_UPDATE => 'handleEvent', + SubtaskModel::EVENT_DELETE => 'handleEvent', + CommentModel::EVENT_CREATE => 'handleEvent', + CommentModel::EVENT_UPDATE => 'handleEvent', + CommentModel::EVENT_DELETE => 'handleEvent', + CommentModel::EVENT_USER_MENTION => 'handleEvent', + TaskFileModel::EVENT_CREATE => 'handleEvent', + TaskLinkModel::EVENT_CREATE_UPDATE => 'handleEvent', + TaskLinkModel::EVENT_DELETE => 'handleEvent', ); } diff --git a/app/Template/category/edit.php b/app/Template/category/edit.php index 72fd40de..d8ca313d 100644 --- a/app/Template/category/edit.php +++ b/app/Template/category/edit.php @@ -10,10 +10,10 @@ <?= $this->form->hidden('project_id', $values) ?> <?= $this->form->label(t('Category Name'), 'name') ?> - <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> + <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"', 'tabindex="1"')) ?> <?= $this->form->label(t('Description'), 'description') ?> - <?= $this->form->textEditor('description', $values, $errors) ?> + <?= $this->form->textEditor('description', $values, $errors, array('tabindex' => 2)) ?> <div class="form-actions"> <button type="submit" class="btn btn-blue"><?= t('Save') ?></button> diff --git a/app/Template/category/index.php b/app/Template/category/index.php index ac60d9a8..336b79a2 100644 --- a/app/Template/category/index.php +++ b/app/Template/category/index.php @@ -15,9 +15,11 @@ <a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-cog fa-fw"></i><i class="fa fa-caret-down"></i></a> <ul> <li> + <i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> <?= $this->url->link(t('Edit'), 'CategoryController', 'edit', array('project_id' => $project['id'], 'category_id' => $category_id), false, 'popover') ?> </li> <li> + <i class="fa fa-trash-o fa-fw" aria-hidden="true"></i> <?= $this->url->link(t('Remove'), 'CategoryController', 'confirm', array('project_id' => $project['id'], 'category_id' => $category_id), false, 'popover') ?> </li> </ul> diff --git a/app/Template/column/create.php b/app/Template/column/create.php index 71c94062..f4cded52 100644 --- a/app/Template/column/create.php +++ b/app/Template/column/create.php @@ -8,18 +8,18 @@ <?= $this->form->hidden('project_id', $values) ?> <?= $this->form->label(t('Title'), 'title') ?> - <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> + <?= $this->form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="50"', 'tabindex="1"')) ?> <?= $this->form->label(t('Task limit'), 'task_limit') ?> - <?= $this->form->number('task_limit', $values, $errors) ?> + <?= $this->form->number('task_limit', $values, $errors, array('tabindex="2"')) ?> - <?= $this->form->checkbox('hide_in_dashboard', t('Hide tasks in this column in the dashboard'), 1) ?> + <?= $this->form->checkbox('hide_in_dashboard', t('Hide tasks in this column in the dashboard'), 1, false, '', array('tabindex' => 3)) ?> <?= $this->form->label(t('Description'), 'description') ?> - <?= $this->form->textEditor('description', $values, $errors) ?> + <?= $this->form->textEditor('description', $values, $errors, array('tabindex' => 4)) ?> <div class="form-actions"> - <button type="submit" class="btn btn-blue"><?= t('Save') ?></button> + <button type="submit" class="btn btn-blue" tabindex="5"><?= t('Save') ?></button> <?= t('or') ?> <?= $this->url->link(t('cancel'), 'column', 'index', array('project_id' => $project['id']), false, 'close-popover') ?> </div> diff --git a/app/Template/comments/show.php b/app/Template/comments/show.php index 5c6d8e20..dfc13821 100644 --- a/app/Template/comments/show.php +++ b/app/Template/comments/show.php @@ -26,6 +26,7 @@ 'values' => array( 'user_id' => $this->user->getId(), 'task_id' => $task['id'], + 'project_id' => $task['project_id'], ), 'errors' => array(), 'task' => $task, diff --git a/app/Template/notification/comment_create.php b/app/Template/notification/comment_create.php index fefc8ba1..41262a7e 100644 --- a/app/Template/notification/comment_create.php +++ b/app/Template/notification/comment_create.php @@ -6,6 +6,6 @@ <h3><?= t('New comment') ?></h3> <?php endif ?> -<?= $this->text->markdown($comment['comment']) ?> +<?= $this->text->markdown($comment['comment'], true) ?> <?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>
\ No newline at end of file diff --git a/app/Template/notification/comment_delete.php b/app/Template/notification/comment_delete.php index 928623ec..14babbd9 100644 --- a/app/Template/notification/comment_delete.php +++ b/app/Template/notification/comment_delete.php @@ -2,6 +2,6 @@ <h3><?= t('Comment removed') ?></h3> -<?= $this->text->markdown($comment['comment']) ?> +<?= $this->text->markdown($comment['comment'], true) ?> <?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?> diff --git a/app/Template/notification/comment_update.php b/app/Template/notification/comment_update.php index 2477d8b3..f1cffae6 100644 --- a/app/Template/notification/comment_update.php +++ b/app/Template/notification/comment_update.php @@ -2,6 +2,6 @@ <h3><?= t('Comment updated') ?></h3> -<?= $this->text->markdown($comment['comment']) ?> +<?= $this->text->markdown($comment['comment'], true) ?> <?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>
\ No newline at end of file diff --git a/app/Template/notification/comment_user_mention.php b/app/Template/notification/comment_user_mention.php index 372183df..0990e7ab 100644 --- a/app/Template/notification/comment_user_mention.php +++ b/app/Template/notification/comment_user_mention.php @@ -2,6 +2,6 @@ <p><?= $this->text->e($task['title']) ?></p> -<?= $this->text->markdown($comment['comment']) ?> +<?= $this->text->markdown($comment['comment'], true) ?> <?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>
\ No newline at end of file diff --git a/app/Template/notification/task_assignee_change.php b/app/Template/notification/task_assignee_change.php index 53f7c5c1..f075fdbf 100644 --- a/app/Template/notification/task_assignee_change.php +++ b/app/Template/notification/task_assignee_change.php @@ -14,7 +14,7 @@ <?php if (! empty($task['description'])): ?> <h2><?= t('Description') ?></h2> - <?= $this->text->markdown($task['description']) ?: t('There is no description.') ?> + <?= $this->text->markdown($task['description'], true) ?: t('There is no description.') ?> <?php endif ?> <?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>
\ No newline at end of file diff --git a/app/Template/notification/task_create.php b/app/Template/notification/task_create.php index 3cd68ac0..3439e357 100644 --- a/app/Template/notification/task_create.php +++ b/app/Template/notification/task_create.php @@ -37,7 +37,7 @@ <?php if (! empty($task['description'])): ?> <h2><?= t('Description') ?></h2> - <?= $this->text->markdown($task['description']) ?> + <?= $this->text->markdown($task['description'], true) ?> <?php endif ?> <?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>
\ No newline at end of file diff --git a/app/Template/notification/task_update.php b/app/Template/notification/task_update.php index 8adb2553..9abe8e0a 100644 --- a/app/Template/notification/task_update.php +++ b/app/Template/notification/task_update.php @@ -1,4 +1,4 @@ <h2><?= $this->text->e($task['title']) ?> (#<?= $task['id'] ?>)</h2> -<?= $this->render('task/changes', array('changes' => $changes, 'task' => $task)) ?> +<?= $this->render('task/changes', array('changes' => $changes, 'task' => $task, 'public' => true)) ?> <?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>
\ No newline at end of file diff --git a/app/Template/notification/task_user_mention.php b/app/Template/notification/task_user_mention.php index 3d8c8e95..71ad348b 100644 --- a/app/Template/notification/task_user_mention.php +++ b/app/Template/notification/task_user_mention.php @@ -2,6 +2,6 @@ <p><?= $this->text->e($task['title']) ?></p> <h2><?= t('Description') ?></h2> -<?= $this->text->markdown($task['description']) ?> +<?= $this->text->markdown($task['description'], true) ?> <?= $this->render('notification/footer', array('task' => $task, 'application_url' => $application_url)) ?>
\ No newline at end of file diff --git a/app/Template/swimlane/create.php b/app/Template/swimlane/create.php index 0eb25411..207b526c 100644 --- a/app/Template/swimlane/create.php +++ b/app/Template/swimlane/create.php @@ -7,13 +7,13 @@ <?= $this->form->hidden('project_id', $values) ?> <?= $this->form->label(t('Name'), 'name') ?> - <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> + <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"', 'tabindex="1"')) ?> <?= $this->form->label(t('Description'), 'description') ?> - <?= $this->form->textEditor('description', $values, $errors) ?> + <?= $this->form->textEditor('description', $values, $errors, array('tabindex' => 2)) ?> <div class="form-actions"> - <button type="submit" class="btn btn-blue"><?= t('Save') ?></button> + <button type="submit" class="btn btn-blue" tabindex="3"><?= t('Save') ?></button> <?= t('or') ?> <?= $this->url->link(t('cancel'), 'SwimlaneController', 'index', array('project_id' => $project['id']), false, 'close-popover') ?> </div> diff --git a/app/Template/swimlane/edit.php b/app/Template/swimlane/edit.php index 2cbabb60..d225b345 100644 --- a/app/Template/swimlane/edit.php +++ b/app/Template/swimlane/edit.php @@ -10,13 +10,13 @@ <?= $this->form->hidden('project_id', $values) ?> <?= $this->form->label(t('Name'), 'name') ?> - <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> + <?= $this->form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"', 'tabindex="1"')) ?> <?= $this->form->label(t('Description'), 'description') ?> - <?= $this->form->textEditor('description', $values, $errors) ?> + <?= $this->form->textEditor('description', $values, $errors, array('tabindex' => 2)) ?> <div class="form-actions"> - <button type="submit" class="btn btn-blue"><?= t('Save') ?></button> + <button type="submit" class="btn btn-blue" tabindex="3"><?= t('Save') ?></button> <?= t('or') ?> <?= $this->url->link(t('cancel'), 'SwimlaneController', 'index', array('project_id' => $project['id']), false, 'close-popover') ?> </div> diff --git a/app/Template/swimlane/edit_default.php b/app/Template/swimlane/edit_default.php index f271c513..8a0c0a15 100644 --- a/app/Template/swimlane/edit_default.php +++ b/app/Template/swimlane/edit_default.php @@ -6,7 +6,7 @@ <?= $this->form->hidden('id', $values) ?> <?= $this->form->label(t('Name'), 'default_swimlane') ?> - <?= $this->form->text('default_swimlane', $values, $errors, array('required', 'maxlength="50"')) ?> + <?= $this->form->text('default_swimlane', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> <?= $this->form->checkbox('show_default_swimlane', t('Show default swimlane'), 1, $values['show_default_swimlane'] == 1) ?> diff --git a/app/Template/swimlane/table.php b/app/Template/swimlane/table.php index cefef9de..81daed01 100644 --- a/app/Template/swimlane/table.php +++ b/app/Template/swimlane/table.php @@ -20,12 +20,15 @@ <a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-cog fa-fw"></i><i class="fa fa-caret-down"></i></a> <ul> <li> + <i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> <?= $this->url->link(t('Edit'), 'SwimlaneController', 'editDefault', array('project_id' => $project['id']), false, 'popover') ?> </li> <li> <?php if ($default_swimlane['show_default_swimlane'] == 1): ?> + <i class="fa fa-toggle-off fa-fw" aria-hidden="true"></i> <?= $this->url->link(t('Disable'), 'SwimlaneController', 'disableDefault', array('project_id' => $project['id']), true) ?> <?php else: ?> + <i class="fa fa-toggle-on fa-fw" aria-hidden="true"></i> <?= $this->url->link(t('Enable'), 'SwimlaneController', 'enableDefault', array('project_id' => $project['id']), true) ?> <?php endif ?> </li> @@ -55,16 +58,20 @@ <a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-cog fa-fw"></i><i class="fa fa-caret-down"></i></a> <ul> <li> + <i class="fa fa-pencil-square-o fa-fw" aria-hidden="true"></i> <?= $this->url->link(t('Edit'), 'SwimlaneController', 'edit', array('project_id' => $project['id'], 'swimlane_id' => $swimlane['id']), false, 'popover') ?> </li> <li> <?php if ($swimlane['is_active']): ?> + <i class="fa fa-toggle-off fa-fw" aria-hidden="true"></i> <?= $this->url->link(t('Disable'), 'SwimlaneController', 'disable', array('project_id' => $project['id'], 'swimlane_id' => $swimlane['id']), true) ?> <?php else: ?> + <i class="fa fa-toggle-on fa-fw" aria-hidden="true"></i> <?= $this->url->link(t('Enable'), 'SwimlaneController', 'enable', array('project_id' => $project['id'], 'swimlane_id' => $swimlane['id']), true) ?> <?php endif ?> </li> <li> + <i class="fa fa-trash-o fa-fw" aria-hidden="true"></i> <?= $this->url->link(t('Remove'), 'SwimlaneController', 'confirm', array('project_id' => $project['id'], 'swimlane_id' => $swimlane['id']), false, 'popover') ?> </li> </ul> diff --git a/app/Template/task/changes.php b/app/Template/task/changes.php index 9d36f09f..2c2bf267 100644 --- a/app/Template/task/changes.php +++ b/app/Template/task/changes.php @@ -69,6 +69,10 @@ <?php if (! empty($changes['description'])): ?> <p><strong><?= t('The description has been modified:') ?></strong></p> - <div class="markdown"><?= $this->text->markdown($task['description']) ?></div> + <?php if (isset($public)): ?> + <div class="markdown"><?= $this->text->markdown($task['description'], true) ?></div> + <?php else: ?> + <div class="markdown"><?= $this->text->markdown($task['description']) ?></div> + <?php endif ?> <?php endif ?> <?php endif ?>
\ No newline at end of file diff --git a/app/Template/task_move_position/show.php b/app/Template/task_move_position/show.php index c1a02484..91241016 100644 --- a/app/Template/task_move_position/show.php +++ b/app/Template/task_move_position/show.php @@ -2,45 +2,22 @@ <h2><?= t('Move task to another position on the board') ?></h2> </div> -<script type="x/template" id="template-task-move-position"> - <?= $this->form->label(t('Swimlane'), 'swimlane') ?> - <select v-model="swimlaneId" @change="onChangeSwimlane()" id="form-swimlane"> - <option v-for="swimlane in board" v-bind:value="swimlane.id"> - {{ swimlane.name }} - </option> - </select> +<form> - <div v-if="columns.length > 0"> - <?= $this->form->label(t('Column'), 'column') ?> - <select v-model="columnId" @change="onChangeColumn()" id="form-column"> - <option v-for="column in columns" v-bind:value="column.id"> - {{ column.title }} - </option> - </select> - </div> +<?= $this->app->component('task-move-position', array( + 'saveUrl' => $this->url->href('TaskMovePositionController', 'save', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), + 'board' => $board, + 'swimlaneLabel' => t('Swimlane'), + 'columnLabel' => t('Column'), + 'positionLabel' => t('Position'), + 'beforeLabel' => t('Insert before this task'), + 'afterLabel' => t('Insert after this task'), +)) ?> - <div v-if="tasks.length > 0"> - <?= $this->form->label(t('Position'), 'position') ?> - <select v-model="position" id="form-position"> - <option v-for="task in tasks" v-bind:value="task.position">#{{ task.id }} - {{ task.title }}</option> - </select> - <label><input type="radio" value="before" v-model="positionChoice"><?= t('Insert before this task') ?></label> - <label><input type="radio" value="after" v-model="positionChoice"><?= t('Insert after this task') ?></label> - </div> +<?= $this->app->component('submit-cancel', array( + 'submitLabel' => t('Save'), + 'orLabel' => t('or'), + 'cancelLabel' => t('cancel'), +)) ?> - <div v-if="errorMessage"> - <div class="alert alert-error">{{ errorMessage }}</div> - </div> - - <submit-cancel - label-button="<?= t('Save') ?>" - label-or="<?= t('or') ?>" - label-cancel="<?= t('cancel') ?>" - :callback="onSubmit"> - </submit-cancel> -</script> - -<task-move-position - save-url="<?= $this->url->href('TaskMovePositionController', 'save', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>" - :board='<?= json_encode($board, JSON_HEX_APOS) ?>' -></task-move-position> +</form> diff --git a/app/Template/user_api_access/show.php b/app/Template/user_api_access/show.php new file mode 100644 index 00000000..3d58e0d5 --- /dev/null +++ b/app/Template/user_api_access/show.php @@ -0,0 +1,17 @@ +<div class="page-header"> + <h2><?= t('API User Access') ?></h2> +</div> + +<p class="alert"> + <?php if (empty($user['api_access_token'])): ?> + <?= t('No personal API access token registered.') ?> + <?php else: ?> + <?= t('Your personal API access token is "%s"', $user['api_access_token']) ?> + <?php endif ?> +</p> + +<?php if (! empty($user['api_access_token'])): ?> + <?= $this->url->link(t('Remove your token'), 'UserApiAccessController', 'remove', array('user_id' => $user['id']), true, 'btn btn-red') ?> +<?php endif ?> + +<?= $this->url->link(t('Generate a new token'), 'UserApiAccessController', 'generate', array('user_id' => $user['id']), true, 'btn btn-blue') ?> diff --git a/app/Template/user_view/sidebar.php b/app/Template/user_view/sidebar.php index a80daefa..ef494e42 100644 --- a/app/Template/user_view/sidebar.php +++ b/app/Template/user_view/sidebar.php @@ -90,6 +90,11 @@ <?= $this->url->link(t('Integrations'), 'UserViewController', 'integrations', array('user_id' => $user['id'])) ?> </li> <?php endif ?> + <?php if ($this->user->hasAccess('UserApiAccessController', 'show')): ?> + <li <?= $this->app->checkMenuSelection('UserApiAccessController', 'show') ?>> + <?= $this->url->link(t('API'), 'UserApiAccessController', 'show', array('user_id' => $user['id'])) ?> + </li> + <?php endif ?> <?php endif ?> <?php if ($this->user->hasAccess('UserCredentialController', 'changeAuthentication')): ?> diff --git a/app/constants.php b/app/constants.php index 3adb0835..ba14cde6 100644 --- a/app/constants.php +++ b/app/constants.php @@ -35,6 +35,9 @@ defined('LOG_FILE') or define('LOG_FILE', DATA_DIR.DIRECTORY_SEPARATOR.'debug.lo // Application version defined('APP_VERSION') or define('APP_VERSION', build_app_version('$Format:%d$', '$Format:%H$')); +// Run automatically database migrations +defined('DB_RUN_MIGRATIONS') or define('DB_RUN_MIGRATIONS', true); + // Database driver: sqlite, mysql or postgres defined('DB_DRIVER') or define('DB_DRIVER', 'sqlite'); diff --git a/app/functions.php b/app/functions.php index 8f0d482c..e732f308 100644 --- a/app/functions.php +++ b/app/functions.php @@ -53,6 +53,37 @@ function array_column_index(array &$input, $column) } /** + * Create indexed array from a list of dict with unique values + * + * $input = [ + * ['k1' => 1, 'k2' => 2], ['k1' => 3, 'k2' => 4], ['k1' => 1, 'k2' => 5] + * ] + * + * array_column_index_unique($input, 'k1') will returns: + * + * [ + * 1 => ['k1' => 1, 'k2' => 2], + * 3 => ['k1' => 3, 'k2' => 4], + * ] + * + * @param array $input + * @param string $column + * @return array + */ +function array_column_index_unique(array &$input, $column) +{ + $result = array(); + + foreach ($input as &$row) { + if (isset($row[$column]) && ! isset($result[$row[$column]])) { + $result[$row[$column]] = $row; + } + } + + return $result; +} + +/** * Sum all values from a single column in the input array * * $input = [ diff --git a/assets/css/app.min.css b/assets/css/app.min.css index a861f4bd..0ef8f1c9 100644 --- a/assets/css/app.min.css +++ b/assets/css/app.min.css @@ -1 +1 @@ -h1,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:10px;color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;text-rendering:optimizeLegibility}small{font-size:0.8em}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)}.pull-right{text-align:right}ul.no-bullet li{list-style-type:none;margin-left:0}.chosen-select{min-height:27px}#app-loading-icon{position:fixed;right:3px;bottom:3px}.assign-me{vertical-align:bottom}a{color:#36c;border:none}a:focus{outline:0;color:#DF5353;text-decoration:none}a:hover{color:#333;text-decoration:none}h1,h2,h3{font-weight:normal;color:#333}h1{font-size:1.5em}h2{font-size:1.4em;margin-bottom:10px}h3{margin-top:10px;font-size:1.2em}table{width:100%;border-collapse:collapse;border-spacing:0;margin-bottom:20px}table.table-fixed{table-layout:fixed;white-space:nowrap}table.table-fixed th{overflow:hidden}table.table-fixed td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}table.table-small{font-size:0.8em}table.table-striped tr:nth-child(odd){background:#fefefe}@media (max-width: 768px){table.table-scrolling{overflow-x:auto;display:inline-block;vertical-align:top;max-width:100%;white-space:nowrap}}table th{text-align:left;padding:0.5em 3px;border:1px solid #eee;background:#fbfbfb}table th a{text-decoration:none;color:#333}table th a:focus,table th a:hover{text-decoration:underline}table td{border:1px solid #eee;padding:0.5em 3px;vertical-align:top}table td li{margin-left:20px}.column-1{width:1%}.column-2{width:2%}.column-3{width:3%}.column-4{width:4%}.column-5{width:5%}.column-6{width:6%}.column-7{width:7%}.column-8{width:8%}.column-9{width:9%}.column-10{width:10%}.column-11{width:11%}.column-12{width:12%}.column-13{width:13%}.column-14{width:14%}.column-15{width:15%}.column-16{width:16%}.column-17{width:17%}.column-18{width:18%}.column-19{width:19%}.column-20{width:20%}.column-21{width:21%}.column-22{width:22%}.column-23{width:23%}.column-24{width:24%}.column-25{width:25%}.column-26{width:26%}.column-27{width:27%}.column-28{width:28%}.column-29{width:29%}.column-30{width:30%}.column-31{width:31%}.column-32{width:32%}.column-33{width:33%}.column-34{width:34%}.column-35{width:35%}.column-36{width:36%}.column-37{width:37%}.column-38{width:38%}.column-39{width:39%}.column-40{width:40%}.column-41{width:41%}.column-42{width:42%}.column-43{width:43%}.column-44{width:44%}.column-45{width:45%}.column-46{width:46%}.column-47{width:47%}.column-48{width:48%}.column-49{width:49%}.column-50{width:50%}.column-51{width:51%}.column-52{width:52%}.column-53{width:53%}.column-54{width:54%}.column-55{width:55%}.column-56{width:56%}.column-57{width:57%}.column-58{width:58%}.column-59{width:59%}.column-60{width:60%}.column-61{width:61%}.column-62{width:62%}.column-63{width:63%}.column-64{width:64%}.column-65{width:65%}.column-66{width:66%}.column-67{width:67%}.column-68{width:68%}.column-69{width:69%}.column-70{width:70%}.column-71{width:71%}.column-72{width:72%}.column-73{width:73%}.column-74{width:74%}.column-75{width:75%}.column-76{width:76%}.column-77{width:77%}.column-78{width:78%}.column-79{width:79%}.column-80{width:80%}.column-81{width:81%}.column-82{width:82%}.column-83{width:83%}.column-84{width:84%}.column-85{width:85%}.column-86{width:86%}.column-87{width:87%}.column-88{width:88%}.column-89{width:89%}.column-90{width:90%}.column-91{width:91%}.column-92{width:92%}.column-93{width:93%}.column-94{width:94%}.column-95{width:95%}.column-96{width:96%}.column-97{width:97%}.column-98{width:98%}.column-99{width:99%}.column-100{width:100%}.draggable-row-handle{cursor:move;color:#dedede}.draggable-row-handle:hover{color:#333}tr.draggable-item-selected{background:#fff;border:2px solid #666;box-shadow:4px 2px 10px -4px rgba(0,0,0,0.55)}tr.draggable-item-selected td{border-top:none;border-bottom:none}tr.draggable-item-selected td:first-child{border-left:none}tr.draggable-item-selected td:last-child{border-right:none}.table-stripped tr.draggable-item-hover,.table-stripped tr.draggable-item-hover{background:#FEFFF2}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"]:not(.input-addon-field){color:#999;border:1px solid #ccc;width:300px;max-width:95%;font-size:1em;height:25px;padding-bottom:0;font-family:sans-serif;margin-top:10px;-webkit-appearance:none;-moz-appearance:none}input[type="number"]::-webkit-input-placeholder,input[type="date"]::-webkit-input-placeholder,input[type="email"]::-webkit-input-placeholder,input[type="password"]::-webkit-input-placeholder,input[type="text"]:not(.input-addon-field)::-webkit-input-placeholder{color:#dedede}input[type="number"]::-moz-placeholder,input[type="date"]::-moz-placeholder,input[type="email"]::-moz-placeholder,input[type="password"]::-moz-placeholder,input[type="text"]:not(.input-addon-field)::-moz-placeholder{color:#dedede}input[type="number"]:-ms-input-placeholder,input[type="date"]:-ms-input-placeholder,input[type="email"]:-ms-input-placeholder,input[type="password"]:-ms-input-placeholder,input[type="text"]:not(.input-addon-field):-ms-input-placeholder{color:#dedede}input[type="number"]:focus,input[type="date"]:focus,input[type="email"]:focus,input[type="password"]:focus,input[type="text"]: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[type="number"]{width:70px}input[type="text"]:not(.input-addon-field).form-numeric{width:70px}input[type="text"]:not(.input-addon-field).form-datetime,input[type="text"]:not(.input-addon-field).form-date{width:150px}input[type="text"]:not(.input-addon-field).form-input-large{width:400px}input[type="text"]:not(.input-addon-field).form-input-small{width:150px}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)}textarea{padding:3px;border:1px solid #ccc;width:400px;max-width:99%;height:200px;font-family:sans-serif;font-size:1em}textarea::-webkit-input-placeholder{color:#dedede}textarea::-moz-placeholder{color:#dedede}textarea:-ms-input-placeholder{color:#dedede}select{font-size:1.0em;max-width:95%}select:focus{outline:0}select[multiple]{width:300px}.tag-autocomplete{width:400px}span.select2-container{margin-top:2px}.form-actions{padding-top:20px;clear:both}.form-required{color:red;padding-left:5px;font-weight:bold}@media (max-width: 480px){.form-required{display:none}}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-errors{color:#b94a48;list-style-type:none}ul.form-errors li{margin-left:0}.form-help{font-size:0.8em;color:brown;margin-bottom:15px}.form-inline{padding:0;margin:0;border:none}.form-inline label{display:inline}.form-inline input,.form-inline select{margin:0 15px 0 0}.form-inline .form-required{display:none}.form-inline-group{display:inline}.form-columns{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:flex-start;justify-content:flex-start}.form-columns .form-column{margin-right:25px;flex-grow:1}.form-login{max-width:350px;margin:8% auto 0}.form-login li{margin-left:25px;line-height:25px}.form-login h2{margin-bottom:30px;font-weight:bold}.reset-password{margin-top:20px}.reset-password a{color:#999}.input-addon{display:flex}.input-addon-field{flex:1;font-size:1em;color:#999;margin:0;-webkit-appearance:none;-moz-appearance:none}.input-addon-item{background-color:rgba(147,128,108,0.1);color:#666;font:inherit;font-weight:normal}@media (max-width: 480px){.input-addon-item .dropdown .fa-caret-down{display:none}}.input-addon-field,.input-addon-item{border:1px solid rgba(147,128,108,0.25);padding:4px 0.75em}.input-addon-field:not(:first-child),.input-addon-item:not(:first-child){border-left:0}.input-addon-field:first-child,.input-addon-item:first-child{border-radius:5px 0 0 5px}.input-addon-field:last-child,.input-addon-item:last-child{border-radius:0 5px 5px 0}.alert{padding:8px 35px 8px 14px;margin-top:5px;margin-bottom:5px;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}.alert-fade-out{text-align:center;position:fixed;bottom:0;left:20%;width:60%;padding-top:5px;padding-bottom:5px;margin-bottom:0;border-width:1px 0 0;border-radius:4px 4px 0 0;z-index:9999}a.btn{text-decoration:none}.btn{-webkit-appearance:none;-moz-appearance:none;font-size:1.2em;font-weight:normal;cursor:pointer;display:inline-block;border-radius:2px;padding:3px 10px;margin:0;border:1px solid #ddd;background:#f5f5f5;color:#333}.btn:hover,.btn:focus{border-color:#bbb;background:#fafafa;color:#000}.btn-red{border-color:#b0281a;background:#d14836;color:#fff}.btn-red:hover,.btn-red:focus{border-color:#b0281a;background:#c53727;color:#fff}.btn-blue{border-color:#3079ed;background:#4d90fe;color:#fff}.btn-blue:hover,.btn-blue:focus{border-color:#3079ed;background:#357ae8;color:#fff}.btn:disabled{color:#ccc;border-color:#ccc;background:#f7f7f7}.buttons-header{font-size:0.8em;margin-top:5px;margin-bottom:15px}.tooltip-arrow:after{background:#fff;border:1px solid #aaaaaa;box-shadow:0 0 5px #aaa}div.ui-tooltip{min-width:200px;max-width:600px}.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:600px}.ui-tooltip-content .markdown p{margin-bottom:0}.ui-tooltip li{list-style-type:none}.tooltip .fa-info-circle{color:#999}h2 .dropdown ul{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:8px 10px;font-size:0.9em;border-bottom:1px solid #f8f8f8;cursor:pointer}.dropdown-submenu-open li.no-hover{cursor:default}.dropdown-submenu-open li:last-child{border:none}.dropdown-submenu-open li:not(.no-hover):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}.dropdown-menu-link-text,.dropdown-menu-link-icon{color:#333;text-decoration:none}.dropdown-menu-link-text:hover{text-decoration:underline}.accordion-title{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAADCAYAAABS3WWCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NEQ5RDgxQzc2RjQ5MTFFMjhEMUNENzFGRUMwRjhBRTciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NEQ5RDgxQzg2RjQ5MTFFMjhEMUNENzFGRUMwRjhBRTciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0RDlEODFDNTZGNDkxMUUyOEQxQ0Q3MUZFQzBGOEFFNyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0RDlEODFDNjZGNDkxMUUyOEQxQ0Q3MUZFQzBGOEFFNyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvXFWFAAAAAYSURBVHjaYvj//z8D0/Pnz/8zgFgAAQYAS5UJscReGMIAAAAASUVORK5CYII=) repeat-x scroll 0 10px}.accordion-title h3{display:inline;padding-right:5px;background:#fff}.accordion-content{margin-top:15px;margin-bottom:25px}.accordion-toggle{color:#333;text-decoration:none}.accordion-toggle:focus{color:#333}.accordion-toggle:hover{color:#999}.accordion-toggle:before{content:"\f0d7"}.accordion-collapsed{margin-bottom:25px}.accordion-collapsed .accordion-toggle:before{content:"\f0da"}.accordion-collapsed .accordion-content{display:none}#main .confirm{max-width:700px}#popover-container{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.9);overflow:auto;z-index:100}#popover-content{position:fixed;width:950px;max-width:95%;max-height:calc(100% - 50px);top:5%;left:50%;transform:translateX(-50%);padding:0 15px 15px;background:#fff;overflow:auto}#popover-content-header{text-align:right}#popover-close-button{color:#333}#popover-close-button:hover{color:#b94a48}.popover-form{margin-bottom:0}.pagination{text-align:center}.pagination-next{margin-left:5px}.pagination-previous{margin-right:5px}header{box-sizing:border-box;display:flex;flex-wrap:wrap;margin-top:5px;margin-bottom:5px;border-bottom:1px solid #dedede}header>*{box-sizing:border-box}header>*{width:1%}header .menus-container{width:10%}@media (min-width: 768px) and (max-width: 1150px){header .menus-container{width:15%}}@media (max-width: 768px){header .menus-container{width:65%;order:2}}header .board-selector-container{width:15%}@media (min-width: 768px) and (max-width: 1150px){header .board-selector-container{width:20%}}@media (max-width: 768px){header .board-selector-container{width:35%;order:1;margin-bottom:5px}}header .title-container{width:75%}@media (min-width: 768px) and (max-width: 1150px){header .title-container{width:65%}}@media (max-width: 768px){header .title-container{width:100%;order:3}}header h1{font-size:1.5em}header h1 .tooltip{opacity:0.3;font-size:0.7em}.web-notification-icon{color:#36c}.web-notification-icon:focus,.web-notification-icon:hover{color:#000}.logo a{opacity:0.5;color:#d40000;text-decoration:none}.logo span{color:#333}.logo a:hover{opacity:0.8;color:#333}.logo a:focus span,.logo a:hover span{color:#d40000}.page-header{margin-bottom:20px}.page-header .dropdown{padding-right:10px}.page-header h2{margin:0;padding:0;font-weight:bold;border-bottom:1px dotted #ccc}.page-header h2 a{color:#333;text-decoration:none}.page-header h2 a:focus,.page-header h2 a:hover{color:#999}.page-header ul{text-align:left;margin-top:5px;display:inline-block}.page-header li{display:inline;padding-right:15px}@media (max-width: 480px){.page-header li{display:block;line-height:1.5em}}.page-header li.active a{color:#333;text-decoration:none;font-weight:bold}.page-header li.active a:hover,.page-header li.active a:focus{text-decoration:underline}.menu-inline{margin-bottom:5px}.menu-inline li{display:inline;padding-right:15px}.menu-inline li .active a{font-weight:bold;color:#000;text-decoration:none}.sidebar-container{box-sizing:border-box;display:flex;flex-wrap:wrap}.sidebar-container>*{box-sizing:border-box}.sidebar-container>*{width:1%}.sidebar-content{padding-left:10px;width:82%}@media (max-width: 480px){.sidebar-content{width:100%}}.sidebar{max-width:240px;min-width:190px;width:18%}@media (max-width: 480px){.sidebar{width:100%;max-width:99%;min-width:0}}.sidebar h2{margin-top:0}.sidebar>ul a{text-decoration:none;color:#999;font-weight:300}.sidebar>ul a:hover{color:#333}.sidebar>ul li{list-style-type:none;line-height:35px;border-bottom:1px dotted #efefef;padding-left:13px}.sidebar>ul li:hover{border-left:5px solid #555;padding-left:8px}.sidebar>ul li.active{border-left:5px solid #333;padding-left:8px}.sidebar>ul li.active a{color:#333;font-weight:bold}.sidebar-icons>ul li{padding-left:0}.sidebar-icons>ul li:hover,.sidebar-icons>ul li.active{padding-left:0;border-left:none}.sidebar>ul li.active a:focus,.sidebar>ul li.active a:hover{color:#555}.sidebar>ul li:last-child{margin-bottom:15px}.avatar img{vertical-align:bottom}.avatar-left{float:left;margin-right:10px}.avatar-inline{display:inline-block;margin-right:3px}.avatar-48 img,.avatar-48 div{border-radius:30px}.avatar-48 .avatar-letter{line-height:48px;width:48px;font-size:25px}.avatar-20 img,.avatar-20 div{border-radius:10px}.avatar-20 .avatar-letter{line-height:20px;width:20px;font-size:11px}.avatar-letter{color:#fff;text-align:center}#file-dropzone,#screenshot-zone{position:relative;border:2px dashed #ccc;width:99%;height:250px;overflow:auto}#file-dropzone-inner,#screenshot-inner{position:absolute;left:0;bottom:48%;width:100%;text-align:center;color:#aaa}#screenshot-zone.screenshot-pasted{border:2px solid #333}#file-list{margin:20px}#file-list li{list-style-type:none;padding-top:8px;padding-bottom:8px;border-bottom:1px dotted #ddd;width:95%}#file-list li.file-error{font-weight:bold;color:#b94a48}.file-thumbnails{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:flex-start;justify-content:flex-start}.file-thumbnail{width:250px;border:1px solid #efefef;border-radius:5px;margin-bottom:20px;box-shadow:4px 2px 10px -6px rgba(0,0,0,0.55);margin-right:15px}.file-thumbnail img{border-top-left-radius:5px;border-top-right-radius:5px}.file-thumbnail img:hover{opacity:0.5}.file-thumbnail-content{padding-left:8px;padding-right:8px}.file-thumbnail-title{font-weight:700;font-size:0.9em;color:#555}.file-thumbnail-description{font-size:0.8em;color:#999;margin-top:8px;margin-bottom:5px}.file-viewer{position:relative}.file-viewer img{max-width:95%;max-height:85%;margin-top:10px}.color-picker{width:180px}.color-picker-option{height:25px}.color-picker-square{display:inline-block;width:18px;height:18px;margin-right:5px;border:1px solid #000}.color-picker-label{display:inline-block;vertical-align:bottom;padding-bottom:3px}.filter-box{max-width:800px}.action-menu{color:#333;text-decoration:none}.action-menu:hover,.action-menu:focus{text-decoration:underline}.project-creation-options{max-width:500px;border-left:3px dotted #efefef;margin-top:20px;padding-left:15px;padding-bottom:5px;padding-top:5px}.project-overview-columns{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;margin-bottom:20px;font-size:1.4em}@media (max-width: 480px){.project-overview-columns{display:block}}.project-overview-column{text-align:center;margin-right:3%;margin-top:5px;padding:3px 15px 3px 15px;border:1px dashed #ddd}@media (max-width: 480px){.project-overview-column{text-align:left}}.project-overview-column small{color:#999}.project-overview-column strong{color:#555;display:block}@media (max-width: 480px){.project-overview-column strong{display:inline}}.project-header{box-sizing:border-box;display:flex;flex-wrap:wrap;margin-bottom:8px}.project-header>*{box-sizing:border-box}.project-header>*{width:1%}.project-header .dropdown-component{margin-top:4px;width:5%}@media (min-width: 768px) and (max-width: 1150px){.project-header .dropdown-component{width:8%}}@media (max-width: 768px){.project-header .dropdown-component{width:100%}}.project-header .views-switcher-component{margin-top:4px;width:38%}@media (max-width: 1300px){.project-header .views-switcher-component{width:45%}}@media (min-width: 768px) and (max-width: 1150px){.project-header .views-switcher-component{width:92%}}@media (max-width: 768px){.project-header .views-switcher-component{margin-top:0;width:100%}}.project-header .filter-box-component{margin:0;width:55%}@media (max-width: 1300px){.project-header .filter-box-component{width:50%}}@media (min-width: 768px) and (max-width: 1150px){.project-header .filter-box-component{width:100%;margin-top:10px}.project-header .filter-box-component .filter-box{max-width:100%}}@media (max-width: 768px){.project-header .filter-box-component{width:100%;margin-top:10px}.project-header .filter-box-component .filter-box{max-width:100%}}.project-header .filter-box-component form{margin:0}.views{display:inline-block;margin-right:10px;font-size:0.9em}@media (max-width: 560px){.views{width:100%}}@media (max-width: 768px){.views{margin-top:10px;font-size:1em}}@media (max-width: 480px){.views{margin-top:5px}}.views li{white-space:nowrap;background:#fafafa;border:1px solid #ddd;border-right:none;padding:4px 8px;display:inline}@media (max-width: 560px){.views li{display:block;margin-top:5px;border-radius:5px;border:1px solid #ddd}}.views li.active a{font-weight:bold;color:#000;text-decoration:none}.views li:first-child{border-top-left-radius:5px;border-bottom-left-radius:5px}.views li:last-child{border-right:1px solid #ddd;border-top-right-radius:5px;border-bottom-right-radius:5px}.views a{color:#555;text-decoration:none}.views a:hover{color:#333;text-decoration:underline}.dashboard-project-stats small{margin-right:10px;color:#999}.dashboard-table-link{font-weight:bold;color:#000;text-decoration:none}.dashboard-table-link:focus,.dashboard-table-link:hover{color:#999}.public-board{margin-top:5px}.public-task{max-width:800px;margin:5px auto 0}#board-container{overflow-x:auto}#board{table-layout:fixed;margin-bottom:0}#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 .dropdown-menu{text-decoration:none}.board-add-icon{float:left;padding:0 5px}.board-add-icon a{text-decoration:none;color:#36c;font-size:1.6em;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}a.board-swimlane-toggle{text-decoration:none}a.board-swimlane-toggle:hover,a.board-swimlane-toggle:focus{color:#000;text-decoration:none;border:none}.board-task-list{min-height:60px}.board-task-list-limit{background-color:#DF5353}.draggable-item{cursor:pointer;user-select:none;-webkit-user-select:none;-moz-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;word-wrap:break-word;font-size:0.9em}div.task-board-recent{border-width:2px}div.task-board-status-closed{user-select:none;border:1px dotted #555}.task-board a{color:#000;text-decoration:none}.task-board .dropdown-menu{font-weight:bold}.task-board .task-score{font-weight:bold}.task-board-collapsed{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.task-board-title{margin-top:5px;margin-bottom:8px}.task-board-title a:hover{text-decoration:underline}.task-board-saving-state{opacity:0.3}.task-board-saving-icon{position:absolute;margin:auto;width:100%;text-align:center;color:#000}.task-board-category-container{text-align:right;margin-top:8px;margin-bottom:8px}.task-board-category{font-weight:500;color:#000;border:1px solid #555;padding:1px 2px 1px 2px;border-radius:4px}.task-board-category:hover{opacity:0.6}.task-board-avatars{text-align:right;float:right}.task-board-change-assignee{cursor:pointer}.task-board-change-assignee:hover{opacity:0.6}.task-board-icons{font-size:0.8em;text-align:right;margin-top:4px;margin-bottom:2px}.task-board-icons a{opacity:0.5}.task-board-icons span{opacity:0.5;margin-left:2px}.task-board-icons a:hover,.task-board-icons span:hover{opacity:1.0}.flag-milestone{color:green}.task-board-age{display:inline-block}span.task-board-age-total{border:#666 1px solid;padding:1px 3px 1px 3px;border-top-left-radius:3px;border-bottom-left-radius:3px}span.task-board-age-column{border:#666 1px solid;border-left:none;margin-left:-5px;padding:1px 3px 1px 3px;border-top-right-radius:3px;border-bottom-right-radius:3px}.task-board-date{font-weight:bold;color:#000}span.task-board-date-today{opacity:1.0;color:#36c}span.task-board-date-overdue{opacity:1.0;color:#b94a48}.task-tags li{display:inline-block;margin:3px 3px 0 0;padding:1px 3px 1px 3px;color:#333;border:1px solid #333;border-radius:4px}.task-summary-container .task-tags{margin-top:10px}#task-summary{margin-bottom:15px}#task-summary h2{color:#555;font-size:1.6em;margin-top:0;padding-top:0}.task-summary-container{border:2px solid #000;border-radius:8px;padding:15px}.task-summary-columns{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:space-between;justify-content:space-between}@media (max-width: 480px){.task-summary-columns{display:block}}.task-summary-column{color:#333}.task-summary-column span{color:#555}.task-summary-column li{line-height:23px}#external-task-view{padding:10px;margin-top:10px;margin-bottom:10px;border:1px dotted #ccc}.task-table .dropdown-menu{color:#000;text-decoration:none;font-weight:bold}.task-table .dropdown-menu:focus,.task-table .dropdown-menu:hover{text-decoration:underline}td.task-table a{color:#000;text-decoration:none}td.task-table a:hover{text-decoration:underline}.comment-sorting{text-align:right}.comment-sorting a{color:#555;font-weight:normal;text-decoration:none}.comment-sorting a:hover{color:#999}.comment{padding:5px;margin-bottom:15px}.comment:hover{background:#fafafa}.comment-title{border-bottom:1px dotted #eee;margin-left:55px;margin-bottom:10px}.comment-date{color:#999;font-weight:200}.comment-actions{font-size:0.8em;margin-left:55px;margin-top:8px}.comment-actions li{display:inline}.comment-actions a{color:#999;text-decoration:none}.comment-actions a:focus,.comment-actions a:hover{color:#333;text-decoration:underline}.comment-content{margin-left:55px}.subtasks-table td{vertical-align:middle}.task-links-table td{vertical-align:middle}.task-links-task-count{color:#999}.task-link-closed{text-decoration:line-through}.text-editor a{font-size:1em;color:#999;text-decoration:none;margin-right:10px}.text-editor a:hover{color:#36c}.text-editor .text-editor-preview-area{border:1px solid #dedede;width:400px;height:200px;overflow:auto;padding:2px}.markdown{line-height:1.4em}.markdown h1{margin-top:5px;margin-bottom:10px;font-weight:bold}.markdown h2{font-weight:bold}.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:#555}.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;color:#555}.documentation img{border:1px solid #333}.documentation h1{text-decoration:none;margin-bottom:30px}.documentation h2{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:#fcfcfc;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:15px;padding:10px}.activity-event:hover{background:#fafafa}.activity-date{margin-left:10px;font-weight:normal;color:#999}.activity-content{margin-left:55px}.activity-title{font-weight:bold;color:#000;border-bottom:1px dotted #efefef}.activity-description{color:#555;margin-top:10px}@media (max-width: 480px){.activity-description{overflow:auto}}.activity-description li{list-style-type:circle}.activity-description ul{margin-top:10px;margin-left:20px}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:none}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:#555}div.ganttview-vtheader{margin-top:41px;width:400px;overflow:hidden;background-color:#fff}div.ganttview-vtheader-item{color:#555}div.ganttview-vtheader-series-name{width:400px;height:31px;line-height:31px;padding-left:3px;border-top:1px solid #d0d0d0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}div.ganttview-vtheader-series-name a{color:#555;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:#555}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 #c0c0c0;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:0.7em;color:#999;padding:2px 3px}div.ganttview-block div.ui-resizable-handle.ui-resizable-s{bottom:-0}.user-mention-link{font-weight:bold;color:#000;text-decoration:none}.user-mention-link:hover{color:#555} +h1,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:10px;color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;text-rendering:optimizeLegibility}small{font-size:0.8em}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)}.pull-right{text-align:right}ul.no-bullet li{list-style-type:none;margin-left:0}.chosen-select{min-height:27px}#app-loading-icon{position:fixed;right:3px;bottom:3px}.assign-me{vertical-align:bottom}a{color:#36c;border:none}a:focus{outline:0;color:#DF5353;text-decoration:none}a:hover{color:#333;text-decoration:none}h1,h2,h3{font-weight:normal;color:#333}h1{font-size:1.5em}h2{font-size:1.4em;margin-bottom:10px}h3{margin-top:10px;font-size:1.2em}table{width:100%;border-collapse:collapse;border-spacing:0;margin-bottom:20px}table.table-fixed{table-layout:fixed;white-space:nowrap}table.table-fixed th{overflow:hidden}table.table-fixed td{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}table.table-small{font-size:0.8em}table.table-striped tr:nth-child(odd){background:#fefefe}@media (max-width: 768px){table.table-scrolling{overflow-x:auto;display:inline-block;vertical-align:top;max-width:100%;white-space:nowrap}}table th{text-align:left;padding:0.5em 3px;border:1px solid #eee;background:#fbfbfb}table th a{text-decoration:none;color:#333}table th a:focus,table th a:hover{text-decoration:underline}table td{border:1px solid #eee;padding:0.5em 3px;vertical-align:top}table td li{margin-left:20px}.column-1{width:1%}.column-2{width:2%}.column-3{width:3%}.column-4{width:4%}.column-5{width:5%}.column-6{width:6%}.column-7{width:7%}.column-8{width:8%}.column-9{width:9%}.column-10{width:10%}.column-11{width:11%}.column-12{width:12%}.column-13{width:13%}.column-14{width:14%}.column-15{width:15%}.column-16{width:16%}.column-17{width:17%}.column-18{width:18%}.column-19{width:19%}.column-20{width:20%}.column-21{width:21%}.column-22{width:22%}.column-23{width:23%}.column-24{width:24%}.column-25{width:25%}.column-26{width:26%}.column-27{width:27%}.column-28{width:28%}.column-29{width:29%}.column-30{width:30%}.column-31{width:31%}.column-32{width:32%}.column-33{width:33%}.column-34{width:34%}.column-35{width:35%}.column-36{width:36%}.column-37{width:37%}.column-38{width:38%}.column-39{width:39%}.column-40{width:40%}.column-41{width:41%}.column-42{width:42%}.column-43{width:43%}.column-44{width:44%}.column-45{width:45%}.column-46{width:46%}.column-47{width:47%}.column-48{width:48%}.column-49{width:49%}.column-50{width:50%}.column-51{width:51%}.column-52{width:52%}.column-53{width:53%}.column-54{width:54%}.column-55{width:55%}.column-56{width:56%}.column-57{width:57%}.column-58{width:58%}.column-59{width:59%}.column-60{width:60%}.column-61{width:61%}.column-62{width:62%}.column-63{width:63%}.column-64{width:64%}.column-65{width:65%}.column-66{width:66%}.column-67{width:67%}.column-68{width:68%}.column-69{width:69%}.column-70{width:70%}.column-71{width:71%}.column-72{width:72%}.column-73{width:73%}.column-74{width:74%}.column-75{width:75%}.column-76{width:76%}.column-77{width:77%}.column-78{width:78%}.column-79{width:79%}.column-80{width:80%}.column-81{width:81%}.column-82{width:82%}.column-83{width:83%}.column-84{width:84%}.column-85{width:85%}.column-86{width:86%}.column-87{width:87%}.column-88{width:88%}.column-89{width:89%}.column-90{width:90%}.column-91{width:91%}.column-92{width:92%}.column-93{width:93%}.column-94{width:94%}.column-95{width:95%}.column-96{width:96%}.column-97{width:97%}.column-98{width:98%}.column-99{width:99%}.column-100{width:100%}.draggable-row-handle{cursor:move;color:#dedede}.draggable-row-handle:hover{color:#333}tr.draggable-item-selected{background:#fff;border:2px solid #666;box-shadow:4px 2px 10px -4px rgba(0,0,0,0.55)}tr.draggable-item-selected td{border-top:none;border-bottom:none}tr.draggable-item-selected td:first-child{border-left:none}tr.draggable-item-selected td:last-child{border-right:none}.table-stripped tr.draggable-item-hover,.table-stripped tr.draggable-item-hover{background:#FEFFF2}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"]:not(.input-addon-field){color:#999;border:1px solid #ccc;width:300px;max-width:95%;font-size:1em;height:25px;padding-bottom:0;font-family:sans-serif;margin-top:10px;-webkit-appearance:none;-moz-appearance:none}input[type="number"]::-webkit-input-placeholder,input[type="date"]::-webkit-input-placeholder,input[type="email"]::-webkit-input-placeholder,input[type="password"]::-webkit-input-placeholder,input[type="text"]:not(.input-addon-field)::-webkit-input-placeholder{color:#dedede}input[type="number"]::-moz-placeholder,input[type="date"]::-moz-placeholder,input[type="email"]::-moz-placeholder,input[type="password"]::-moz-placeholder,input[type="text"]:not(.input-addon-field)::-moz-placeholder{color:#dedede}input[type="number"]:-ms-input-placeholder,input[type="date"]:-ms-input-placeholder,input[type="email"]:-ms-input-placeholder,input[type="password"]:-ms-input-placeholder,input[type="text"]:not(.input-addon-field):-ms-input-placeholder{color:#dedede}input[type="number"]:focus,input[type="date"]:focus,input[type="email"]:focus,input[type="password"]:focus,input[type="text"]: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[type="number"]{width:70px}input[type="text"]:not(.input-addon-field).form-numeric{width:70px}input[type="text"]:not(.input-addon-field).form-datetime,input[type="text"]:not(.input-addon-field).form-date{width:150px}input[type="text"]:not(.input-addon-field).form-input-large{width:400px}input[type="text"]:not(.input-addon-field).form-input-small{width:150px}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)}textarea{padding:3px;border:1px solid #ccc;width:400px;max-width:99%;height:200px;font-family:sans-serif;font-size:1em}textarea::-webkit-input-placeholder{color:#dedede}textarea::-moz-placeholder{color:#dedede}textarea:-ms-input-placeholder{color:#dedede}select{font-size:1.0em;max-width:95%}select:focus{outline:0}select[multiple]{width:300px}.tag-autocomplete{width:400px}span.select2-container{margin-top:2px}.form-actions{padding-top:20px;clear:both}.form-required{color:red;padding-left:5px;font-weight:bold}@media (max-width: 480px){.form-required{display:none}}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-errors{color:#b94a48;list-style-type:none}ul.form-errors li{margin-left:0}.form-help{font-size:0.8em;color:brown;margin-bottom:15px}.form-inline{padding:0;margin:0;border:none}.form-inline label{display:inline}.form-inline input,.form-inline select{margin:0 15px 0 0}.form-inline .form-required{display:none}.form-inline-group{display:inline}.form-columns{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:flex-start;justify-content:flex-start}.form-columns .form-column{margin-right:25px;flex-grow:1}.form-login{max-width:350px;margin:8% auto 0}.form-login li{margin-left:25px;line-height:25px}.form-login h2{margin-bottom:30px;font-weight:bold}.reset-password{margin-top:20px}.reset-password a{color:#999}.input-addon{display:flex}.input-addon-field{flex:1;font-size:1em;color:#999;margin:0;-webkit-appearance:none;-moz-appearance:none}.input-addon-item{background-color:rgba(147,128,108,0.1);color:#666;font:inherit;font-weight:normal}@media (max-width: 480px){.input-addon-item .dropdown .fa-caret-down{display:none}}.input-addon-field,.input-addon-item{border:1px solid rgba(147,128,108,0.25);padding:4px 0.75em}.input-addon-field:not(:first-child),.input-addon-item:not(:first-child){border-left:0}.input-addon-field:first-child,.input-addon-item:first-child{border-radius:5px 0 0 5px}.input-addon-field:last-child,.input-addon-item:last-child{border-radius:0 5px 5px 0}.alert{padding:8px 35px 8px 14px;margin-top:5px;margin-bottom:5px;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}.alert-fade-out{text-align:center;position:fixed;bottom:0;left:20%;width:60%;padding-top:5px;padding-bottom:5px;margin-bottom:0;border-width:1px 0 0;border-radius:4px 4px 0 0;z-index:9999;opacity:1;animation:fadeout 5s linear forwards}@keyframes fadeout{0%{opacity:1}100%{opacity:0}}a.btn{text-decoration:none}.btn{-webkit-appearance:none;-moz-appearance:none;font-size:1.2em;font-weight:normal;cursor:pointer;display:inline-block;border-radius:2px;padding:3px 10px;margin:0;border:1px solid #ddd;background:#f5f5f5;color:#333}.btn:hover,.btn:focus{border-color:#bbb;background:#fafafa;color:#000}.btn-red{border-color:#b0281a;background:#d14836;color:#fff}.btn-red:hover,.btn-red:focus{border-color:#b0281a;background:#c53727;color:#fff}.btn-blue{border-color:#3079ed;background:#4d90fe;color:#fff}.btn-blue:hover,.btn-blue:focus{border-color:#3079ed;background:#357ae8;color:#fff}.btn:disabled{color:#ccc;border-color:#ccc;background:#f7f7f7}.buttons-header{font-size:0.8em;margin-top:5px;margin-bottom:15px}.tooltip-arrow:after{background:#fff;border:1px solid #aaaaaa;box-shadow:0 0 5px #aaa}div.ui-tooltip{min-width:200px;max-width:600px}.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:600px}.ui-tooltip-content .markdown p{margin-bottom:0}.ui-tooltip li{list-style-type:none}.tooltip .fa-info-circle{color:#999}h2 .dropdown ul{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:8px 10px;font-size:0.9em;border-bottom:1px solid #f8f8f8;cursor:pointer}.dropdown-submenu-open li.no-hover{cursor:default}.dropdown-submenu-open li:last-child{border:none}.dropdown-submenu-open li:not(.no-hover):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}.dropdown-menu-link-text,.dropdown-menu-link-icon{color:#333;text-decoration:none}.dropdown-menu-link-text:hover{text-decoration:underline}.accordion-title{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAADCAYAAABS3WWCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NEQ5RDgxQzc2RjQ5MTFFMjhEMUNENzFGRUMwRjhBRTciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NEQ5RDgxQzg2RjQ5MTFFMjhEMUNENzFGRUMwRjhBRTciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0RDlEODFDNTZGNDkxMUUyOEQxQ0Q3MUZFQzBGOEFFNyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0RDlEODFDNjZGNDkxMUUyOEQxQ0Q3MUZFQzBGOEFFNyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvXFWFAAAAAYSURBVHjaYvj//z8D0/Pnz/8zgFgAAQYAS5UJscReGMIAAAAASUVORK5CYII=) repeat-x scroll 0 10px}.accordion-title h3{display:inline;padding-right:5px;background:#fff}.accordion-content{margin-top:15px;margin-bottom:25px}.accordion-toggle{color:#333;text-decoration:none}.accordion-toggle:focus{color:#333}.accordion-toggle:hover{color:#999}.accordion-toggle:before{content:"\f0d7"}.accordion-collapsed{margin-bottom:25px}.accordion-collapsed .accordion-toggle:before{content:"\f0da"}.accordion-collapsed .accordion-content{display:none}#suggest-menu{position:absolute;display:block;z-index:1000;min-width:160px;padding:5px 0;background:#fff;list-style:none;border:1px solid #ccc;border-radius:3px;box-shadow:0 6px 12px rgba(0,0,0,0.175)}.suggest-menu-item{white-space:nowrap;padding:3px 10px;color:#333;font-weight:bold;cursor:pointer}.suggest-menu-item.active{color:#fff;background:#428bca}.suggest-menu-item.active small{color:#fff}.suggest-menu-item small{color:#999;font-weight:normal}#main .confirm{max-width:700px}#popover-container{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.9);overflow:auto;z-index:100}#popover-content{position:fixed;width:950px;max-width:95%;max-height:calc(100% - 50px);top:5%;left:50%;transform:translateX(-50%);padding:0 15px 15px;background:#fff;overflow:auto}#popover-content-header{text-align:right}#popover-close-button{color:#333}#popover-close-button:hover{color:#b94a48}.popover-form{margin-bottom:0}.pagination{text-align:center}.pagination-next{margin-left:5px}.pagination-previous{margin-right:5px}header{box-sizing:border-box;display:flex;flex-wrap:wrap;margin-top:5px;margin-bottom:5px;border-bottom:1px solid #dedede}header>*{box-sizing:border-box}header>*{width:1%}header .menus-container{width:10%}@media (min-width: 768px) and (max-width: 1150px){header .menus-container{width:15%}}@media (max-width: 768px){header .menus-container{width:65%;order:2}}header .board-selector-container{width:15%}@media (min-width: 768px) and (max-width: 1150px){header .board-selector-container{width:20%}}@media (max-width: 768px){header .board-selector-container{width:35%;order:1;margin-bottom:5px}}header .title-container{width:75%}@media (min-width: 768px) and (max-width: 1150px){header .title-container{width:65%}}@media (max-width: 768px){header .title-container{width:100%;order:3}}header h1{font-size:1.5em}header h1 .tooltip{opacity:0.3;font-size:0.7em}.web-notification-icon{color:#36c}.web-notification-icon:focus,.web-notification-icon:hover{color:#000}.logo a{opacity:0.5;color:#d40000;text-decoration:none}.logo span{color:#333}.logo a:hover{opacity:0.8;color:#333}.logo a:focus span,.logo a:hover span{color:#d40000}.page-header{margin-bottom:20px}.page-header .dropdown{padding-right:10px}.page-header h2{margin:0;padding:0;font-weight:bold;border-bottom:1px dotted #ccc}.page-header h2 a{color:#333;text-decoration:none}.page-header h2 a:focus,.page-header h2 a:hover{color:#999}.page-header ul{text-align:left;margin-top:5px;display:inline-block}.page-header li{display:inline;padding-right:15px}@media (max-width: 480px){.page-header li{display:block;line-height:1.5em}}.page-header li.active a{color:#333;text-decoration:none;font-weight:bold}.page-header li.active a:hover,.page-header li.active a:focus{text-decoration:underline}.menu-inline{margin-bottom:5px}.menu-inline li{display:inline;padding-right:15px}.menu-inline li .active a{font-weight:bold;color:#000;text-decoration:none}.sidebar-container{box-sizing:border-box;display:flex;flex-wrap:wrap}.sidebar-container>*{box-sizing:border-box}.sidebar-container>*{width:1%}.sidebar-content{padding-left:10px;width:82%}@media (max-width: 480px){.sidebar-content{width:100%}}.sidebar{max-width:240px;min-width:190px;width:18%}@media (max-width: 480px){.sidebar{width:100%;max-width:99%;min-width:0}}.sidebar h2{margin-top:0}.sidebar>ul a{text-decoration:none;color:#999;font-weight:300}.sidebar>ul a:hover{color:#333}.sidebar>ul li{list-style-type:none;line-height:35px;border-bottom:1px dotted #efefef;padding-left:13px}.sidebar>ul li:hover{border-left:5px solid #555;padding-left:8px}.sidebar>ul li.active{border-left:5px solid #333;padding-left:8px}.sidebar>ul li.active a{color:#333;font-weight:bold}.sidebar-icons>ul li{padding-left:0}.sidebar-icons>ul li:hover,.sidebar-icons>ul li.active{padding-left:0;border-left:none}.sidebar>ul li.active a:focus,.sidebar>ul li.active a:hover{color:#555}.sidebar>ul li:last-child{margin-bottom:15px}.avatar img{vertical-align:bottom}.avatar-left{float:left;margin-right:10px}.avatar-inline{display:inline-block;margin-right:3px}.avatar-48 img,.avatar-48 div{border-radius:30px}.avatar-48 .avatar-letter{line-height:48px;width:48px;font-size:25px}.avatar-20 img,.avatar-20 div{border-radius:10px}.avatar-20 .avatar-letter{line-height:20px;width:20px;font-size:11px}.avatar-letter{color:#fff;text-align:center}#file-dropzone,#screenshot-zone{position:relative;border:2px dashed #ccc;width:99%;height:250px;overflow:auto}#file-dropzone-inner,#screenshot-inner{position:absolute;left:0;bottom:48%;width:100%;text-align:center;color:#aaa}#screenshot-zone.screenshot-pasted{border:2px solid #333}#file-list{margin:20px}#file-list li{list-style-type:none;padding-top:8px;padding-bottom:8px;border-bottom:1px dotted #ddd;width:95%}#file-list li.file-error{font-weight:bold;color:#b94a48}.file-thumbnails{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-justify-content:flex-start;justify-content:flex-start}.file-thumbnail{width:250px;border:1px solid #efefef;border-radius:5px;margin-bottom:20px;box-shadow:4px 2px 10px -6px rgba(0,0,0,0.55);margin-right:15px}.file-thumbnail img{border-top-left-radius:5px;border-top-right-radius:5px}.file-thumbnail img:hover{opacity:0.5}.file-thumbnail-content{padding-left:8px;padding-right:8px}.file-thumbnail-title{font-weight:700;font-size:0.9em;color:#555}.file-thumbnail-description{font-size:0.8em;color:#999;margin-top:8px;margin-bottom:5px}.file-viewer{position:relative}.file-viewer img{max-width:95%;max-height:85%;margin-top:10px}.color-picker{width:180px}.color-picker-option{height:25px}.color-picker-square{display:inline-block;width:18px;height:18px;margin-right:5px;border:1px solid #000}.color-picker-label{display:inline-block;vertical-align:bottom;padding-bottom:3px}.filter-box{max-width:800px}.action-menu{color:#333;text-decoration:none}.action-menu:hover,.action-menu:focus{text-decoration:underline}.project-creation-options{max-width:500px;border-left:3px dotted #efefef;margin-top:20px;padding-left:15px;padding-bottom:5px;padding-top:5px}.project-overview-columns{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;margin-bottom:20px;font-size:1.4em}@media (max-width: 480px){.project-overview-columns{display:block}}.project-overview-column{text-align:center;margin-right:3%;margin-top:5px;padding:3px 15px 3px 15px;border:1px dashed #ddd}@media (max-width: 480px){.project-overview-column{text-align:left}}.project-overview-column small{color:#999}.project-overview-column strong{color:#555;display:block}@media (max-width: 480px){.project-overview-column strong{display:inline}}.project-header{box-sizing:border-box;display:flex;flex-wrap:wrap;margin-bottom:8px}.project-header>*{box-sizing:border-box}.project-header>*{width:1%}.project-header .dropdown-component{margin-top:4px;width:5%}@media (min-width: 768px) and (max-width: 1150px){.project-header .dropdown-component{width:8%}}@media (max-width: 768px){.project-header .dropdown-component{width:100%}}.project-header .views-switcher-component{margin-top:4px;width:38%}@media (max-width: 1300px){.project-header .views-switcher-component{width:45%}}@media (min-width: 768px) and (max-width: 1150px){.project-header .views-switcher-component{width:92%}}@media (max-width: 768px){.project-header .views-switcher-component{margin-top:0;width:100%}}.project-header .filter-box-component{margin:0;width:55%}@media (max-width: 1300px){.project-header .filter-box-component{width:50%}}@media (min-width: 768px) and (max-width: 1150px){.project-header .filter-box-component{width:100%;margin-top:10px}.project-header .filter-box-component .filter-box{max-width:100%}}@media (max-width: 768px){.project-header .filter-box-component{width:100%;margin-top:10px}.project-header .filter-box-component .filter-box{max-width:100%}}.project-header .filter-box-component form{margin:0}.views{display:inline-block;margin-right:10px;font-size:0.9em}@media (max-width: 560px){.views{width:100%}}@media (max-width: 768px){.views{margin-top:10px;font-size:1em}}@media (max-width: 480px){.views{margin-top:5px}}.views li{white-space:nowrap;background:#fafafa;border:1px solid #ddd;border-right:none;padding:4px 8px;display:inline}@media (max-width: 560px){.views li{display:block;margin-top:5px;border-radius:5px;border:1px solid #ddd}}.views li.active a{font-weight:bold;color:#000;text-decoration:none}.views li:first-child{border-top-left-radius:5px;border-bottom-left-radius:5px}.views li:last-child{border-right:1px solid #ddd;border-top-right-radius:5px;border-bottom-right-radius:5px}.views a{color:#555;text-decoration:none}.views a:hover{color:#333;text-decoration:underline}.dashboard-project-stats small{margin-right:10px;color:#999}.dashboard-table-link{font-weight:bold;color:#000;text-decoration:none}.dashboard-table-link:focus,.dashboard-table-link:hover{color:#999}.public-board{margin-top:5px}.public-task{max-width:800px;margin:5px auto 0}#board-container{overflow-x:auto}#board{table-layout:fixed;margin-bottom:0}#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 .dropdown-menu{text-decoration:none}.board-add-icon{float:left;padding:0 5px}.board-add-icon a{text-decoration:none;color:#36c;font-size:1.6em;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}a.board-swimlane-toggle{text-decoration:none}a.board-swimlane-toggle:hover,a.board-swimlane-toggle:focus{color:#000;text-decoration:none;border:none}.board-task-list{min-height:60px}.board-task-list-limit{background-color:#DF5353}.draggable-item{cursor:pointer;user-select:none;-webkit-user-select:none;-moz-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;word-wrap:break-word;font-size:0.9em}div.task-board-recent{border-width:2px}div.task-board-status-closed{user-select:none;border:1px dotted #555}.task-board a{color:#000;text-decoration:none}.task-board .dropdown-menu{font-weight:bold}.task-board .task-score{font-weight:bold}.task-board-collapsed{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.task-board-title{margin-top:5px;margin-bottom:8px}.task-board-title a:hover{text-decoration:underline}.task-board-saving-state{opacity:0.3}.task-board-saving-icon{position:absolute;margin:auto;width:100%;text-align:center;color:#000}.task-board-category-container{text-align:right;margin-top:8px;margin-bottom:8px}.task-board-category{font-weight:500;color:#000;border:1px solid #555;padding:1px 2px 1px 2px;border-radius:4px}.task-board-category:hover{opacity:0.6}.task-board-avatars{text-align:right;float:right}.task-board-change-assignee{cursor:pointer}.task-board-change-assignee:hover{opacity:0.6}.task-board-icons{font-size:0.8em;text-align:right;margin-top:4px;margin-bottom:2px}.task-board-icons a{opacity:0.5}.task-board-icons span{opacity:0.5;margin-left:2px}.task-board-icons a:hover,.task-board-icons span:hover{opacity:1.0}.flag-milestone{color:green}.task-board-age{display:inline-block}span.task-board-age-total{border:#666 1px solid;padding:1px 3px 1px 3px;border-top-left-radius:3px;border-bottom-left-radius:3px}span.task-board-age-column{border:#666 1px solid;border-left:none;margin-left:-5px;padding:1px 3px 1px 3px;border-top-right-radius:3px;border-bottom-right-radius:3px}.task-board-date{font-weight:bold;color:#000}span.task-board-date-today{opacity:1.0;color:#36c}span.task-board-date-overdue{opacity:1.0;color:#b94a48}.task-tags li{display:inline-block;margin:3px 3px 0 0;padding:1px 3px 1px 3px;color:#333;border:1px solid #333;border-radius:4px}.task-summary-container .task-tags{margin-top:10px}#task-summary{margin-bottom:15px}#task-summary h2{color:#555;font-size:1.6em;margin-top:0;padding-top:0}.task-summary-container{border:2px solid #000;border-radius:8px;padding:15px}.task-summary-columns{display:-webkit-flex;display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:space-between;justify-content:space-between}@media (max-width: 480px){.task-summary-columns{display:block}}.task-summary-column{color:#333}.task-summary-column span{color:#555}.task-summary-column li{line-height:23px}#external-task-view{padding:10px;margin-top:10px;margin-bottom:10px;border:1px dotted #ccc}.task-table .dropdown-menu{color:#000;text-decoration:none;font-weight:bold}.task-table .dropdown-menu:focus,.task-table .dropdown-menu:hover{text-decoration:underline}td.task-table a{color:#000;text-decoration:none}td.task-table a:hover{text-decoration:underline}.comment-sorting{text-align:right}.comment-sorting a{color:#555;font-weight:normal;text-decoration:none}.comment-sorting a:hover{color:#999}.comment{padding:5px;margin-bottom:15px}.comment:hover{background:#fafafa}.comment-title{border-bottom:1px dotted #eee;margin-left:55px;margin-bottom:10px}.comment-date{color:#999;font-weight:200}.comment-actions{font-size:0.8em;margin-left:55px;margin-top:8px}.comment-actions li{display:inline}.comment-actions a{color:#999;text-decoration:none}.comment-actions a:focus,.comment-actions a:hover{color:#333;text-decoration:underline}.comment-content{margin-left:55px}.subtasks-table td{vertical-align:middle}.task-links-table td{vertical-align:middle}.task-links-task-count{color:#999}.task-link-closed{text-decoration:line-through}.text-editor a{font-size:1em;color:#999;text-decoration:none;margin-right:10px}.text-editor a:hover{color:#36c}.text-editor .text-editor-preview-area{border:1px solid #dedede;width:400px;height:200px;overflow:auto;padding:2px}.markdown{line-height:1.4em}.markdown h1{margin-top:5px;margin-bottom:10px;font-weight:bold}.markdown h2{font-weight:bold}.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:#555}.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;color:#555}.documentation img{border:1px solid #333}.documentation h1{text-decoration:none;margin-bottom:30px}.documentation h2{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:#fcfcfc;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:15px;padding:10px}.activity-event:hover{background:#fafafa}.activity-date{margin-left:10px;font-weight:normal;color:#999}.activity-content{margin-left:55px}.activity-title{font-weight:bold;color:#000;border-bottom:1px dotted #efefef}.activity-description{color:#555;margin-top:10px}@media (max-width: 480px){.activity-description{overflow:auto}}.activity-description li{list-style-type:circle}.activity-description ul{margin-top:10px;margin-left:20px}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:none}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:#555}div.ganttview-vtheader{margin-top:41px;width:400px;overflow:hidden;background-color:#fff}div.ganttview-vtheader-item{color:#555}div.ganttview-vtheader-series-name{width:400px;height:31px;line-height:31px;padding-left:3px;border-top:1px solid #d0d0d0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}div.ganttview-vtheader-series-name a{color:#555;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:#555}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 #c0c0c0;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:0.7em;color:#999;padding:2px 3px}div.ganttview-block div.ui-resizable-handle.ui-resizable-s{bottom:-0}.user-mention-link{font-weight:bold;color:#000;text-decoration:none}.user-mention-link:hover{color:#555} diff --git a/assets/js/app.min.js b/assets/js/app.min.js index 576f3971..8b73db8c 100644 --- a/assets/js/app.min.js +++ b/assets/js/app.min.js @@ -1,2 +1,2 @@ -"use strict";var Kanboard={},KB={components:{},utils:{}};KB.component=function(t,e){this.components[t]=e},KB.render=function(){for(var t in this.components)for(var e=document.querySelectorAll(".js-"+t),o=0;o<e.length;o++){var a=this.components[t],n=new a(e[o],JSON.parse(e[o].dataset.params));n.render(),e[o].className=e[o].className+"-rendered"}},KB.el=function(t){function e(t){var e="string"==typeof t?document.createElement(t):t;this.attr=function(t,o){return null!==o&&e.setAttribute(t,o),this},this.hide=function(){return e.style.display="none",this},this.show=function(){return e.style.display="block",this},this.toggle=function(){return"none"===e.style.display?this.show():this.hide(),this},this.click=function(t){return e.onclick=function(e){e.preventDefault(),t()},this},this.add=function(t){return e.appendChild(t),this},this.html=function(t){return e.innerHTML=t,this},this.text=function(t){return e.appendChild(document.createTextNode(t)),this},this["for"]=function(t,o){for(var a=0;a<o.length;a++){var n=o[a];if("object"!=typeof n)e.appendChild(KB.el(t).text(n).build());else{var i=KB.el(t);for(var r in n)r in this&&"function"==typeof this[r]?i[r](n[r]):i.attr(r,n[r]);e.appendChild(i.build())}}return this},this.build=function(){return e}}return new e(t)},KB.utils.formatDuration=function(t){return t>=86400?Math.round(t/86400)+"d":t>=3600?Math.round(t/3600)+"h":t>=60?Math.round(t/60)+"m":t+"s"},Kanboard.Accordion=function(t){this.app=t},Kanboard.Accordion.prototype.listen=function(){$(document).on("click",".accordion-toggle",function(t){var e=$(this).parents(".accordion-section");t.preventDefault(),e.hasClass("accordion-collapsed")?(e.find(".accordion-content").show(),e.removeClass("accordion-collapsed")):(e.find(".accordion-content").hide(),e.addClass("accordion-collapsed"))})},Kanboard.App=function(){this.controllers={}},Kanboard.App.prototype.get=function(t){return this.controllers[t]},Kanboard.App.prototype.execute=function(){for(var t in Kanboard)if("App"!==t){var e=new Kanboard[t](this);this.controllers[t]=e,"function"==typeof e.execute&&e.execute(),"function"==typeof e.listen&&e.listen(),"function"==typeof e.focus&&e.focus(),"function"==typeof e.keyboardShortcuts&&e.keyboardShortcuts()}this.focus(),this.chosen(),this.keyboardShortcuts(),this.datePicker(),this.autoComplete(),this.tagAutoComplete()},Kanboard.App.prototype.keyboardShortcuts=function(){var t=this;Mousetrap.bindGlobal("mod+enter",function(){var e=$("form");1==e.length?e.submit():e.length>1&&("INPUT"===document.activeElement.tagName||"TEXTAREA"===document.activeElement.tagName?$(document.activeElement).parents("form").submit():t.get("Popover").isOpen()&&$("#popover-container form").submit())}),Mousetrap.bind("b",function(t){t.preventDefault(),$("#board-selector").trigger("chosen:open")}),Mousetrap.bindGlobal("esc",function(){t.get("Popover").close(),t.get("Dropdown").close()}),Mousetrap.bind("?",function(){t.get("Popover").open($("body").data("keyboard-shortcut-url"))})},Kanboard.App.prototype.focus=function(){$(document).on("focus",".auto-select",function(){$(this).select()}),$(document).on("mouseup",".auto-select",function(t){t.preventDefault()})},Kanboard.App.prototype.chosen=function(){$(".chosen-select").each(function(){var t=$(this).data("search-threshold");void 0===t&&(t=10),$(this).chosen({width:"180px",no_results_text:$(this).data("notfound"),disable_search_threshold:t})}),$(".select-auto-redirect").change(function(){var t=new RegExp($(this).data("redirect-regex"),"g");window.location=$(this).data("redirect-url").replace(t,$(this).val())})},Kanboard.App.prototype.datePicker=function(){var t=$("body"),e=t.data("js-date-format"),o=t.data("js-time-format"),a=t.data("js-lang");$.datepicker.setDefaults($.datepicker.regional[a]),$.timepicker.setDefaults($.timepicker.regional[a]),$(".form-date").datepicker({showOtherMonths:!0,selectOtherMonths:!0,dateFormat:e,constrainInput:!1}),$(".form-datetime").datetimepicker({dateFormat:e,timeFormat:o,constrainInput:!1})},Kanboard.App.prototype.tagAutoComplete=function(){$(".tag-autocomplete").select2({tags:!0})},Kanboard.App.prototype.autoComplete=function(){$(".autocomplete").each(function(){var t=$(this),e=t.data("dst-field"),o=t.data("dst-extra-field");""==$("#form-"+e).val()&&t.parent().find("button[type=submit]").attr("disabled","disabled"),t.autocomplete({source:t.data("search-url"),minLength:1,select:function(a,n){$("input[name="+e+"]").val(n.item.id),o&&$("input[name="+o+"]").val(n.item[o]),t.parent().find("button[type=submit]").removeAttr("disabled")}})})},Kanboard.App.prototype.hasId=function(t){return!!document.getElementById(t)},Kanboard.App.prototype.showLoadingIcon=function(){$("body").append('<span id="app-loading-icon"> <i class="fa fa-spinner fa-spin"></i></span>')},Kanboard.App.prototype.hideLoadingIcon=function(){$("#app-loading-icon").remove()},Kanboard.App.prototype.isVisible=function(){var t="";return"undefined"!=typeof document.hidden?t="visibilityState":"undefined"!=typeof document.mozHidden?t="mozVisibilityState":"undefined"!=typeof document.msHidden?t="msVisibilityState":"undefined"!=typeof document.webkitHidden&&(t="webkitVisibilityState"),""==t||"visible"==document[t]},Kanboard.BoardCollapsedMode=function(t){this.app=t},Kanboard.BoardCollapsedMode.prototype.keyboardShortcuts=function(){var t=this;t.app.hasId("board")&&Mousetrap.bind("s",function(){t.toggle()})},Kanboard.BoardCollapsedMode.prototype.toggle=function(){var t=this;this.app.showLoadingIcon(),$.ajax({cache:!1,url:$('.filter-display-mode:not([style="display: none;"]) a').attr("href"),success:function(e){$(".filter-display-mode").toggle(),t.app.get("BoardDragAndDrop").refresh(e)}})},Kanboard.BoardColumnView=function(t){this.app=t},Kanboard.BoardColumnView.prototype.execute=function(){this.app.hasId("board")&&this.render()},Kanboard.BoardColumnView.prototype.listen=function(){var t=this;$(document).on("click",".board-toggle-column-view",function(){t.toggle($(this).data("column-id"))})},Kanboard.BoardColumnView.prototype.onBoardRendered=function(){this.render()},Kanboard.BoardColumnView.prototype.render=function(){var t=this;$(".board-column-header").each(function(){var e=$(this).data("column-id");localStorage.getItem("hidden_column_"+e)&&t.hideColumn(e)})},Kanboard.BoardColumnView.prototype.toggle=function(t){localStorage.getItem("hidden_column_"+t)?this.showColumn(t):this.hideColumn(t)},Kanboard.BoardColumnView.prototype.hideColumn=function(t){$(".board-column-"+t+" .board-column-expanded").hide(),$(".board-column-"+t+" .board-column-collapsed").show(),$(".board-column-header-"+t+" .board-column-expanded").hide(),$(".board-column-header-"+t+" .board-column-collapsed").show(),$(".board-column-header-"+t).each(function(){$(this).removeClass("board-column-compact"),$(this).addClass("board-column-header-collapsed")}),$(".board-column-"+t).each(function(){$(this).addClass("board-column-task-collapsed")}),$(".board-column-"+t+" .board-rotation").each(function(){$(this).css("width",$(".board-column-"+t).height())}),localStorage.setItem("hidden_column_"+t,1)},Kanboard.BoardColumnView.prototype.showColumn=function(t){$(".board-column-"+t+" .board-column-expanded").show(),$(".board-column-"+t+" .board-column-collapsed").hide(),$(".board-column-header-"+t+" .board-column-expanded").show(),$(".board-column-header-"+t+" .board-column-collapsed").hide(),$(".board-column-header-"+t).removeClass("board-column-header-collapsed"),$(".board-column-"+t).removeClass("board-column-task-collapsed"),0==localStorage.getItem("horizontal_scroll")&&$(".board-column-header-"+t).addClass("board-column-compact"),localStorage.removeItem("hidden_column_"+t)},Kanboard.BoardHorizontalScrolling=function(t){this.app=t},Kanboard.BoardHorizontalScrolling.prototype.execute=function(){this.app.hasId("board")&&this.render()},Kanboard.BoardHorizontalScrolling.prototype.listen=function(){var t=this;$(document).on("click",".filter-toggle-scrolling",function(e){e.preventDefault(),t.toggle()})},Kanboard.BoardHorizontalScrolling.prototype.keyboardShortcuts=function(){var t=this;t.app.hasId("board")&&Mousetrap.bind("c",function(){t.toggle()})},Kanboard.BoardHorizontalScrolling.prototype.onBoardRendered=function(){this.render()},Kanboard.BoardHorizontalScrolling.prototype.toggle=function(){var t=localStorage.getItem("horizontal_scroll")||1;localStorage.setItem("horizontal_scroll",0==t?1:0),this.render()},Kanboard.BoardHorizontalScrolling.prototype.render=function(){0==localStorage.getItem("horizontal_scroll")?($(".filter-wide").show(),$(".filter-compact").hide(),$("#board-container").addClass("board-container-compact"),$("#board th:not(.board-column-header-collapsed)").addClass("board-column-compact")):($(".filter-wide").hide(),$(".filter-compact").show(),$("#board-container").removeClass("board-container-compact"),$("#board th").removeClass("board-column-compact"))},Kanboard.BoardPolling=function(t){this.app=t},Kanboard.BoardPolling.prototype.execute=function(){if(this.app.hasId("board")){var t=parseInt($("#board").attr("data-check-interval"));t>0&&window.setInterval(this.check.bind(this),1e3*t)}},Kanboard.BoardPolling.prototype.check=function(){if(this.app.isVisible()&&!this.app.get("BoardDragAndDrop").savingInProgress){var t=this;this.app.showLoadingIcon(),$.ajax({cache:!1,url:$("#board").data("check-url"),statusCode:{200:function(e){t.app.get("BoardDragAndDrop").refresh(e)},304:function(){t.app.hideLoadingIcon()}}})}},Kanboard.BoardTask=function(t){this.app=t},Kanboard.BoardTask.prototype.listen=function(){var t=this;$(document).on("click",".task-board-change-assignee",function(e){e.preventDefault(),e.stopPropagation(),t.app.get("Popover").open($(this).data("url"))}),$(document).on("click",".task-board",function(t){"A"!=t.target.tagName&&"IMG"!=t.target.tagName&&(window.location=$(this).data("task-url"))})},Kanboard.BoardTask.prototype.keyboardShortcuts=function(){var t=this;t.app.hasId("board")&&Mousetrap.bind("n",function(){t.app.get("Popover").open($("#board").data("task-creation-url"))})},Kanboard.Column=function(t){this.app=t},Kanboard.Column.prototype.listen=function(){this.dragAndDrop()},Kanboard.Column.prototype.dragAndDrop=function(){var t=this;$(".draggable-row-handle").mouseenter(function(){$(this).parent().parent().addClass("draggable-item-hover")}).mouseleave(function(){$(this).parent().parent().removeClass("draggable-item-hover")}),$(".columns-table tbody").sortable({forcePlaceholderSize:!0,handle:"td:first i",helper:function(t,e){return e.children().each(function(){$(this).width($(this).width())}),e},stop:function(e,o){var a=o.item;a.removeClass("draggable-item-selected"),t.savePosition(a.data("column-id"),a.index()+1)},start:function(t,e){e.item.addClass("draggable-item-selected")}}).disableSelection()},Kanboard.Column.prototype.savePosition=function(t,e){var o=$(".columns-table").data("save-position-url"),a=this;this.app.showLoadingIcon(),$.ajax({cache:!1,url:o,contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({column_id:t,position:e}),complete:function(){a.app.hideLoadingIcon()}})},Kanboard.Dropdown=function(t){this.app=t},Kanboard.Dropdown.prototype.listen=function(){var t=this;$(document).on("click",function(){t.close()}),$(document).on("click","#popover-content",function(){t.close()}),$(document).on("click",".dropdown-menu",function(e){e.preventDefault(),e.stopImmediatePropagation(),t.close();var o=$(this).next("ul"),a=$(this).offset();$("body").append(jQuery("<div>",{id:"dropdown"})),o.clone().appendTo("#dropdown");var n=$("#dropdown ul");n.addClass("dropdown-submenu-open");var i=n.outerHeight(),r=n.outerWidth();a.top+i-$(window).scrollTop()<$(window).height()||$(window).scrollTop()+a.top<i?n.css("top",a.top+$(this).height()):n.css("top",a.top-i-5),a.left+r>$(window).width()?n.css("left",a.left-r+$(this).outerWidth()):n.css("left",a.left)}),$(document).on("click",".dropdown-submenu-open li",function(t){$(t.target).is("li")&&$(this).find("a:visible")[0].click()})},Kanboard.Dropdown.prototype.close=function(){$("#dropdown").remove()},Kanboard.Dropdown.prototype.onPopoverOpened=function(){this.close()},Kanboard.FileUpload=function(t){this.app=t,this.files=[],this.currentFile=0},Kanboard.FileUpload.prototype.onPopoverOpened=function(){var t=document.getElementById("file-dropzone"),e=this;t&&(t.ondragover=t.ondragenter=function(t){t.stopPropagation(),t.preventDefault()},t.ondrop=function(t){t.stopPropagation(),t.preventDefault(),e.files=t.dataTransfer.files,e.show(),$("#file-error-max-size").hide()},$(document).on("click","#file-browser",function(t){t.preventDefault(),$("#file-form-element").get(0).click()}),$(document).on("click","#file-upload-button",function(t){t.preventDefault(),e.currentFile=0,e.checkFiles()}),$("#file-form-element").change(function(){e.files=document.getElementById("file-form-element").files,e.show(),$("#file-error-max-size").hide()}))},Kanboard.FileUpload.prototype.show=function(){if($("#file-list").remove(),this.files.length>0){$("#file-upload-button").prop("disabled",!1),$("#file-dropzone-inner").hide();for(var t=jQuery("<ul>",{id:"file-list"}),e=0;e<this.files.length;e++){var o=jQuery("<span>",{id:"file-percentage-"+e}).append("(0%)"),a=jQuery("<progress>",{id:"file-progress-"+e,value:0}),n=jQuery("<li>",{id:"file-label-"+e}).append(a).append(" ").append(this.files[e].name).append(" ").append(o);t.append(n)}$("#file-dropzone").append(t)}else $("#file-dropzone-inner").show()},Kanboard.FileUpload.prototype.checkFiles=function(){for(var t=parseInt($("#file-dropzone").data("max-size")),e=0;e<this.files.length;e++)if(this.files[e].size>t)return $("#file-error-max-size").show(),$("#file-label-"+e).addClass("file-error"),void $("#file-upload-button").prop("disabled",!0);this.uploadFiles()},Kanboard.FileUpload.prototype.uploadFiles=function(){this.files.length>0&&this.uploadFile(this.files[this.currentFile])},Kanboard.FileUpload.prototype.uploadFile=function(t){var e=document.getElementById("file-dropzone"),o=e.dataset.url,a=new XMLHttpRequest,n=new FormData;a.upload.addEventListener("progress",this.updateProgress.bind(this)),a.upload.addEventListener("load",this.transferComplete.bind(this)),a.open("POST",o,!0),n.append("files[]",t),a.send(n)},Kanboard.FileUpload.prototype.updateProgress=function(t){t.lengthComputable&&($("#file-progress-"+this.currentFile).val(t.loaded/t.total),$("#file-percentage-"+this.currentFile).text("("+Math.floor(t.loaded/t.total*100)+"%)"))},Kanboard.FileUpload.prototype.transferComplete=function(){if(this.currentFile++,this.currentFile<this.files.length)this.uploadFile(this.files[this.currentFile]);else{var t=$("#file-upload-button");t.prop("disabled",!0),t.parent().hide(),$("#file-done").show()}},Kanboard.Gantt=function(t){this.app=t,this.data=[],this.options={container:"#gantt-chart",showWeekends:!0,allowMoves:!0,allowResizes:!0,cellWidth:21,cellHeight:31,slideWidth:1e3,vHeaderWidth:200}},Kanboard.Gantt.prototype.execute=function(){this.app.hasId("gantt-chart")&&this.show()},Kanboard.Gantt.prototype.saveRecord=function(t){this.app.showLoadingIcon(),$.ajax({cache:!1,url:$(this.options.container).data("save-url"),contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify(t),complete:this.app.hideLoadingIcon.bind(this)})},Kanboard.Gantt.prototype.show=function(){this.data=this.prepareData($(this.options.container).data("records"));var t=Math.floor(this.options.slideWidth/this.options.cellWidth+5),e=this.getDateRange(t),o=e[0],a=e[1],n=$(this.options.container),i=jQuery("<div>",{"class":"ganttview"});i.append(this.renderVerticalHeader()),i.append(this.renderSlider(o,a)),n.append(i),jQuery("div.ganttview-grid-row div.ganttview-grid-row-cell:last-child",n).addClass("last"),jQuery("div.ganttview-hzheader-days div.ganttview-hzheader-day:last-child",n).addClass("last"),jQuery("div.ganttview-hzheader-months div.ganttview-hzheader-month:last-child",n).addClass("last"),$(this.options.container).data("readonly")?(this.options.allowResizes=!1,this.options.allowMoves=!1):(this.listenForBlockResize(o),this.listenForBlockMove(o))},Kanboard.Gantt.prototype.renderVerticalHeader=function(){for(var t=jQuery("<div>",{"class":"ganttview-vtheader"}),e=jQuery("<div>",{"class":"ganttview-vtheader-item"}),o=jQuery("<div>",{"class":"ganttview-vtheader-series"}),a=0;a<this.data.length;a++){var n=jQuery("<span>").append(jQuery("<i>",{"class":"fa fa-info-circle tooltip",title:this.getVerticalHeaderTooltip(this.data[a])})).append(" ");"task"==this.data[a].type?n.append(jQuery("<a>",{href:this.data[a].link,title:this.data[a].title}).append(this.data[a].title)):n.append(jQuery("<a>",{href:this.data[a].board_link,title:$(this.options.container).data("label-board-link")}).append('<i class="fa fa-th"></i>')).append(" ").append(jQuery("<a>",{href:this.data[a].gantt_link,title:$(this.options.container).data("label-gantt-link")}).append('<i class="fa fa-sliders"></i>')).append(" ").append(jQuery("<a>",{href:this.data[a].link}).append(this.data[a].title)),o.append(jQuery("<div>",{"class":"ganttview-vtheader-series-name"}).append(n))}return e.append(o),t.append(e),t},Kanboard.Gantt.prototype.renderSlider=function(t,e){var o=jQuery("<div>",{"class":"ganttview-slide-container"}),a=this.getDates(t,e);return o.append(this.renderHorizontalHeader(a)),o.append(this.renderGrid(a)),o.append(this.addBlockContainers()),this.addBlocks(o,t),o},Kanboard.Gantt.prototype.renderHorizontalHeader=function(t){var e=jQuery("<div>",{"class":"ganttview-hzheader"}),o=jQuery("<div>",{"class":"ganttview-hzheader-months"}),a=jQuery("<div>",{"class":"ganttview-hzheader-days"}),n=0;for(var i in t)for(var r in t[i]){var s=t[i][r].length*this.options.cellWidth;n+=s,o.append(jQuery("<div>",{"class":"ganttview-hzheader-month",css:{width:s-1+"px"}}).append($.datepicker.regional[$("body").data("js-lang")].monthNames[r]+" "+i));for(var d in t[i][r])a.append(jQuery("<div>",{"class":"ganttview-hzheader-day"}).append(t[i][r][d].getDate()))}return o.css("width",n+"px"),a.css("width",n+"px"),e.append(o).append(a),e},Kanboard.Gantt.prototype.renderGrid=function(t){var e=jQuery("<div>",{"class":"ganttview-grid"}),o=jQuery("<div>",{"class":"ganttview-grid-row"});for(var a in t)for(var n in t[a])for(var i in t[a][n]){var r=jQuery("<div>",{"class":"ganttview-grid-row-cell"});this.options.showWeekends&&this.isWeekend(t[a][n][i])&&r.addClass("ganttview-weekend"),o.append(r)}var s=jQuery("div.ganttview-grid-row-cell",o).length*this.options.cellWidth;o.css("width",s+"px"),e.css("width",s+"px");for(var d=0;d<this.data.length;d++)e.append(o.clone());return e},Kanboard.Gantt.prototype.addBlockContainers=function(){for(var t=jQuery("<div>",{"class":"ganttview-blocks"}),e=0;e<this.data.length;e++)t.append(jQuery("<div>",{"class":"ganttview-block-container"}));return t},Kanboard.Gantt.prototype.addBlocks=function(t,e){for(var o=jQuery("div.ganttview-blocks div.ganttview-block-container",t),a=0,n=0;n<this.data.length;n++){var i=this.data[n],r=this.daysBetween(i.start,i.end)+1,s=this.daysBetween(e,i.start),d=jQuery("<div>",{"class":"ganttview-block-text"}),l=jQuery("<div>",{"class":"ganttview-block tooltip"+(this.options.allowMoves?" ganttview-block-movable":""),title:this.getBarTooltip(i),css:{width:r*this.options.cellWidth-9+"px","margin-left":s*this.options.cellWidth+"px"}}).append(d);r>=2&&d.append(i.progress),l.data("record",i),this.setBarColor(l,i),jQuery(o[a]).append(l),a+=1}},Kanboard.Gantt.prototype.getVerticalHeaderTooltip=function(t){var e="";if("task"==t.type)e="<strong>"+t.column_title+"</strong> ("+t.progress+")<br/>"+t.title;else{var o=["project-manager","project-member"];for(var a in o){var n=o[a];if(!jQuery.isEmptyObject(t.users[n])){var i=jQuery("<ul>");for(var r in t.users[n])r&&i.append(jQuery("<li>").append(t.users[n][r]));e+="<p><strong>"+$(this.options.container).data("label-"+n)+"</strong></p>"+i[0].outerHTML}}}return e},Kanboard.Gantt.prototype.getBarTooltip=function(t){var e="";return t.not_defined?e=$(this.options.container).data("label-not-defined"):("task"==t.type&&(e="<strong>"+t.progress+"</strong><br/>"+$(this.options.container).data("label-assignee")+" "+(t.assignee?t.assignee:"")+"<br/>"),e+=$(this.options.container).data("label-start-date")+" "+$.datepicker.formatDate("yy-mm-dd",t.start)+"<br/>",e+=$(this.options.container).data("label-end-date")+" "+$.datepicker.formatDate("yy-mm-dd",t.end)),e},Kanboard.Gantt.prototype.setBarColor=function(t,e){e.not_defined?t.addClass("ganttview-block-not-defined"):(t.css("background-color",e.color.background),t.css("border-color",e.color.border),"0%"!=e.progress&&t.append(jQuery("<div>",{css:{"z-index":0,position:"absolute",top:0,bottom:0,"background-color":e.color.border,width:e.progress,opacity:.4}})))},Kanboard.Gantt.prototype.listenForBlockResize=function(t){var e=this;jQuery("div.ganttview-block",this.options.container).resizable({grid:this.options.cellWidth,handles:"e,w",delay:300,stop:function(){var o=jQuery(this);e.updateDataAndPosition(o,t),e.saveRecord(o.data("record"))}})},Kanboard.Gantt.prototype.listenForBlockMove=function(t){var e=this;jQuery("div.ganttview-block",this.options.container).draggable({axis:"x",delay:300,grid:[this.options.cellWidth,this.options.cellWidth],stop:function(){var o=jQuery(this);e.updateDataAndPosition(o,t),e.saveRecord(o.data("record"))}})},Kanboard.Gantt.prototype.updateDataAndPosition=function(t,e){var o=jQuery("div.ganttview-slide-container",this.options.container),a=o.scrollLeft(),n=t.offset().left-o.offset().left-1+a,i=t.data("record");i.not_defined=!1,this.setBarColor(t,i);var r=Math.round(n/this.options.cellWidth),s=this.addDays(this.cloneDate(e),r);i.start=s;var d=t.outerWidth(),l=Math.round(d/this.options.cellWidth)-1;i.end=this.addDays(this.cloneDate(s),l),"task"===i.type&&l>0&&jQuery("div.ganttview-block-text",t).text(i.progress),t.attr("title",this.getBarTooltip(i)),t.data("record",i),t.css("top","").css("left","").css("position","relative").css("margin-left",n+"px")},Kanboard.Gantt.prototype.getDates=function(t,e){var o=[];o[t.getFullYear()]=[],o[t.getFullYear()][t.getMonth()]=[t];for(var a=t;this.compareDate(a,e)==-1;){var n=this.addDays(this.cloneDate(a),1);o[n.getFullYear()]||(o[n.getFullYear()]=[]),o[n.getFullYear()][n.getMonth()]||(o[n.getFullYear()][n.getMonth()]=[]),o[n.getFullYear()][n.getMonth()].push(n),a=n}return o},Kanboard.Gantt.prototype.prepareData=function(t){for(var e=0;e<t.length;e++){var o=new Date(t[e].start[0],t[e].start[1]-1,t[e].start[2],0,0,0,0);t[e].start=o;var a=new Date(t[e].end[0],t[e].end[1]-1,t[e].end[2],0,0,0,0);t[e].end=a}return t},Kanboard.Gantt.prototype.getDateRange=function(t){for(var e=new Date,o=new Date,a=0;a<this.data.length;a++){var n=new Date;n.setTime(Date.parse(this.data[a].start));var i=new Date;i.setTime(Date.parse(this.data[a].end)),0==a&&(e=n,o=i),1==this.compareDate(e,n)&&(e=n),this.compareDate(o,i)==-1&&(o=i)}return this.daysBetween(e,o)<t&&(o=this.addDays(this.cloneDate(e),t)),e.setDate(e.getDate()-1),[e,o]},Kanboard.Gantt.prototype.daysBetween=function(t,e){if(!t||!e)return 0;for(var o=0,a=this.cloneDate(t);this.compareDate(a,e)==-1;)o+=1,this.addDays(a,1);return o},Kanboard.Gantt.prototype.isWeekend=function(t){return t.getDay()%6==0},Kanboard.Gantt.prototype.cloneDate=function(t){return new Date(t.getTime())},Kanboard.Gantt.prototype.addDays=function(t,e){return t.setDate(t.getDate()+1*e),t},Kanboard.Gantt.prototype.compareDate=function(t,e){if(isNaN(t)||isNaN(e))throw new Error(t+" - "+e);if(t instanceof Date&&e instanceof Date)return t<e?-1:t>e?1:0;throw new TypeError(t+" - "+e)},Kanboard.Notification=function(t){this.app=t},Kanboard.Notification.prototype.execute=function(){$(".alert-fade-out").delay(4e3).fadeOut(800,function(){$(this).remove()})},Kanboard.Popover=function(t){this.app=t},Kanboard.Popover.prototype.listen=function(){var t=this;$(document).on("click",".popover",function(e){t.onClick(e)}),$(document).on("click",".close-popover",function(e){t.close(e)}),$(document).on("click","#popover-close-button",function(e){t.close(e)}),$(document).on("click","#popover-content",function(t){t.stopPropagation()})},Kanboard.Popover.prototype.onClick=function(t){t.preventDefault(),t.stopPropagation();var e=t.currentTarget||t.target,o=e.getAttribute("href");o||(o=e.getAttribute("data-href")),o&&this.open(o)},Kanboard.Popover.prototype.isOpen=function(){return $("#popover-container").size()>0},Kanboard.Popover.prototype.open=function(t){var e=this;e.isOpen()||$.get(t,function(t){$("body").prepend('<div id="popover-container"><div id="popover-content"><div id="popover-content-header"><a href="#" id="popover-close-button"><i class="fa fa-times"></i></a></div>'+t+"</div></div>"),e.executeOnOpenedListeners()})},Kanboard.Popover.prototype.close=function(t){this.isOpen()&&(t&&t.preventDefault(),$("#popover-container").remove(),this.executeOnClosedListeners())},Kanboard.Popover.prototype.ajaxReload=function(t,e,o){var a=e.getResponseHeader("X-Ajax-Redirect");"self"===a?window.location.reload():a&&a.indexOf("#")>-1?window.location=a.split("#")[0]:a?window.location=a:($("#popover-content").html(t),$("#popover-content input[autofocus]").focus(),o.executeOnOpenedListeners())},Kanboard.Popover.prototype.executeOnOpenedListeners=function(){for(var t in this.app.controllers){var e=this.app.get(t);"function"==typeof e.onPopoverOpened&&e.onPopoverOpened()}this.afterOpen()},Kanboard.Popover.prototype.executeOnClosedListeners=function(){for(var t in this.app.controllers){var e=this.app.get(t);"function"==typeof e.onPopoverClosed&&e.onPopoverClosed()}},Kanboard.Popover.prototype.afterOpen=function(){var t=this,e=$("#popover-content .popover-form");e&&e.on("submit",function(o){o.preventDefault(),$.ajax({type:"POST",url:e.attr("action"),data:e.serialize(),success:function(e,o,a){t.ajaxReload(e,a,t)},beforeSend:function(){var t=$('.popover-form button[type="submit"]');t.html('<i class="fa fa-spinner fa-pulse"></i> '+t.html()),t.attr("disabled",!0)}})}),$(document).on("click",".popover-link",function(e){e.preventDefault(),$.ajax({type:"GET",url:$(this).attr("href"),success:function(e,o,a){t.ajaxReload(e,a,t)}})}),$("#popover-content input[autofocus]").each(function(){$(this).focus()}),this.app.datePicker(),this.app.autoComplete(),this.app.tagAutoComplete(),new Vue({el:"#popover-container"}),KB.render()},Kanboard.ProjectCreation=function(t){this.app=t},Kanboard.ProjectCreation.prototype.onPopoverOpened=function(){$("#project-creation-form #form-src_project_id").on("change",function(){var t=$(this).val();0==t?$(".project-creation-options").hide():$(".project-creation-options").show()})},Kanboard.ProjectPermission=function(t){this.app=t},Kanboard.ProjectPermission.prototype.listen=function(){$(".project-change-role").on("change",function(){$.ajax({cache:!1,url:$(this).data("url"),contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({id:$(this).data("id"),role:$(this).val()})})})},Kanboard.Screenshot=function(t){this.app=t,this.pasteCatcher=null},Kanboard.Screenshot.prototype.onPopoverOpened=function(){this.app.hasId("screenshot-zone")&&this.initialize()},Kanboard.Screenshot.prototype.initialize=function(){this.destroy(),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))},Kanboard.Screenshot.prototype.destroy=function(){null!=this.pasteCatcher?document.body.removeChild(this.pasteCatcher):document.getElementById("screenshot-pastezone")&&document.body.removeChild(document.getElementById("screenshot-pastezone")),document.removeEventListener("click",this.setFocus.bind(this)),this.pasteCatcher=null},Kanboard.Screenshot.prototype.setFocus=function(){null!==this.pasteCatcher&&this.pasteCatcher.focus()},Kanboard.Screenshot.prototype.pasteHandler=function(t){if(t.clipboardData&&t.clipboardData.items){var e=t.clipboardData.items;if(e)for(var o=0;o<e.length;o++)if(e[o].type.indexOf("image")!==-1){var a=e[o].getAsFile(),n=new FileReader,i=this;n.onload=function(t){i.createImage(t.target.result)},n.readAsDataURL(a)}}else setTimeout(this.checkInput.bind(this),100)},Kanboard.Screenshot.prototype.checkInput=function(){var t=this.pasteCatcher.childNodes[0];t&&"IMG"===t.tagName&&this.createImage(t.src),this.pasteCatcher.innerHTML=""},Kanboard.Screenshot.prototype.createImage=function(t){var e=new Image;e.src=t,e.onload=function(){var e=t.split("base64,"),o=e[1];$("input[name=screenshot]").val(o)};var o=document.getElementById("screenshot-zone");o.innerHTML="",o.className="screenshot-pasted",o.appendChild(e),this.destroy(),this.initialize()},Kanboard.Search=function(t){this.app=t},Kanboard.Search.prototype.focus=function(){$(document).on("focus","#form-search",function(){var t=$("#form-search");if(t[0].setSelectionRange){var e=2*t.val().length;t[0].setSelectionRange(e,e)}})},Kanboard.Search.prototype.listen=function(){$(document).on("click",".filter-helper",function(t){t.preventDefault();var e=$(this).data("filter"),o=$(this).data("append-filter"),a=$(this).data("unique-filter"),n=$("#form-search");if(a){var i=a.substr(0,a.indexOf(":"));e=n.val().replace(new RegExp("("+i+":[#a-z0-9]+)","g"),""),e=e.replace(new RegExp("("+i+':"(.+)")',"g"),""),e=e.trim(),e+=" "+a}else o&&(e=n.val()+" "+o);n.val(e),$("form.search").submit()})},Kanboard.Search.prototype.goToView=function(t){var e=$(t);e.length&&(window.location=e.attr("href"))},Kanboard.Search.prototype.keyboardShortcuts=function(){var t=this;Mousetrap.bind("v o",function(){t.goToView(".view-overview")}),Mousetrap.bind("v b",function(){t.goToView(".view-board")}),Mousetrap.bind("v c",function(){t.goToView(".view-calendar")}),Mousetrap.bind("v l",function(){t.goToView(".view-listing")}),Mousetrap.bind("v g",function(){t.goToView(".view-gantt")}),Mousetrap.bind("f",function(t){t.preventDefault();var e=document.getElementById("form-search");e&&e.focus()}),Mousetrap.bind("r",function(t){t.preventDefault();var e=$(".filter-reset").data("filter"),o=$("#form-search");o.val(e),$("form.search").submit()})},Kanboard.Session=function(t){this.app=t},Kanboard.Session.prototype.execute=function(){window.setInterval(this.checkSession,6e4)},Kanboard.Session.prototype.checkSession=function(){$(".form-login").length||$.ajax({cache:!1,url:$("body").data("status-url"),statusCode:{401:function(){window.location=$("body").data("login-url")}}})},Kanboard.Subtask=function(t){this.app=t},Kanboard.Subtask.prototype.listen=function(){var t=this;this.dragAndDrop(),$(document).on("click",".subtask-toggle-status",function(e){var o=$(this);e.preventDefault(),$.ajax({cache:!1,url:o.attr("href"),success:function(e){o.hasClass("subtask-refresh-table")?$(".subtasks-table").replaceWith(e):o.replaceWith(e),t.dragAndDrop()}})}),$(document).on("click",".subtask-toggle-timer",function(e){var o=$(this);e.preventDefault(),$.ajax({cache:!1,url:o.attr("href"),success:function(e){$(".subtasks-table").replaceWith(e),t.dragAndDrop()}})})},Kanboard.Subtask.prototype.dragAndDrop=function(){var t=this;$(".draggable-row-handle").mouseenter(function(){$(this).parent().parent().addClass("draggable-item-hover")}).mouseleave(function(){$(this).parent().parent().removeClass("draggable-item-hover")}),$(".subtasks-table tbody").sortable({forcePlaceholderSize:!0,handle:"td:first i",helper:function(t,e){return e.children().each(function(){$(this).width($(this).width())}),e},stop:function(e,o){var a=o.item;a.removeClass("draggable-item-selected"),t.savePosition(a.data("subtask-id"),a.index()+1); -},start:function(t,e){e.item.addClass("draggable-item-selected")}}).disableSelection()},Kanboard.Subtask.prototype.savePosition=function(t,e){var o=$(".subtasks-table").data("save-position-url"),a=this;this.app.showLoadingIcon(),$.ajax({cache:!1,url:o,contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({subtask_id:t,position:e}),complete:function(){a.app.hideLoadingIcon()}})},Kanboard.Swimlane=function(t){this.app=t},Kanboard.Swimlane.prototype.execute=function(){$(".swimlanes-table").length&&this.dragAndDrop()},Kanboard.Swimlane.prototype.listen=function(){var t=this;$(document).on("click",".board-swimlane-toggle",function(e){e.preventDefault();var o=$(this).data("swimlane-id");t.isCollapsed(o)?t.expand(o):t.collapse(o)})},Kanboard.Swimlane.prototype.onBoardRendered=function(){for(var t=this.getAllCollapsed(),e=0;e<t.length;e++)this.collapse(t[e])},Kanboard.Swimlane.prototype.getStorageKey=function(){return"hidden_swimlanes_"+$("#board").data("project-id")},Kanboard.Swimlane.prototype.expand=function(t){var e=this.getAllCollapsed(),o=e.indexOf(t);o>-1&&e.splice(o,1),localStorage.setItem(this.getStorageKey(),JSON.stringify(e)),$(".board-swimlane-columns-"+t).css("display","table-row"),$(".board-swimlane-tasks-"+t).css("display","table-row"),$(".hide-icon-swimlane-"+t).css("display","inline"),$(".show-icon-swimlane-"+t).css("display","none")},Kanboard.Swimlane.prototype.collapse=function(t){var e=this.getAllCollapsed();e.indexOf(t)<0&&(e.push(t),localStorage.setItem(this.getStorageKey(),JSON.stringify(e))),$(".board-swimlane-columns-"+t+":not(:first-child)").css("display","none"),$(".board-swimlane-tasks-"+t).css("display","none"),$(".hide-icon-swimlane-"+t).css("display","none"),$(".show-icon-swimlane-"+t).css("display","inline")},Kanboard.Swimlane.prototype.isCollapsed=function(t){return this.getAllCollapsed().indexOf(t)>-1},Kanboard.Swimlane.prototype.getAllCollapsed=function(){return JSON.parse(localStorage.getItem(this.getStorageKey()))||[]},Kanboard.Swimlane.prototype.dragAndDrop=function(){var t=this;$(".draggable-row-handle").mouseenter(function(){$(this).parent().parent().addClass("draggable-item-hover")}).mouseleave(function(){$(this).parent().parent().removeClass("draggable-item-hover")}),$(".swimlanes-table tbody").sortable({forcePlaceholderSize:!0,handle:"td:first i",helper:function(t,e){return e.children().each(function(){$(this).width($(this).width())}),e},stop:function(e,o){var a=o.item;a.removeClass("draggable-item-selected"),t.savePosition(a.data("swimlane-id"),a.index()+1)},start:function(t,e){e.item.addClass("draggable-item-selected")}}).disableSelection()},Kanboard.Swimlane.prototype.savePosition=function(t,e){var o=$(".swimlanes-table").data("save-position-url"),a=this;this.app.showLoadingIcon(),$.ajax({cache:!1,url:o,contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({swimlane_id:t,position:e}),complete:function(){a.app.hideLoadingIcon()}})},Kanboard.Task=function(t){this.app=t},Kanboard.Task.prototype.keyboardShortcuts=function(){var t=$("#task-view"),e=this;this.app.hasId("task-view")&&(Mousetrap.bind("e",function(){e.app.get("Popover").open(t.data("edit-url"))}),Mousetrap.bind("c",function(){e.app.get("Popover").open(t.data("comment-url"))}),Mousetrap.bind("s",function(){e.app.get("Popover").open(t.data("subtask-url"))}),Mousetrap.bind("l",function(){e.app.get("Popover").open(t.data("internal-link-url"))}))},Kanboard.Task.prototype.onPopoverOpened=function(){var t=this,e=0;t.renderColorPicker(),$(document).on("click",".assign-me",function(t){var e=$(this).data("current-id"),o="#"+$(this).data("target-id");t.preventDefault(),$(o+" option[value="+e+"]").length&&$(o).val(e)}),$(document).on("change","select.task-reload-project-destination",function(){if(e>0)$(this).val(e);else{e=$(this).val();var o=$(this).data("redirect").replace(/PROJECT_ID/g,e);$(".loading-icon").show(),$.ajax({type:"GET",url:o,success:function(o,a,n){e=0,$(".loading-icon").hide(),t.app.get("Popover").ajaxReload(o,n,t.app.get("Popover"))}})}})},Kanboard.Task.prototype.renderColorPicker=function(){function t(t){return $('<div class="color-picker-option"><div class="color-picker-square color-'+t.id+'"></div><div class="color-picker-label">'+t.text+"</div></div>")}$(".color-picker").select2({minimumResultsForSearch:1/0,templateResult:t,templateSelection:t})},Kanboard.Tooltip=function(t){this.app=t},Kanboard.Tooltip.prototype.onBoardRendered=function(){this.execute()},Kanboard.Tooltip.prototype.execute=function(){$(".tooltip").tooltip({track:!1,show:!1,hide:!1,position:{my:"left-20 top",at:"center bottom+9",using:function(t,e){$(this).css(t);var o=e.target.left+e.target.width/2-e.element.left-20;$("<div>").addClass("tooltip-arrow").addClass(e.vertical).addClass(o<1?"align-left":"align-right").appendTo(this)}},content:function(){var t=this,e=$(this).attr("data-href");return e?($.get(e,function(e){var o=$(".ui-tooltip:visible");$(".ui-tooltip-content:visible").html(e),o.css({top:"",left:""}),o.children(".tooltip-arrow").remove();var a=$(t).tooltip("option","position");a.of=$(t),o.position(a)}),'<i class="fa fa-spinner fa-spin"></i>'):'<div class="markdown">'+$(this).attr("title")+"</div>"}}).on("mouseenter",function(){var t=this;$(this).tooltip("open"),$(".ui-tooltip").on("mouseleave",function(){$(t).tooltip("close")})}).on("mouseleave focusout",function(t){t.stopImmediatePropagation();var e=this;setTimeout(function(){$(".ui-tooltip:hover").length||$(e).tooltip("close")},100)})},Kanboard.BoardDragAndDrop=function(t){this.app=t,this.savingInProgress=!1},Kanboard.BoardDragAndDrop.prototype.execute=function(){this.app.hasId("board")&&(this.dragAndDrop(),this.executeListeners())},Kanboard.BoardDragAndDrop.prototype.dragAndDrop=function(){var t=this,e=$(".board-task-list"),o={forcePlaceholderSize:!0,tolerance:"pointer",connectWith:".sortable-column",placeholder:"draggable-placeholder",items:".draggable-item",stop:function(e,o){var a=o.item,n=a.attr("data-task-id"),i=a.attr("data-position"),r=a.attr("data-column-id"),s=a.attr("data-swimlane-id"),d=a.parent().attr("data-column-id"),l=a.parent().attr("data-swimlane-id"),c=a.index()+1;a.removeClass("draggable-item-selected"),d==r&&l==s&&c==i||(t.changeTaskState(n),t.save(n,r,d,c,l))},start:function(t,e){e.item.addClass("draggable-item-selected"),e.placeholder.height(e.item.height())}};isMobile.any&&($(".task-board-sort-handle").css("display","inline"),o.handle=".task-board-sort-handle"),e.each(function(){$(this).css("min-height",$(this).parent().height())}),e.sortable(o)},Kanboard.BoardDragAndDrop.prototype.changeTaskState=function(t){var e=$("div[data-task-id="+t+"]");e.addClass("task-board-saving-state"),e.find(".task-board-saving-icon").show()},Kanboard.BoardDragAndDrop.prototype.save=function(t,e,o,a,n){var i=this;i.app.showLoadingIcon(),i.savingInProgress=!0,$.ajax({cache:!1,url:$("#board").data("save-url"),contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({task_id:t,src_column_id:e,dst_column_id:o,swimlane_id:n,position:a}),success:function(t){i.refresh(t),i.savingInProgress=!1},error:function(){i.app.hideLoadingIcon(),i.savingInProgress=!1},statusCode:{403:function(t){window.alert(t.responseJSON.message),document.location.reload(!0)}}})},Kanboard.BoardDragAndDrop.prototype.refresh=function(t){$("#board-container").replaceWith(t),this.app.hideLoadingIcon(),this.dragAndDrop(),this.executeListeners()},Kanboard.BoardDragAndDrop.prototype.executeListeners=function(){for(var t in this.app.controllers){var e=this.app.get(t);"function"==typeof e.onBoardRendered&&e.onBoardRendered()}},KB.component("calendar",function(t,e){this.render=function(){var o=$(t);o.fullCalendar({locale:$("body").data("js-lang"),editable:!0,eventLimit:!0,defaultView:"month",header:{left:"prev,next today",center:"title",right:"month,agendaWeek,agendaDay"},eventDrop:function(t){$.ajax({cache:!1,url:e.saveUrl,contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({task_id:t.id,date_due:t.start.format()})})},viewRender:function(){var t=e.checkUrl,a={start:o.fullCalendar("getView").start.format(),end:o.fullCalendar("getView").end.format()};for(var n in a)t+="&"+n+"="+a[n];$.getJSON(t,function(t){o.fullCalendar("removeEvents"),o.fullCalendar("addEventSource",t),o.fullCalendar("rerenderEvents")})}})}}),KB.component("chart-project-avg-time-column",function(t,e){this.render=function(){var o=e.metrics,a=[e.label],n=[];for(var i in o)a.push(o[i].average),n.push(o[i].title);KB.el(t).add(KB.el("div").attr("id","chart").build()),c3.generate({data:{columns:[a],type:"bar"},bar:{width:{ratio:.5}},axis:{x:{type:"category",categories:n},y:{tick:{format:KB.utils.formatDuration}}},legend:{show:!1}})}}),KB.component("chart-project-burndown",function(t,e){this.render=function(){for(var o=e.metrics,a=[[e.labelTotal]],n=[],i=d3.time.format("%Y-%m-%d"),r=d3.time.format(e.dateFormat),s=0;s<o.length;s++)for(var d=0;d<o[s].length;d++)0==s?a.push([o[s][d]]):(a[d+1].push(o[s][d]),d>0&&(void 0==a[0][s]&&a[0].push(0),a[0][s]+=o[s][d]),0==d&&n.push(r(i.parse(o[s][d]))));KB.el(t).add(KB.el("div").attr("id","chart").build()),c3.generate({data:{columns:a},axis:{x:{type:"category",categories:n}}})}}),KB.component("chart-project-cumulative-flow",function(t,e){this.render=function(){for(var o=e.metrics,a=[],n=[],i=[],r=d3.time.format("%Y-%m-%d"),s=d3.time.format(e.dateFormat),d=0;d<o.length;d++)for(var l=0;l<o[d].length;l++)0==d?(a.push([o[d][l]]),l>0&&n.push(o[d][l])):(a[l].push(o[d][l]),0==l&&i.push(s(r.parse(o[d][l]))));KB.el(t).add(KB.el("div").attr("id","chart").build()),c3.generate({data:{columns:a,type:"area-spline",groups:[n]},axis:{x:{type:"category",categories:i}}})}}),KB.component("chart-project-lead-cycle-time",function(t,e){this.render=function(){var o=e.metrics,a=[e.labelCycle],n=[e.labelLead],i=[],r={};r[e.labelCycle]="area",r[e.labelLead]="area-spline";var s={};s[e.labelLead]="#afb42b",s[e.labelCycle]="#4e342e";for(var d=0;d<o.length;d++)a.push(parseInt(o[d].avg_cycle_time)),n.push(parseInt(o[d].avg_lead_time)),i.push(o[d].day);KB.el(t).add(KB.el("div").attr("id","chart").build()),c3.generate({data:{columns:[n,a],types:r,colors:s},axis:{x:{type:"category",categories:i},y:{tick:{format:KB.utils.formatDuration}}}})}}),KB.component("chart-project-task-distribution",function(t,e){this.render=function(){for(var o=[],a=0;a<e.metrics.length;a++)o.push([e.metrics[a].column_title,e.metrics[a].nb_tasks]);KB.el(t).add(KB.el("div").attr("id","chart").build()),c3.generate({data:{columns:o,type:"donut"}})}}),KB.component("chart-project-time-comparison",function(t,e){this.render=function(){var o=[e.labelSpent],a=[e.labelEstimated],n=[];for(var i in e.metrics)o.push(e.metrics[i].time_spent),a.push(e.metrics[i].time_estimated),n.push("open"===i?e.labelOpen:e.labelClosed);KB.el(t).add(KB.el("div").attr("id","chart").build()),c3.generate({data:{columns:[o,a],type:"bar"},bar:{width:{ratio:.2}},axis:{x:{type:"category",categories:n}},legend:{show:!0}})}}),KB.component("chart-project-user-distribution",function(t,e){this.render=function(){for(var o=[],a=0;a<e.metrics.length;a++)o.push([e.metrics[a].user,e.metrics[a].nb_tasks]);KB.el(t).add(KB.el("div").attr("id","chart").build()),c3.generate({data:{columns:o,type:"donut"}})}}),KB.component("chart-task-time-column",function(t,e){this.render=function(){for(var o=e.metrics,a=[e.label],n=[],i=0;i<o.length;i++)a.push(o[i].time_spent),n.push(o[i].title);KB.el(t).add(KB.el("div").attr("id","chart").build()),c3.generate({data:{columns:[a],type:"bar"},bar:{width:{ratio:.5}},axis:{x:{type:"category",categories:n},y:{tick:{format:KB.utils.formatDuration}}},legend:{show:!1}})}}),KB.component("external-task-view",function(t,e){this.render=function(){$.ajax({cache:!1,url:e.url,success:function(e){KB.el(t).html('<div id="external-task-view">'+e+"</div>")}})}}),Vue.component("submit-cancel",{props:["labelButton","labelOr","labelCancel","callback"],template:'<div class="form-actions"><button type="button" class="btn btn-blue" @click="onSubmit" :disabled="isLoading"><span v-show="isLoading"><i class="fa fa-spinner fa-pulse"></i> </span>{{ labelButton }}</button> {{ labelOr }} <a href="#" v-on:click.prevent="onCancel">{{ labelCancel }}</a></div>',data:function(){return{loading:!1}},computed:{isLoading:function(){return this.loading}},methods:{onSubmit:function(){this.loading=!0,this.callback()},onCancel:function(){_KB.get("Popover").close()}},events:{submitCancelled:function(){this.loading=!1}}}),Vue.component("task-move-position",{props:["board","saveUrl"],template:"#template-task-move-position",data:function(){return{swimlaneId:0,columnId:0,position:1,columns:[],tasks:[],positionChoice:"before",errorMessage:""}},ready:function(){this.columns=this.board[0].columns,this.columnId=this.columns[0].id,this.tasks=this.columns[0].tasks,this.errorMessage=""},methods:{onChangeSwimlane:function(){var t=this;this.columnId=0,this.position=1,this.columns=[],this.tasks=[],this.positionChoice="before",this.board.forEach(function(e){e.id===t.swimlaneId&&(t.columns=e.columns,t.tasks=t.columns[0].tasks,t.columnId=t.columns[0].id)})},onChangeColumn:function(){var t=this;this.position=1,this.tasks=[],this.positionChoice="before",this.columns.forEach(function(e){e.id==t.columnId&&(t.tasks=e.tasks,t.tasks.length>0&&(t.position=parseInt(t.tasks[0].position)))})},onSubmit:function(){var t=this;"after"==this.positionChoice&&this.position++,$.ajax({cache:!1,url:this.saveUrl,contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({column_id:this.columnId,swimlane_id:this.swimlaneId,position:this.position}),statusCode:{200:function(){window.location.reload(!0)},403:function(e){var o=JSON.parse(e.responseText);t.errorMessage=o.message,t.$broadcast("submitCancelled")}}})}}}),KB.component("text-editor",function(t,e){function o(){var t=KB.el("div").attr("class","text-editor-toolbar")["for"]("a",[{href:"#",html:'<i class="fa fa-pencil-square-o fa-fw"></i> '+e.labelWrite,click:function(){n()}}]).build();return m=KB.el("div").attr("class","text-editor-preview-area markdown").build(),KB.el("div").attr("class","text-editor-view-mode").add(t).add(m).hide().build()}function a(){var t=KB.el("div").attr("class","text-editor-toolbar")["for"]("a",[{href:"#",html:'<i class="fa fa-eye fa-fw"></i> '+e.labelPreview,click:function(){n()}},{href:"#",html:'<i class="fa fa-bold fa-fw"></i>',click:function(){s("**")}},{href:"#",html:'<i class="fa fa-italic fa-fw"></i>',click:function(){s("_")}},{href:"#",html:'<i class="fa fa-strikethrough fa-fw"></i>',click:function(){s("~~")}},{href:"#",html:'<i class="fa fa-quote-right fa-fw"></i>',click:function(){l("> ")}},{href:"#",html:'<i class="fa fa-list-ul fa-fw"></i>',click:function(){l("* ")}},{href:"#",html:'<i class="fa fa-code fa-fw"></i>',click:function(){d("```")}}]).build();return u=KB.el("textarea").attr("name",e.name).attr("tabindex",e.tabindex||"-1").attr("required",e.required||!1).attr("autofocus",e.autofocus||null).attr("placeholder",e.placeholder||"").text(e.text).build(),KB.el("div").attr("class","text-editor-write-mode").add(t).add(u).build()}function n(){KB.el(m).html(marked(u.value,{sanitize:!0})),KB.el(h).toggle(),KB.el(f).toggle()}function i(){return u.value.substring(u.selectionStart,u.selectionEnd)}function r(t,e,o,a){return t.substring(0,e)+a+t.substring(o)}function s(t){var e=i();c(t+e+t),p(t)}function d(t){var e=i();c("\n"+t+"\n"+e+"\n"+t),p(t,2)}function l(t){var e=i();if(e.indexOf("\n")===-1)c("\n"+t+e);else{for(var o=e.split("\n"),a=0;a<o.length;a++)o[a].indexOf(t)===-1&&(o[a]=t+o[a]);c(o.join("\n"))}}function c(t){var e=!1;if(b=u.selectionStart,v=u.selectionEnd,u.focus(),document.queryCommandSupported("insertText")&&(e=document.execCommand("insertText",!1,t)),!e){try{document.execCommand("ms-beginUndoUnit")}catch(o){}u.value=r(text,u.selectionStart,u.selectionEnd,t);try{document.execCommand("ms-endUndoUnit")}catch(o){}}}function p(t,e){e=e||0;var o=v+t.length+e;u.setSelectionRange(o,o)}var u,h,f,m,b,v;this.render=function(){f=a(),h=o(),t.appendChild(KB.el("div").attr("class","text-editor").add(h).add(f).build())}});var _KB=null;jQuery(document).ready(function(){_KB=new Kanboard.App,_KB.execute(),KB.render()});
\ No newline at end of file +!function(){function t(t,a,i){if(!o)throw new Error("textarea-caret-position#getCaretCoordinates should only be called in a browser");var r=i&&i.debug||!1;if(r){var s=document.querySelector("#input-textarea-caret-position-mirror-div");s&&s.parentNode.removeChild(s)}var d=document.createElement("div");d.id="input-textarea-caret-position-mirror-div",document.body.appendChild(d);var l=d.style,c=window.getComputedStyle?getComputedStyle(t):t.currentStyle;l.whiteSpace="pre-wrap","INPUT"!==t.nodeName&&(l.wordWrap="break-word"),l.position="absolute",r||(l.visibility="hidden"),e.forEach(function(t){l[t]=c[t]}),n?t.scrollHeight>parseInt(c.height)&&(l.overflowY="scroll"):l.overflow="hidden",d.textContent=t.value.substring(0,a),"INPUT"===t.nodeName&&(d.textContent=d.textContent.replace(/\s/g,"Â "));var p=document.createElement("span");p.textContent=t.value.substring(a)||".",d.appendChild(p);var u={top:p.offsetTop+parseInt(c.borderTopWidth),left:p.offsetLeft+parseInt(c.borderLeftWidth)};return r?p.style.backgroundColor="#aaa":document.body.removeChild(d),u}var e=["direction","boxSizing","width","height","overflowX","overflowY","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","borderStyle","paddingTop","paddingRight","paddingBottom","paddingLeft","fontStyle","fontVariant","fontWeight","fontStretch","fontSize","fontSizeAdjust","lineHeight","fontFamily","textAlign","textTransform","textIndent","textDecoration","letterSpacing","wordSpacing","tabSize","MozTabSize"],o="undefined"!=typeof window,n=o&&null!=window.mozInnerScreenX;"undefined"!=typeof module&&"undefined"!=typeof module.exports?module.exports=t:o&&(window.getCaretCoordinates=t)}(),Element.prototype.matches||(Element.prototype.matches=Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(t){for(var e=(this.document||this.ownerDocument).querySelectorAll(t),o=e.length;--o>=0&&e.item(o)!==this;);return o>-1});var KB={components:{},utils:{},html:{},http:{},listeners:{clicks:{},internals:{}}};KB.on=function(t,e){this.listeners.internals.hasOwnProperty(t)||(this.listeners.internals[t]=[]),this.listeners.internals[t].push(e)},KB.trigger=function(t,e){if(this.listeners.internals.hasOwnProperty(t))for(var o=0;o<this.listeners.internals[t].length&&this.listeners.internals[t][o](e);o++);},KB.onClick=function(t,e){this.listeners.clicks[t]=e},KB.listen=function(){function t(t){for(var o in e.listeners.clicks)e.listeners.clicks.hasOwnProperty(o)&&t.target.matches(o)&&(t.preventDefault(),e.listeners.clicks[o](t))}var e=this;document.addEventListener("click",t,!1)},KB.component=function(t,e){this.components[t]=e},KB.getComponent=function(t,e,o){var n=this.components[t];return new n(e,o)},KB.render=function(){for(var t in this.components)for(var e=document.querySelectorAll(".js-"+t),o=0;o<e.length;o++)if(this.components.hasOwnProperty(t)){var n;e[o].dataset.params&&(n=JSON.parse(e[o].dataset.params));var a=KB.getComponent(t,e[o],n);a.render(),e[o].className=e[o].className+"-rendered"}},KB.dom=function(t){function e(t){var e="string"==typeof t?document.createElement(t):t;this.attr=function(t,o){return null!==o&&e.setAttribute(t,o),this},this.data=function(t,o){return 1===arguments.length?e.dataset[t]:(e.dataset[t]=o,this)},this.hide=function(){return e.style.display="none",this},this.show=function(){return e.style.display="block",this},this.toggle=function(){return"none"===e.style.display?this.show():this.hide(),this},this.style=function(t,o){return e.style[t]=o,this},this.on=function(t,o){return e.addEventListener(t,function(t){t.preventDefault(),o(t.target)}),this},this.click=function(t){return this.on("click",t)},this.mouseover=function(t){return this.on("mouseover",t)},this.change=function(t){return this.on("change",t)},this.add=function(t){return e.appendChild(t),this},this.replace=function(t){return e.parentNode.replaceChild(t,e),this},this.html=function(t){return e.innerHTML=t,this},this.text=function(t){return e.appendChild(document.createTextNode(t)),this},this.addClass=function(t){return e.classList.add(t),this},this.removeClass=function(t){return e.classList.remove(t),this},this.toggleClass=function(t){return e.classList.toggle(t),this},this.hasClass=function(t){return e.classList.contains(t)},this.disable=function(){return e.disabled=!0,this},this.enable=function(){return e.disabled=!1,this},this.remove=function(){return e.parentNode.removeChild(e),this},this.parent=function(t){for(;e&&e!==document;e=e.parentNode)if(e.matches(t))return e;return null},this.find=function(t){return e.querySelector(t)},this["for"]=function(t,o){for(var n=0;n<o.length;n++){var a=o[n];if("object"!=typeof a)e.appendChild(KB.dom(t).text(a).build());else{var i=KB.dom(t);for(var r in a)a.hasOwnProperty(r)&&r in this&&"function"==typeof this[r]?i[r](a[r]):i.attr(r,a[r]);e.appendChild(i.build())}}return this},this.build=function(){return e}}return new e(t)},KB.find=function(t){var e=document.querySelector(t);return e?KB.dom(e):null},KB.html.label=function(t,e){return KB.dom("label").attr("for",e).text(t).build()},KB.html.radio=function(t,e,o){return KB.dom("label").add(KB.dom("input").attr("type","radio").attr("name",e).attr("value",o).build()).text(t).build()},KB.html.radios=function(t){var e=KB.dom("div");for(var o in t)t.hasOwnProperty(o)&&e.add(KB.html.radio(o.label,o.name,o.value))},KB.http.request=function(t,e,o,n){function a(t){try{return JSON.parse(t.responseText)}catch(e){return t.responseText}}var i=function(){},r=function(){};this.execute=function(){var s=new XMLHttpRequest;s.open(t,e,!0),s.setRequestHeader("X-Requested-With","XMLHttpRequest");for(var d in o)o.hasOwnProperty(d)&&s.setRequestHeader(d,o[d]);return s.onerror=function(){r()},s.onreadystatechange=function(){if(s.readyState===XMLHttpRequest.DONE){var t=a(s);200===s.status?i(t):r(t)}},s.send(n),this},this.success=function(t){return i=t,this},this.error=function(t){return r=t,this}},KB.http.get=function(t){return new KB.http.request("GET",t).execute()},KB.http.postJson=function(t,e){var o={"Content-Type":"application/json",Accept:"application/json"};return new KB.http.request("POST",t,o,JSON.stringify(e)).execute()},KB.utils.formatDuration=function(t){return t>=86400?Math.round(t/86400)+"d":t>=3600?Math.round(t/3600)+"h":t>=60?Math.round(t/60)+"m":t+"s"},KB.utils.getSelectionPosition=function(t){var e,o;return e=t.value.length<t.selectionStart?t.value.length:t.selectionStart,o=t.selectionStart===t.selectionEnd?e:t.selectionEnd,{selectionStart:e,selectionEnd:o}},KB.onClick(".accordion-toggle",function(t){var e=KB.dom(t.target).parent(".accordion-section");e&&(KB.dom(e).toggleClass("accordion-collapsed"),KB.dom(KB.dom(e).find(".accordion-content")).toggle())}),KB.component("calendar",function(t,e){this.render=function(){var o=$(t);o.fullCalendar({locale:$("body").data("js-lang"),editable:!0,eventLimit:!0,defaultView:"month",header:{left:"prev,next today",center:"title",right:"month,agendaWeek,agendaDay"},eventDrop:function(t){$.ajax({cache:!1,url:e.saveUrl,contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({task_id:t.id,date_due:t.start.format()})})},viewRender:function(){var t=e.checkUrl,n={start:o.fullCalendar("getView").start.format(),end:o.fullCalendar("getView").end.format()};for(var a in n)t+="&"+a+"="+n[a];$.getJSON(t,function(t){o.fullCalendar("removeEvents"),o.fullCalendar("addEventSource",t),o.fullCalendar("rerenderEvents")})}})}}),KB.component("chart-project-avg-time-column",function(t,e){this.render=function(){var o=e.metrics,n=[e.label],a=[];for(var i in o)n.push(o[i].average),a.push(o[i].title);KB.dom(t).add(KB.dom("div").attr("id","chart").build()),c3.generate({data:{columns:[n],type:"bar"},bar:{width:{ratio:.5}},axis:{x:{type:"category",categories:a},y:{tick:{format:KB.utils.formatDuration}}},legend:{show:!1}})}}),KB.component("chart-project-burndown",function(t,e){this.render=function(){for(var o=e.metrics,n=[[e.labelTotal]],a=[],i=d3.time.format("%Y-%m-%d"),r=d3.time.format(e.dateFormat),s=0;s<o.length;s++)for(var d=0;d<o[s].length;d++)0===s?n.push([o[s][d]]):(n[d+1].push(o[s][d]),d>0&&(void 0===n[0][s]&&n[0].push(0),n[0][s]+=o[s][d]),0===d&&a.push(r(i.parse(o[s][d]))));KB.dom(t).add(KB.dom("div").attr("id","chart").build()),c3.generate({data:{columns:n},axis:{x:{type:"category",categories:a}}})}}),KB.component("chart-project-cumulative-flow",function(t,e){this.render=function(){for(var o=e.metrics,n=[],a=[],i=[],r=d3.time.format("%Y-%m-%d"),s=d3.time.format(e.dateFormat),d=0;d<o.length;d++)for(var l=0;l<o[d].length;l++)0===d?(n.push([o[d][l]]),l>0&&a.push(o[d][l])):(n[l].push(o[d][l]),0===l&&i.push(s(r.parse(o[d][l]))));KB.dom(t).add(KB.dom("div").attr("id","chart").build()),c3.generate({data:{columns:n,type:"area-spline",groups:[a]},axis:{x:{type:"category",categories:i}}})}}),KB.component("chart-project-lead-cycle-time",function(t,e){this.render=function(){var o=e.metrics,n=[e.labelCycle],a=[e.labelLead],i=[],r={};r[e.labelCycle]="area",r[e.labelLead]="area-spline";var s={};s[e.labelLead]="#afb42b",s[e.labelCycle]="#4e342e";for(var d=0;d<o.length;d++)n.push(parseInt(o[d].avg_cycle_time)),a.push(parseInt(o[d].avg_lead_time)),i.push(o[d].day);KB.dom(t).add(KB.dom("div").attr("id","chart").build()),c3.generate({data:{columns:[a,n],types:r,colors:s},axis:{x:{type:"category",categories:i},y:{tick:{format:KB.utils.formatDuration}}}})}}),KB.component("chart-project-task-distribution",function(t,e){this.render=function(){for(var o=[],n=0;n<e.metrics.length;n++)o.push([e.metrics[n].column_title,e.metrics[n].nb_tasks]);KB.dom(t).add(KB.dom("div").attr("id","chart").build()),c3.generate({data:{columns:o,type:"donut"}})}}),KB.component("chart-project-time-comparison",function(t,e){this.render=function(){var o=[e.labelSpent],n=[e.labelEstimated],a=[];for(var i in e.metrics)o.push(e.metrics[i].time_spent),n.push(e.metrics[i].time_estimated),a.push("open"===i?e.labelOpen:e.labelClosed);KB.dom(t).add(KB.dom("div").attr("id","chart").build()),c3.generate({data:{columns:[o,n],type:"bar"},bar:{width:{ratio:.2}},axis:{x:{type:"category",categories:a}},legend:{show:!0}})}}),KB.component("chart-project-user-distribution",function(t,e){this.render=function(){for(var o=[],n=0;n<e.metrics.length;n++)o.push([e.metrics[n].user,e.metrics[n].nb_tasks]);KB.dom(t).add(KB.dom("div").attr("id","chart").build()),c3.generate({data:{columns:o,type:"donut"}})}}),KB.component("chart-task-time-column",function(t,e){this.render=function(){for(var o=e.metrics,n=[e.label],a=[],i=0;i<o.length;i++)n.push(o[i].time_spent),a.push(o[i].title);KB.dom(t).add(KB.dom("div").attr("id","chart").build()),c3.generate({data:{columns:[n],type:"bar"},bar:{width:{ratio:.5}},axis:{x:{type:"category",categories:a},y:{tick:{format:KB.utils.formatDuration}}},legend:{show:!1}})}}),KB.component("external-task-view",function(t,e){this.render=function(){$.ajax({cache:!1,url:e.url,success:function(e){KB.dom(t).html('<div id="external-task-view">'+e+"</div>")}})}}),KB.component("submit-cancel",function(t,e){function o(){r=!0,KB.find("#modal-submit-button").replace(i()),KB.trigger("modal.submit")}function n(){KB.trigger("modal.cancel"),_KB.get("Popover").close()}function a(){r=!1,KB.find("#modal-submit-button").replace(i())}function i(){var t=KB.dom("button").click(o).attr("id","modal-submit-button").attr("type","submit").attr("class","btn btn-blue");return r&&t.disable().add(KB.dom("i").attr("class","fa fa-spinner fa-pulse").build()).text(" "),t.text(e.submitLabel).build()}var r=!1;this.render=function(){KB.on("modal.stop",a);var o=KB.dom("div").attr("class","form-actions").add(i()).text(" "+e.orLabel+" ").add(KB.dom("a").attr("href","#").click(n).text(e.cancelLabel).build()).build();t.appendChild(o)}}),KB.component("suggest-menu",function(t,e){function o(t){switch(t.keyCode){case 27:p();break;case 38:t.preventDefault(),t.stopImmediatePropagation(),l();break;case 40:t.preventDefault(),t.stopImmediatePropagation(),c();break;case 13:t.preventDefault(),t.stopImmediatePropagation(),i()}}function n(){i()}function a(t){KB.dom(t).hasClass("suggest-menu-item")&&(KB.find(".suggest-menu-item.active").removeClass("active"),KB.dom(t).addClass("active"))}function i(){t.focus();var e=KB.find(".suggest-menu-item.active"),o=e.data("value"),n=e.data("trigger"),a=t.value,i=r(t),s=n+o+" ",d=KB.utils.getSelectionPosition(t),l=a.substring(0,d.selectionStart-i.length),c=a.substring(d.selectionEnd),u=l.length+s.length;t.value=l+s+c,t.setSelectionRange(u,u),p()}function r(t){var e=t.value.substring(0,t.selectionEnd).split("\n"),o=e[e.length-1],n=o.split(" ");return n[n.length-1]}function s(){for(var t=[".popover-form","#popover-content","body"],e=0;e<t.length;e++){var o=document.querySelector(t[e]);if(null!==o)return o}return null}function d(){for(var t=document.querySelectorAll(".suggest-menu-item"),e=0;e<t.length;e++)if(KB.dom(t[e]).hasClass("active")){KB.dom(t[e]).removeClass("active");break}return{items:t,index:e}}function l(){var t=d();t.index>0&&(t.index=t.index-1),KB.dom(t.items[t.index]).addClass("active")}function c(){var t=d();t.index<t.items.length-1&&t.index++,KB.dom(t.items[t.index]).addClass("active")}function p(){var t=KB.find("#suggest-menu");null!==t&&t.remove(),document.removeEventListener("keydown",o,!1)}function u(t){var o=r(t),n=h(o,e.triggers);p(),null!==n&&f(n,o.substring(n.length),e.triggers[n])}function h(t,e){for(var o in e)if(e.hasOwnProperty(o)&&0===t.indexOf(o))return o;return null}function f(t,e,o){if("string"==typeof o){var n=new RegExp("SEARCH_TERM","g"),a=o.replace(n,e);KB.http.get(a).success(function(o){m(t,e,o)})}else m(t,e,o)}function m(t,e,o){o=v(e,o),o.length>0&&b(g(t,o))}function v(t,e){var o=[];if(0===t.length)return e;for(var n=0;n<e.length;n++)0===e[n].value.toLowerCase().indexOf(t.toLowerCase())&&o.push(e[n]);return o}function g(t,e){for(var o=[],n=0;n<e.length;n++){var a="suggest-menu-item";0===n&&(a+=" active"),o.push({"class":a,html:e[n].html,"data-value":e[n].value,"data-trigger":t})}return o}function b(e){var i=s(),r=getCaretCoordinates(t,t.selectionEnd),d=r.left+t.offsetLeft-t.scrollLeft,l=r.top+t.offsetTop-t.scrollTop+16;document.addEventListener("keydown",o,!1);var c=KB.dom("ul").attr("id","suggest-menu").click(n).mouseover(a).style("left",d+"px").style("top",l+"px")["for"]("li",e).build();i.appendChild(c)}this.render=function(){t.addEventListener("input",function(){u(this)})}}),KB.component("task-move-position",function(t,e){function o(t){var e=KB.dom(document).find("#"+t);return e?parseInt(e.options[e.selectedIndex].value):null}function n(){var t=o("form-swimlanes");return null===t?e.board[0].id:t}function a(){var t=o("form-columns");return null===t?e.board[0].columns[0].id:t}function i(){var t=o("form-position");return null===t?1:t}function r(){var t=KB.find("input[name=positionChoice]:checked");return t?t.value:"before"}function s(){var t=KB.dom(document).find("#form-columns");KB.dom(t).replace(u());var e=KB.dom(document).find("#form-tasks");KB.dom(e).replace(h())}function d(){var t=KB.dom(document).find("#form-tasks");KB.dom(t).replace(h())}function l(t){KB.trigger("modal.stop"),KB.find("#message-container").replace(KB.dom("div").attr("id","message-container").attr("class","alert alert-error").text(t).build())}function c(){var t=i(),o=r();"after"===o&&t++,KB.find("#message-container").replace(KB.dom("div").attr("id","message-container").build()),KB.http.postJson(e.saveUrl,{column_id:a(),swimlane_id:n(),position:t}).success(function(){window.location.reload(!0)}).error(function(t){t&&l(t.message)})}function p(){var t=[];return e.board.forEach(function(e){t.push({value:e.id,text:e.name})}),KB.dom("select").attr("id","form-swimlanes").change(s)["for"]("option",t).build()}function u(){var t=[],o=n();return e.board.forEach(function(e){o===e.id&&e.columns.forEach(function(e){t.push({value:e.id,text:e.title})})}),KB.dom("select").attr("id","form-columns").change(d)["for"]("option",t).build()}function h(){var t=[],o=n(),i=a(),r=KB.dom("div").attr("id","form-tasks");return e.board.forEach(function(e){o===e.id&&e.columns.forEach(function(e){i===e.id&&e.tasks.forEach(function(e){t.push({value:e.position,text:"#"+e.id+" - "+e.title})})})}),t.length>0&&r.add(KB.html.label(e.positionLabel,"form-position")).add(KB.dom("select").attr("id","form-position")["for"]("option",t).build()).add(KB.html.radio(e.beforeLabel,"positionChoice","before")).add(KB.html.radio(e.afterLabel,"positionChoice","after")),r.build()}this.render=function(){KB.on("modal.submit",c);var o=KB.dom("div").on("submit",c).add(KB.dom("div").attr("id","message-container").build()).add(KB.html.label(e.swimlaneLabel,"form-swimlanes")).add(p()).add(KB.html.label(e.columnLabel,"form-columns")).add(u()).add(h()).build();t.appendChild(o)}}),KB.component("text-editor",function(t,e){function o(){var t=KB.dom("div").attr("class","text-editor-toolbar")["for"]("a",[{href:"#",html:'<i class="fa fa-pencil-square-o fa-fw"></i> '+e.labelWrite,click:function(){a()}}]).build();return m=KB.dom("div").attr("class","text-editor-preview-area markdown").build(),KB.dom("div").attr("class","text-editor-view-mode").add(t).add(m).hide().build()}function n(){var t=KB.dom("div").attr("class","text-editor-toolbar")["for"]("a",[{href:"#",html:'<i class="fa fa-eye fa-fw"></i> '+e.labelPreview,click:function(){a()}},{href:"#",html:'<i class="fa fa-bold fa-fw"></i>',click:function(){s("**")}},{href:"#",html:'<i class="fa fa-italic fa-fw"></i>',click:function(){s("_")}},{href:"#",html:'<i class="fa fa-strikethrough fa-fw"></i>',click:function(){s("~~")}},{href:"#",html:'<i class="fa fa-quote-right fa-fw"></i>',click:function(){l("> ")}},{href:"#",html:'<i class="fa fa-list-ul fa-fw"></i>',click:function(){l("* ")}},{href:"#",html:'<i class="fa fa-code fa-fw"></i>',click:function(){d("```")}}]).build(),o=KB.dom("textarea");return o.attr("name",e.name),e.tabindex&&o.attr("tabindex",e.tabindex),e.required&&o.attr("required","required"),o.text(e.text),e.placeholder&&o.attr("placeholder",e.placeholder),u=o.build(),e.suggestOptions&&KB.getComponent("suggest-menu",u,e.suggestOptions).render(),KB.dom("div").attr("class","text-editor-write-mode").add(t).add(u).build()}function a(){KB.dom(m).html(marked(u.value,{sanitize:!0})),KB.dom(h).toggle(),KB.dom(f).toggle()}function i(){return u.value.substring(u.selectionStart,u.selectionEnd)}function r(t,e,o,n){return t.substring(0,e)+n+t.substring(o)}function s(t){var e=i();c(t+e+t),p(t)}function d(t){var e=i();c("\n"+t+"\n"+e+"\n"+t),p(t,2)}function l(t){var e=i();if(e.indexOf("\n")===-1)c("\n"+t+e);else{for(var o=e.split("\n"),n=0;n<o.length;n++)o[n].indexOf(t)===-1&&(o[n]=t+o[n]);c(o.join("\n"))}p(t,1)}function c(t){u.focus();var e=!1,o=KB.utils.getSelectionPosition(u);if(v=o.selectionStart,g=o.selectionEnd,document.queryCommandSupported("insertText")&&(e=document.execCommand("insertText",!1,t)),!e){try{document.execCommand("ms-beginUndoUnit")}catch(n){}u.value=r(u.value,v,g,t);try{document.execCommand("ms-endUndoUnit")}catch(n){}}}function p(t,e){e=e||0;var o=g+t.length+e;u.setSelectionRange(o,o)}var u,h,f,m,v,g;this.render=function(){f=n(),h=o(),t.appendChild(KB.dom("div").attr("class","text-editor").add(h).add(f).build()),e.autofocus&&u.focus()}}),document.addEventListener("DOMContentLoaded",function(){KB.render(),KB.listen()});var Kanboard={};Kanboard.App=function(){this.controllers={}},Kanboard.App.prototype.get=function(t){return this.controllers[t]},Kanboard.App.prototype.execute=function(){for(var t in Kanboard)if("App"!==t){var e=new Kanboard[t](this);this.controllers[t]=e,"function"==typeof e.execute&&e.execute(),"function"==typeof e.listen&&e.listen(),"function"==typeof e.focus&&e.focus(),"function"==typeof e.keyboardShortcuts&&e.keyboardShortcuts()}this.focus(),this.chosen(),this.keyboardShortcuts(),this.datePicker(),this.autoComplete(),this.tagAutoComplete()},Kanboard.App.prototype.keyboardShortcuts=function(){var t=this;Mousetrap.bindGlobal("mod+enter",function(){var e=$("form");1==e.length?e.submit():e.length>1&&("INPUT"===document.activeElement.tagName||"TEXTAREA"===document.activeElement.tagName?$(document.activeElement).parents("form").submit():t.get("Popover").isOpen()&&$("#popover-container form").submit())}),Mousetrap.bind("b",function(t){t.preventDefault(),$("#board-selector").trigger("chosen:open")}),Mousetrap.bindGlobal("esc",function(){document.getElementById("suggest-menu")||(t.get("Popover").close(),t.get("Dropdown").close())}),Mousetrap.bind("?",function(){t.get("Popover").open($("body").data("keyboard-shortcut-url"))})},Kanboard.App.prototype.focus=function(){$(document).on("focus",".auto-select",function(){$(this).select()}),$(document).on("mouseup",".auto-select",function(t){t.preventDefault()})},Kanboard.App.prototype.chosen=function(){$(".chosen-select").each(function(){var t=$(this).data("search-threshold");void 0===t&&(t=10),$(this).chosen({width:"180px",no_results_text:$(this).data("notfound"),disable_search_threshold:t})}),$(".select-auto-redirect").change(function(){var t=new RegExp($(this).data("redirect-regex"),"g");window.location=$(this).data("redirect-url").replace(t,$(this).val())})},Kanboard.App.prototype.datePicker=function(){var t=$("body"),e=t.data("js-date-format"),o=t.data("js-time-format"),n=t.data("js-lang");$.datepicker.setDefaults($.datepicker.regional[n]),$.timepicker.setDefaults($.timepicker.regional[n]),$(".form-date").datepicker({showOtherMonths:!0,selectOtherMonths:!0,dateFormat:e,constrainInput:!1}),$(".form-datetime").datetimepicker({dateFormat:e,timeFormat:o,constrainInput:!1})},Kanboard.App.prototype.tagAutoComplete=function(){$(".tag-autocomplete").select2({tags:!0})},Kanboard.App.prototype.autoComplete=function(){$(".autocomplete").each(function(){var t=$(this),e=t.data("dst-field"),o=t.data("dst-extra-field");""===$("#form-"+e).val()&&t.parent().find("button[type=submit]").attr("disabled","disabled"),t.autocomplete({source:t.data("search-url"),minLength:1,select:function(n,a){$("input[name="+e+"]").val(a.item.id),o&&$("input[name="+o+"]").val(a.item[o]),t.parent().find("button[type=submit]").removeAttr("disabled")}})})},Kanboard.App.prototype.hasId=function(t){return!!document.getElementById(t)},Kanboard.App.prototype.showLoadingIcon=function(){$("body").append('<span id="app-loading-icon"> <i class="fa fa-spinner fa-spin"></i></span>')},Kanboard.App.prototype.hideLoadingIcon=function(){$("#app-loading-icon").remove()},Kanboard.App.prototype.isVisible=function(){var t="";return"undefined"!=typeof document.hidden?t="visibilityState":"undefined"!=typeof document.mozHidden?t="mozVisibilityState":"undefined"!=typeof document.msHidden?t="msVisibilityState":"undefined"!=typeof document.webkitHidden&&(t="webkitVisibilityState"),""===t||"visible"==document[t]},Kanboard.BoardCollapsedMode=function(t){this.app=t},Kanboard.BoardCollapsedMode.prototype.keyboardShortcuts=function(){var t=this;t.app.hasId("board")&&Mousetrap.bind("s",function(){t.toggle()})},Kanboard.BoardCollapsedMode.prototype.toggle=function(){var t=this;this.app.showLoadingIcon(),$.ajax({cache:!1,url:$('.filter-display-mode:not([style="display: none;"]) a').attr("href"),success:function(e){$(".filter-display-mode").toggle(),t.app.get("BoardDragAndDrop").refresh(e)}})},Kanboard.BoardColumnView=function(t){this.app=t},Kanboard.BoardColumnView.prototype.execute=function(){this.app.hasId("board")&&this.render()},Kanboard.BoardColumnView.prototype.listen=function(){var t=this;$(document).on("click",".board-toggle-column-view",function(){t.toggle($(this).data("column-id"))})},Kanboard.BoardColumnView.prototype.onBoardRendered=function(){this.render()},Kanboard.BoardColumnView.prototype.render=function(){var t=this;$(".board-column-header").each(function(){var e=$(this).data("column-id");localStorage.getItem("hidden_column_"+e)&&t.hideColumn(e)})},Kanboard.BoardColumnView.prototype.toggle=function(t){localStorage.getItem("hidden_column_"+t)?this.showColumn(t):this.hideColumn(t)},Kanboard.BoardColumnView.prototype.hideColumn=function(t){$(".board-column-"+t+" .board-column-expanded").hide(),$(".board-column-"+t+" .board-column-collapsed").show(),$(".board-column-header-"+t+" .board-column-expanded").hide(),$(".board-column-header-"+t+" .board-column-collapsed").show(),$(".board-column-header-"+t).each(function(){$(this).removeClass("board-column-compact"),$(this).addClass("board-column-header-collapsed")}),$(".board-column-"+t).each(function(){$(this).addClass("board-column-task-collapsed")}),$(".board-column-"+t+" .board-rotation").each(function(){$(this).css("width",$(".board-column-"+t).height())}),localStorage.setItem("hidden_column_"+t,1)},Kanboard.BoardColumnView.prototype.showColumn=function(t){$(".board-column-"+t+" .board-column-expanded").show(),$(".board-column-"+t+" .board-column-collapsed").hide(),$(".board-column-header-"+t+" .board-column-expanded").show(),$(".board-column-header-"+t+" .board-column-collapsed").hide(),$(".board-column-header-"+t).removeClass("board-column-header-collapsed"),$(".board-column-"+t).removeClass("board-column-task-collapsed"),0==localStorage.getItem("horizontal_scroll")&&$(".board-column-header-"+t).addClass("board-column-compact"),localStorage.removeItem("hidden_column_"+t)},Kanboard.BoardHorizontalScrolling=function(t){this.app=t},Kanboard.BoardHorizontalScrolling.prototype.execute=function(){this.app.hasId("board")&&this.render()},Kanboard.BoardHorizontalScrolling.prototype.listen=function(){var t=this;$(document).on("click",".filter-toggle-scrolling",function(e){e.preventDefault(),t.toggle()})},Kanboard.BoardHorizontalScrolling.prototype.keyboardShortcuts=function(){var t=this;t.app.hasId("board")&&Mousetrap.bind("c",function(){t.toggle()})},Kanboard.BoardHorizontalScrolling.prototype.onBoardRendered=function(){this.render()},Kanboard.BoardHorizontalScrolling.prototype.toggle=function(){var t=localStorage.getItem("horizontal_scroll")||1;localStorage.setItem("horizontal_scroll",0==t?1:0),this.render()},Kanboard.BoardHorizontalScrolling.prototype.render=function(){0==localStorage.getItem("horizontal_scroll")?($(".filter-wide").show(),$(".filter-compact").hide(),$("#board-container").addClass("board-container-compact"),$("#board th:not(.board-column-header-collapsed)").addClass("board-column-compact")):($(".filter-wide").hide(),$(".filter-compact").show(),$("#board-container").removeClass("board-container-compact"),$("#board th").removeClass("board-column-compact"))},Kanboard.BoardPolling=function(t){this.app=t},Kanboard.BoardPolling.prototype.execute=function(){if(this.app.hasId("board")){var t=parseInt($("#board").attr("data-check-interval"));t>0&&window.setInterval(this.check.bind(this),1e3*t)}},Kanboard.BoardPolling.prototype.check=function(){if(this.app.isVisible()&&!this.app.get("BoardDragAndDrop").savingInProgress){var t=this;this.app.showLoadingIcon(),$.ajax({cache:!1,url:$("#board").data("check-url"),statusCode:{200:function(e){t.app.get("BoardDragAndDrop").refresh(e)},304:function(){t.app.hideLoadingIcon()}}})}},Kanboard.BoardTask=function(t){this.app=t},Kanboard.BoardTask.prototype.listen=function(){var t=this;$(document).on("click",".task-board-change-assignee",function(e){e.preventDefault(),e.stopPropagation(),t.app.get("Popover").open($(this).data("url"))}),$(document).on("click",".task-board",function(t){"A"!=t.target.tagName&&"IMG"!=t.target.tagName&&(window.location=$(this).data("task-url"))})},Kanboard.BoardTask.prototype.keyboardShortcuts=function(){var t=this;t.app.hasId("board")&&Mousetrap.bind("n",function(){t.app.get("Popover").open($("#board").data("task-creation-url"))})},Kanboard.Column=function(t){this.app=t},Kanboard.Column.prototype.listen=function(){this.dragAndDrop()},Kanboard.Column.prototype.dragAndDrop=function(){var t=this;$(".draggable-row-handle").mouseenter(function(){$(this).parent().parent().addClass("draggable-item-hover")}).mouseleave(function(){$(this).parent().parent().removeClass("draggable-item-hover")}),$(".columns-table tbody").sortable({forcePlaceholderSize:!0,handle:"td:first i",helper:function(t,e){return e.children().each(function(){$(this).width($(this).width())}),e},stop:function(e,o){var n=o.item;n.removeClass("draggable-item-selected"),t.savePosition(n.data("column-id"),n.index()+1)},start:function(t,e){e.item.addClass("draggable-item-selected")}}).disableSelection()},Kanboard.Column.prototype.savePosition=function(t,e){var o=$(".columns-table").data("save-position-url"),n=this;this.app.showLoadingIcon(),$.ajax({cache:!1,url:o,contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({column_id:t,position:e}),complete:function(){n.app.hideLoadingIcon()}})},Kanboard.Dropdown=function(t){this.app=t},Kanboard.Dropdown.prototype.listen=function(){var t=this;$(document).on("click",function(){t.close()}),$(document).on("click","#popover-content",function(){t.close()}),$(document).on("click",".dropdown-menu",function(e){e.preventDefault(),e.stopImmediatePropagation(),t.close();var o=$(this).next("ul"),n=$(this).offset();$("body").append(jQuery("<div>",{id:"dropdown"})),o.clone().appendTo("#dropdown");var a=$("#dropdown ul");a.addClass("dropdown-submenu-open");var i=a.outerHeight(),r=a.outerWidth();n.top+i-$(window).scrollTop()<$(window).height()||$(window).scrollTop()+n.top<i?a.css("top",n.top+$(this).height()):a.css("top",n.top-i-5),n.left+r>$(window).width()?a.css("left",n.left-r+$(this).outerWidth()):a.css("left",n.left)}),$(document).on("click",".dropdown-submenu-open li",function(t){$(t.target).is("li")&&$(this).find("a:visible")[0].click()})},Kanboard.Dropdown.prototype.close=function(){$("#dropdown").remove()},Kanboard.Dropdown.prototype.onPopoverOpened=function(){this.close()},Kanboard.FileUpload=function(t){this.app=t,this.files=[],this.currentFile=0},Kanboard.FileUpload.prototype.onPopoverOpened=function(){var t=document.getElementById("file-dropzone"),e=this;t&&(t.ondragover=t.ondragenter=function(t){t.stopPropagation(),t.preventDefault()},t.ondrop=function(t){t.stopPropagation(),t.preventDefault(),e.files=t.dataTransfer.files,e.show(),$("#file-error-max-size").hide()},$(document).on("click","#file-browser",function(t){t.preventDefault(),$("#file-form-element").get(0).click()}),$(document).on("click","#file-upload-button",function(t){t.preventDefault(),e.currentFile=0,e.checkFiles()}),$("#file-form-element").change(function(){e.files=document.getElementById("file-form-element").files,e.show(),$("#file-error-max-size").hide()}))},Kanboard.FileUpload.prototype.show=function(){if($("#file-list").remove(),this.files.length>0){$("#file-upload-button").prop("disabled",!1),$("#file-dropzone-inner").hide();for(var t=jQuery("<ul>",{id:"file-list"}),e=0;e<this.files.length;e++){var o=jQuery("<span>",{id:"file-percentage-"+e}).append("(0%)"),n=jQuery("<progress>",{id:"file-progress-"+e,value:0}),a=jQuery("<li>",{id:"file-label-"+e}).append(n).append(" ").append(this.files[e].name).append(" ").append(o);t.append(a)}$("#file-dropzone").append(t)}else $("#file-dropzone-inner").show()},Kanboard.FileUpload.prototype.checkFiles=function(){for(var t=parseInt($("#file-dropzone").data("max-size")),e=0;e<this.files.length;e++)if(this.files[e].size>t)return $("#file-error-max-size").show(),$("#file-label-"+e).addClass("file-error"),void $("#file-upload-button").prop("disabled",!0);this.uploadFiles()},Kanboard.FileUpload.prototype.uploadFiles=function(){this.files.length>0&&this.uploadFile(this.files[this.currentFile])},Kanboard.FileUpload.prototype.uploadFile=function(t){var e=document.getElementById("file-dropzone"),o=e.dataset.url,n=new XMLHttpRequest,a=new FormData;n.upload.addEventListener("progress",this.updateProgress.bind(this)),n.upload.addEventListener("load",this.transferComplete.bind(this)),n.open("POST",o,!0),a.append("files[]",t),n.send(a)},Kanboard.FileUpload.prototype.updateProgress=function(t){t.lengthComputable&&($("#file-progress-"+this.currentFile).val(t.loaded/t.total), +$("#file-percentage-"+this.currentFile).text("("+Math.floor(t.loaded/t.total*100)+"%)"))},Kanboard.FileUpload.prototype.transferComplete=function(){if(this.currentFile++,this.currentFile<this.files.length)this.uploadFile(this.files[this.currentFile]);else{var t=$("#file-upload-button");t.prop("disabled",!0),t.parent().hide(),$("#file-done").show()}},Kanboard.Gantt=function(t){this.app=t,this.data=[],this.options={container:"#gantt-chart",showWeekends:!0,allowMoves:!0,allowResizes:!0,cellWidth:21,cellHeight:31,slideWidth:1e3,vHeaderWidth:200}},Kanboard.Gantt.prototype.execute=function(){this.app.hasId("gantt-chart")&&this.show()},Kanboard.Gantt.prototype.saveRecord=function(t){this.app.showLoadingIcon(),$.ajax({cache:!1,url:$(this.options.container).data("save-url"),contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify(t),complete:this.app.hideLoadingIcon.bind(this)})},Kanboard.Gantt.prototype.show=function(){this.data=this.prepareData($(this.options.container).data("records"));var t=Math.floor(this.options.slideWidth/this.options.cellWidth+5),e=this.getDateRange(t),o=e[0],n=e[1],a=$(this.options.container),i=jQuery("<div>",{"class":"ganttview"});i.append(this.renderVerticalHeader()),i.append(this.renderSlider(o,n)),a.append(i),jQuery("div.ganttview-grid-row div.ganttview-grid-row-cell:last-child",a).addClass("last"),jQuery("div.ganttview-hzheader-days div.ganttview-hzheader-day:last-child",a).addClass("last"),jQuery("div.ganttview-hzheader-months div.ganttview-hzheader-month:last-child",a).addClass("last"),$(this.options.container).data("readonly")?(this.options.allowResizes=!1,this.options.allowMoves=!1):(this.listenForBlockResize(o),this.listenForBlockMove(o))},Kanboard.Gantt.prototype.renderVerticalHeader=function(){for(var t=jQuery("<div>",{"class":"ganttview-vtheader"}),e=jQuery("<div>",{"class":"ganttview-vtheader-item"}),o=jQuery("<div>",{"class":"ganttview-vtheader-series"}),n=0;n<this.data.length;n++){var a=jQuery("<span>").append(jQuery("<i>",{"class":"fa fa-info-circle tooltip",title:this.getVerticalHeaderTooltip(this.data[n])})).append(" ");"task"==this.data[n].type?a.append(jQuery("<a>",{href:this.data[n].link,title:this.data[n].title}).append(this.data[n].title)):a.append(jQuery("<a>",{href:this.data[n].board_link,title:$(this.options.container).data("label-board-link")}).append('<i class="fa fa-th"></i>')).append(" ").append(jQuery("<a>",{href:this.data[n].gantt_link,title:$(this.options.container).data("label-gantt-link")}).append('<i class="fa fa-sliders"></i>')).append(" ").append(jQuery("<a>",{href:this.data[n].link}).append(this.data[n].title)),o.append(jQuery("<div>",{"class":"ganttview-vtheader-series-name"}).append(a))}return e.append(o),t.append(e),t},Kanboard.Gantt.prototype.renderSlider=function(t,e){var o=jQuery("<div>",{"class":"ganttview-slide-container"}),n=this.getDates(t,e);return o.append(this.renderHorizontalHeader(n)),o.append(this.renderGrid(n)),o.append(this.addBlockContainers()),this.addBlocks(o,t),o},Kanboard.Gantt.prototype.renderHorizontalHeader=function(t){var e=jQuery("<div>",{"class":"ganttview-hzheader"}),o=jQuery("<div>",{"class":"ganttview-hzheader-months"}),n=jQuery("<div>",{"class":"ganttview-hzheader-days"}),a=0;for(var i in t)for(var r in t[i]){var s=t[i][r].length*this.options.cellWidth;a+=s,o.append(jQuery("<div>",{"class":"ganttview-hzheader-month",css:{width:s-1+"px"}}).append($.datepicker.regional[$("body").data("js-lang")].monthNames[r]+" "+i));for(var d in t[i][r])n.append(jQuery("<div>",{"class":"ganttview-hzheader-day"}).append(t[i][r][d].getDate()))}return o.css("width",a+"px"),n.css("width",a+"px"),e.append(o).append(n),e},Kanboard.Gantt.prototype.renderGrid=function(t){var e=jQuery("<div>",{"class":"ganttview-grid"}),o=jQuery("<div>",{"class":"ganttview-grid-row"});for(var n in t)for(var a in t[n])for(var i in t[n][a]){var r=jQuery("<div>",{"class":"ganttview-grid-row-cell"});this.options.showWeekends&&this.isWeekend(t[n][a][i])&&r.addClass("ganttview-weekend"),o.append(r)}var s=jQuery("div.ganttview-grid-row-cell",o).length*this.options.cellWidth;o.css("width",s+"px"),e.css("width",s+"px");for(var d=0;d<this.data.length;d++)e.append(o.clone());return e},Kanboard.Gantt.prototype.addBlockContainers=function(){for(var t=jQuery("<div>",{"class":"ganttview-blocks"}),e=0;e<this.data.length;e++)t.append(jQuery("<div>",{"class":"ganttview-block-container"}));return t},Kanboard.Gantt.prototype.addBlocks=function(t,e){for(var o=jQuery("div.ganttview-blocks div.ganttview-block-container",t),n=0,a=0;a<this.data.length;a++){var i=this.data[a],r=this.daysBetween(i.start,i.end)+1,s=this.daysBetween(e,i.start),d=jQuery("<div>",{"class":"ganttview-block-text"}),l=jQuery("<div>",{"class":"ganttview-block tooltip"+(this.options.allowMoves?" ganttview-block-movable":""),title:this.getBarTooltip(i),css:{width:r*this.options.cellWidth-9+"px","margin-left":s*this.options.cellWidth+"px"}}).append(d);r>=2&&d.append(i.progress),l.data("record",i),this.setBarColor(l,i),jQuery(o[n]).append(l),n+=1}},Kanboard.Gantt.prototype.getVerticalHeaderTooltip=function(t){var e="";if("task"==t.type)e="<strong>"+t.column_title+"</strong> ("+t.progress+")<br/>"+t.title;else{var o=["project-manager","project-member"];for(var n in o){var a=o[n];if(!jQuery.isEmptyObject(t.users[a])){var i=jQuery("<ul>");for(var r in t.users[a])r&&i.append(jQuery("<li>").append(t.users[a][r]));e+="<p><strong>"+$(this.options.container).data("label-"+a)+"</strong></p>"+i[0].outerHTML}}}return e},Kanboard.Gantt.prototype.getBarTooltip=function(t){var e="";return t.not_defined?e=$(this.options.container).data("label-not-defined"):("task"==t.type&&(e="<strong>"+t.progress+"</strong><br/>"+$(this.options.container).data("label-assignee")+" "+(t.assignee?t.assignee:"")+"<br/>"),e+=$(this.options.container).data("label-start-date")+" "+$.datepicker.formatDate("yy-mm-dd",t.start)+"<br/>",e+=$(this.options.container).data("label-end-date")+" "+$.datepicker.formatDate("yy-mm-dd",t.end)),e},Kanboard.Gantt.prototype.setBarColor=function(t,e){e.not_defined?t.addClass("ganttview-block-not-defined"):(t.css("background-color",e.color.background),t.css("border-color",e.color.border),"0%"!=e.progress&&t.append(jQuery("<div>",{css:{"z-index":0,position:"absolute",top:0,bottom:0,"background-color":e.color.border,width:e.progress,opacity:.4}})))},Kanboard.Gantt.prototype.listenForBlockResize=function(t){var e=this;jQuery("div.ganttview-block",this.options.container).resizable({grid:this.options.cellWidth,handles:"e,w",delay:300,stop:function(){var o=jQuery(this);e.updateDataAndPosition(o,t),e.saveRecord(o.data("record"))}})},Kanboard.Gantt.prototype.listenForBlockMove=function(t){var e=this;jQuery("div.ganttview-block",this.options.container).draggable({axis:"x",delay:300,grid:[this.options.cellWidth,this.options.cellWidth],stop:function(){var o=jQuery(this);e.updateDataAndPosition(o,t),e.saveRecord(o.data("record"))}})},Kanboard.Gantt.prototype.updateDataAndPosition=function(t,e){var o=jQuery("div.ganttview-slide-container",this.options.container),n=o.scrollLeft(),a=t.offset().left-o.offset().left-1+n,i=t.data("record");i.not_defined=!1,this.setBarColor(t,i);var r=Math.round(a/this.options.cellWidth),s=this.addDays(this.cloneDate(e),r);i.start=s;var d=t.outerWidth(),l=Math.round(d/this.options.cellWidth)-1;i.end=this.addDays(this.cloneDate(s),l),"task"===i.type&&l>0&&jQuery("div.ganttview-block-text",t).text(i.progress),t.attr("title",this.getBarTooltip(i)),t.data("record",i),t.css("top","").css("left","").css("position","relative").css("margin-left",a+"px")},Kanboard.Gantt.prototype.getDates=function(t,e){var o=[];o[t.getFullYear()]=[],o[t.getFullYear()][t.getMonth()]=[t];for(var n=t;this.compareDate(n,e)==-1;){var a=this.addDays(this.cloneDate(n),1);o[a.getFullYear()]||(o[a.getFullYear()]=[]),o[a.getFullYear()][a.getMonth()]||(o[a.getFullYear()][a.getMonth()]=[]),o[a.getFullYear()][a.getMonth()].push(a),n=a}return o},Kanboard.Gantt.prototype.prepareData=function(t){for(var e=0;e<t.length;e++){var o=new Date(t[e].start[0],t[e].start[1]-1,t[e].start[2],0,0,0,0);t[e].start=o;var n=new Date(t[e].end[0],t[e].end[1]-1,t[e].end[2],0,0,0,0);t[e].end=n}return t},Kanboard.Gantt.prototype.getDateRange=function(t){for(var e=new Date,o=new Date,n=0;n<this.data.length;n++){var a=new Date;a.setTime(Date.parse(this.data[n].start));var i=new Date;i.setTime(Date.parse(this.data[n].end)),0==n&&(e=a,o=i),1==this.compareDate(e,a)&&(e=a),this.compareDate(o,i)==-1&&(o=i)}return this.daysBetween(e,o)<t&&(o=this.addDays(this.cloneDate(e),t)),e.setDate(e.getDate()-1),[e,o]},Kanboard.Gantt.prototype.daysBetween=function(t,e){if(!t||!e)return 0;for(var o=0,n=this.cloneDate(t);this.compareDate(n,e)==-1;)o+=1,this.addDays(n,1);return o},Kanboard.Gantt.prototype.isWeekend=function(t){return t.getDay()%6==0},Kanboard.Gantt.prototype.cloneDate=function(t){return new Date(t.getTime())},Kanboard.Gantt.prototype.addDays=function(t,e){return t.setDate(t.getDate()+1*e),t},Kanboard.Gantt.prototype.compareDate=function(t,e){if(isNaN(t)||isNaN(e))throw new Error(t+" - "+e);if(t instanceof Date&&e instanceof Date)return t<e?-1:t>e?1:0;throw new TypeError(t+" - "+e)},Kanboard.Popover=function(t){this.app=t},Kanboard.Popover.prototype.listen=function(){var t=this;$(document).on("click",".popover",function(e){t.onClick(e)}),$(document).on("click",".close-popover",function(e){t.close(e)}),$(document).on("click","#popover-close-button",function(e){t.close(e)}),$(document).on("click","#popover-content",function(t){t.stopPropagation()})},Kanboard.Popover.prototype.onClick=function(t){t.preventDefault(),t.stopPropagation();var e=t.currentTarget||t.target,o=e.getAttribute("href");o||(o=e.getAttribute("data-href")),o&&this.open(o)},Kanboard.Popover.prototype.isOpen=function(){return $("#popover-container").size()>0},Kanboard.Popover.prototype.open=function(t){var e=this;e.isOpen()||$.get(t,function(t){$("body").prepend('<div id="popover-container"><div id="popover-content"><div id="popover-content-header"><a href="#" id="popover-close-button"><i class="fa fa-times"></i></a></div>'+t+"</div></div>"),e.executeOnOpenedListeners()})},Kanboard.Popover.prototype.close=function(t){this.isOpen()&&(t&&t.preventDefault(),$("#popover-container").remove(),this.executeOnClosedListeners())},Kanboard.Popover.prototype.ajaxReload=function(t,e,o){var n=e.getResponseHeader("X-Ajax-Redirect");"self"===n?window.location.reload():n&&n.indexOf("#")>-1?window.location=n.split("#")[0]:n?window.location=n:($("#popover-content").html(t),$("#popover-content input[autofocus]").focus(),o.executeOnOpenedListeners())},Kanboard.Popover.prototype.executeOnOpenedListeners=function(){for(var t in this.app.controllers){var e=this.app.get(t);"function"==typeof e.onPopoverOpened&&e.onPopoverOpened()}this.afterOpen()},Kanboard.Popover.prototype.executeOnClosedListeners=function(){for(var t in this.app.controllers){var e=this.app.get(t);"function"==typeof e.onPopoverClosed&&e.onPopoverClosed()}},Kanboard.Popover.prototype.afterOpen=function(){var t=this,e=$("#popover-content .popover-form");e&&e.on("submit",function(o){o.preventDefault(),$.ajax({type:"POST",url:e.attr("action"),data:e.serialize(),success:function(e,o,n){t.ajaxReload(e,n,t)},beforeSend:function(){var t=$('.popover-form button[type="submit"]');t.html('<i class="fa fa-spinner fa-pulse"></i> '+t.html()),t.attr("disabled",!0)}})}),$(document).on("click",".popover-link",function(e){e.preventDefault(),$.ajax({type:"GET",url:$(this).attr("href"),success:function(e,o,n){t.ajaxReload(e,n,t)}})}),$("#popover-content input[autofocus]").each(function(){$(this).focus()}),this.app.datePicker(),this.app.autoComplete(),this.app.tagAutoComplete(),KB.render()},Kanboard.ProjectCreation=function(t){this.app=t},Kanboard.ProjectCreation.prototype.onPopoverOpened=function(){$("#project-creation-form #form-src_project_id").on("change",function(){var t=$(this).val();0==t?$(".project-creation-options").hide():$(".project-creation-options").show()})},Kanboard.ProjectPermission=function(t){this.app=t},Kanboard.ProjectPermission.prototype.listen=function(){$(".project-change-role").on("change",function(){$.ajax({cache:!1,url:$(this).data("url"),contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({id:$(this).data("id"),role:$(this).val()})})})},Kanboard.Screenshot=function(t){this.app=t,this.pasteCatcher=null},Kanboard.Screenshot.prototype.onPopoverOpened=function(){this.app.hasId("screenshot-zone")&&this.initialize()},Kanboard.Screenshot.prototype.initialize=function(){this.destroy(),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))},Kanboard.Screenshot.prototype.destroy=function(){null!==this.pasteCatcher?document.body.removeChild(this.pasteCatcher):document.getElementById("screenshot-pastezone")&&document.body.removeChild(document.getElementById("screenshot-pastezone")),document.removeEventListener("click",this.setFocus.bind(this)),this.pasteCatcher=null},Kanboard.Screenshot.prototype.setFocus=function(){null!==this.pasteCatcher&&this.pasteCatcher.focus()},Kanboard.Screenshot.prototype.pasteHandler=function(t){if(t.clipboardData&&t.clipboardData.items){var e=t.clipboardData.items;if(e)for(var o=0;o<e.length;o++)if(e[o].type.indexOf("image")!==-1){var n=e[o].getAsFile(),a=new FileReader,i=this;a.onload=function(t){i.createImage(t.target.result)},a.readAsDataURL(n)}}else setTimeout(this.checkInput.bind(this),100)},Kanboard.Screenshot.prototype.checkInput=function(){var t=this.pasteCatcher.childNodes[0];t&&"IMG"===t.tagName&&this.createImage(t.src),this.pasteCatcher.innerHTML=""},Kanboard.Screenshot.prototype.createImage=function(t){var e=new Image;e.src=t,e.onload=function(){var e=t.split("base64,"),o=e[1];$("input[name=screenshot]").val(o)};var o=document.getElementById("screenshot-zone");o.innerHTML="",o.className="screenshot-pasted",o.appendChild(e),this.destroy(),this.initialize()},Kanboard.Search=function(t){this.app=t},Kanboard.Search.prototype.focus=function(){$(document).on("focus","#form-search",function(){var t=$("#form-search");if(t[0].setSelectionRange){var e=2*t.val().length;t[0].setSelectionRange(e,e)}})},Kanboard.Search.prototype.listen=function(){$(document).on("click",".filter-helper",function(t){t.preventDefault();var e=$(this).data("filter"),o=$(this).data("append-filter"),n=$(this).data("unique-filter"),a=$("#form-search");if(n){var i=n.substr(0,n.indexOf(":"));e=a.val().replace(new RegExp("("+i+":[#a-z0-9]+)","g"),""),e=e.replace(new RegExp("("+i+':"(.+)")',"g"),""),e=e.trim(),e+=" "+n}else o&&(e=a.val()+" "+o);a.val(e),$("form.search").submit()})},Kanboard.Search.prototype.goToView=function(t){var e=$(t);e.length&&(window.location=e.attr("href"))},Kanboard.Search.prototype.keyboardShortcuts=function(){var t=this;Mousetrap.bind("v o",function(){t.goToView(".view-overview")}),Mousetrap.bind("v b",function(){t.goToView(".view-board")}),Mousetrap.bind("v c",function(){t.goToView(".view-calendar")}),Mousetrap.bind("v l",function(){t.goToView(".view-listing")}),Mousetrap.bind("v g",function(){t.goToView(".view-gantt")}),Mousetrap.bind("f",function(t){t.preventDefault();var e=document.getElementById("form-search");e&&e.focus()}),Mousetrap.bind("r",function(t){t.preventDefault();var e=$(".filter-reset").data("filter"),o=$("#form-search");o.val(e),$("form.search").submit()})},Kanboard.Session=function(t){this.app=t},Kanboard.Session.prototype.execute=function(){window.setInterval(this.checkSession,6e4)},Kanboard.Session.prototype.checkSession=function(){$(".form-login").length||$.ajax({cache:!1,url:$("body").data("status-url"),statusCode:{401:function(){window.location=$("body").data("login-url")}}})},Kanboard.Subtask=function(t){this.app=t},Kanboard.Subtask.prototype.listen=function(){var t=this;this.dragAndDrop(),$(document).on("click",".subtask-toggle-status",function(e){var o=$(this);e.preventDefault(),$.ajax({cache:!1,url:o.attr("href"),success:function(e){o.hasClass("subtask-refresh-table")?$(".subtasks-table").replaceWith(e):o.replaceWith(e),t.dragAndDrop()}})}),$(document).on("click",".subtask-toggle-timer",function(e){var o=$(this);e.preventDefault(),$.ajax({cache:!1,url:o.attr("href"),success:function(e){$(".subtasks-table").replaceWith(e),t.dragAndDrop()}})})},Kanboard.Subtask.prototype.dragAndDrop=function(){var t=this;$(".draggable-row-handle").mouseenter(function(){$(this).parent().parent().addClass("draggable-item-hover")}).mouseleave(function(){$(this).parent().parent().removeClass("draggable-item-hover")}),$(".subtasks-table tbody").sortable({forcePlaceholderSize:!0,handle:"td:first i",helper:function(t,e){return e.children().each(function(){$(this).width($(this).width())}),e},stop:function(e,o){var n=o.item;n.removeClass("draggable-item-selected"),t.savePosition(n.data("subtask-id"),n.index()+1)},start:function(t,e){e.item.addClass("draggable-item-selected")}}).disableSelection()},Kanboard.Subtask.prototype.savePosition=function(t,e){var o=$(".subtasks-table").data("save-position-url"),n=this;this.app.showLoadingIcon(),$.ajax({cache:!1,url:o,contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({subtask_id:t,position:e}),complete:function(){n.app.hideLoadingIcon()}})},Kanboard.Swimlane=function(t){this.app=t},Kanboard.Swimlane.prototype.execute=function(){$(".swimlanes-table").length&&this.dragAndDrop()},Kanboard.Swimlane.prototype.listen=function(){var t=this;$(document).on("click",".board-swimlane-toggle",function(e){e.preventDefault();var o=$(this).data("swimlane-id");t.isCollapsed(o)?t.expand(o):t.collapse(o)})},Kanboard.Swimlane.prototype.onBoardRendered=function(){for(var t=this.getAllCollapsed(),e=0;e<t.length;e++)this.collapse(t[e])},Kanboard.Swimlane.prototype.getStorageKey=function(){return"hidden_swimlanes_"+$("#board").data("project-id")},Kanboard.Swimlane.prototype.expand=function(t){var e=this.getAllCollapsed(),o=e.indexOf(t);o>-1&&e.splice(o,1),localStorage.setItem(this.getStorageKey(),JSON.stringify(e)),$(".board-swimlane-columns-"+t).css("display","table-row"),$(".board-swimlane-tasks-"+t).css("display","table-row"),$(".hide-icon-swimlane-"+t).css("display","inline"),$(".show-icon-swimlane-"+t).css("display","none")},Kanboard.Swimlane.prototype.collapse=function(t){var e=this.getAllCollapsed();e.indexOf(t)<0&&(e.push(t),localStorage.setItem(this.getStorageKey(),JSON.stringify(e))),$(".board-swimlane-columns-"+t+":not(:first-child)").css("display","none"),$(".board-swimlane-tasks-"+t).css("display","none"),$(".hide-icon-swimlane-"+t).css("display","none"),$(".show-icon-swimlane-"+t).css("display","inline")},Kanboard.Swimlane.prototype.isCollapsed=function(t){return this.getAllCollapsed().indexOf(t)>-1},Kanboard.Swimlane.prototype.getAllCollapsed=function(){return JSON.parse(localStorage.getItem(this.getStorageKey()))||[]},Kanboard.Swimlane.prototype.dragAndDrop=function(){var t=this;$(".draggable-row-handle").mouseenter(function(){$(this).parent().parent().addClass("draggable-item-hover")}).mouseleave(function(){$(this).parent().parent().removeClass("draggable-item-hover")}),$(".swimlanes-table tbody").sortable({forcePlaceholderSize:!0,handle:"td:first i",helper:function(t,e){return e.children().each(function(){$(this).width($(this).width())}),e},stop:function(e,o){var n=o.item;n.removeClass("draggable-item-selected"),t.savePosition(n.data("swimlane-id"),n.index()+1)},start:function(t,e){e.item.addClass("draggable-item-selected")}}).disableSelection()},Kanboard.Swimlane.prototype.savePosition=function(t,e){var o=$(".swimlanes-table").data("save-position-url"),n=this;this.app.showLoadingIcon(),$.ajax({cache:!1,url:o,contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({swimlane_id:t,position:e}),complete:function(){n.app.hideLoadingIcon()}})},Kanboard.Task=function(t){this.app=t},Kanboard.Task.prototype.keyboardShortcuts=function(){var t=$("#task-view"),e=this;this.app.hasId("task-view")&&(Mousetrap.bind("e",function(){e.app.get("Popover").open(t.data("edit-url"))}),Mousetrap.bind("c",function(){e.app.get("Popover").open(t.data("comment-url"))}),Mousetrap.bind("s",function(){e.app.get("Popover").open(t.data("subtask-url"))}),Mousetrap.bind("l",function(){e.app.get("Popover").open(t.data("internal-link-url"))}))},Kanboard.Task.prototype.onPopoverOpened=function(){var t=this,e=0;t.renderColorPicker(),$(document).on("click",".assign-me",function(t){var e=$(this).data("current-id"),o="#"+$(this).data("target-id");t.preventDefault(),$(o+" option[value="+e+"]").length&&$(o).val(e)}),$(document).on("change","select.task-reload-project-destination",function(){if(e>0)$(this).val(e);else{e=$(this).val();var o=$(this).data("redirect").replace(/PROJECT_ID/g,e);$(".loading-icon").show(),$.ajax({type:"GET",url:o,success:function(o,n,a){e=0,$(".loading-icon").hide(),t.app.get("Popover").ajaxReload(o,a,t.app.get("Popover"))}})}})},Kanboard.Task.prototype.renderColorPicker=function(){function t(t){return $('<div class="color-picker-option"><div class="color-picker-square color-'+t.id+'"></div><div class="color-picker-label">'+t.text+"</div></div>")}$(".color-picker").select2({minimumResultsForSearch:1/0,templateResult:t,templateSelection:t})},Kanboard.Tooltip=function(t){this.app=t},Kanboard.Tooltip.prototype.onBoardRendered=function(){this.execute()},Kanboard.Tooltip.prototype.execute=function(){$(".tooltip").tooltip({track:!1,show:!1,hide:!1,position:{my:"left-20 top",at:"center bottom+9",using:function(t,e){$(this).css(t);var o=e.target.left+e.target.width/2-e.element.left-20;$("<div>").addClass("tooltip-arrow").addClass(e.vertical).addClass(o<1?"align-left":"align-right").appendTo(this)}},content:function(){var t=this,e=$(this).attr("data-href");return e?($.get(e,function(e){var o=$(".ui-tooltip:visible");$(".ui-tooltip-content:visible").html(e),o.css({top:"",left:""}),o.children(".tooltip-arrow").remove();var n=$(t).tooltip("option","position");n.of=$(t),o.position(n)}),'<i class="fa fa-spinner fa-spin"></i>'):'<div class="markdown">'+$(this).attr("title")+"</div>"}}).on("mouseenter",function(){var t=this;$(this).tooltip("open"),$(".ui-tooltip").on("mouseleave",function(){$(t).tooltip("close")})}).on("mouseleave focusout",function(t){t.stopImmediatePropagation();var e=this;setTimeout(function(){$(".ui-tooltip:hover").length||$(e).tooltip("close")},100)})},Kanboard.BoardDragAndDrop=function(t){this.app=t,this.savingInProgress=!1},Kanboard.BoardDragAndDrop.prototype.execute=function(){this.app.hasId("board")&&(this.dragAndDrop(),this.executeListeners())},Kanboard.BoardDragAndDrop.prototype.dragAndDrop=function(){var t=this,e=$(".board-task-list"),o={forcePlaceholderSize:!0,tolerance:"pointer",connectWith:".sortable-column",placeholder:"draggable-placeholder",items:".draggable-item",stop:function(e,o){var n=o.item,a=n.attr("data-task-id"),i=n.attr("data-position"),r=n.attr("data-column-id"),s=n.attr("data-swimlane-id"),d=n.parent().attr("data-column-id"),l=n.parent().attr("data-swimlane-id"),c=n.index()+1;n.removeClass("draggable-item-selected"),d==r&&l==s&&c==i||(t.changeTaskState(a),t.save(a,r,d,c,l))},start:function(t,e){e.item.addClass("draggable-item-selected"),e.placeholder.height(e.item.height())}};isMobile.any&&($(".task-board-sort-handle").css("display","inline"),o.handle=".task-board-sort-handle"),e.each(function(){$(this).css("min-height",$(this).parent().height())}),e.sortable(o)},Kanboard.BoardDragAndDrop.prototype.changeTaskState=function(t){var e=$("div[data-task-id="+t+"]");e.addClass("task-board-saving-state"),e.find(".task-board-saving-icon").show()},Kanboard.BoardDragAndDrop.prototype.save=function(t,e,o,n,a){var i=this;i.app.showLoadingIcon(),i.savingInProgress=!0,$.ajax({cache:!1,url:$("#board").data("save-url"),contentType:"application/json",type:"POST",processData:!1,data:JSON.stringify({task_id:t,src_column_id:e,dst_column_id:o,swimlane_id:a,position:n}),success:function(t){i.refresh(t),i.savingInProgress=!1},error:function(){i.app.hideLoadingIcon(),i.savingInProgress=!1},statusCode:{403:function(t){window.alert(t.responseJSON.message),document.location.reload(!0)}}})},Kanboard.BoardDragAndDrop.prototype.refresh=function(t){$("#board-container").replaceWith(t),this.app.hideLoadingIcon(),this.dragAndDrop(),this.executeListeners()},Kanboard.BoardDragAndDrop.prototype.executeListeners=function(){for(var t in this.app.controllers){var e=this.app.get(t);"function"==typeof e.onBoardRendered&&e.onBoardRendered()}};var _KB=null;jQuery(document).ready(function(){_KB=new Kanboard.App,_KB.execute()});
\ No newline at end of file diff --git a/assets/js/components/accordion.js b/assets/js/components/accordion.js new file mode 100644 index 00000000..4588ccc6 --- /dev/null +++ b/assets/js/components/accordion.js @@ -0,0 +1,8 @@ +KB.onClick('.accordion-toggle', function(e) { + var section = KB.dom(e.target).parent('.accordion-section'); + + if (section) { + KB.dom(section).toggleClass('accordion-collapsed'); + KB.dom(KB.dom(section).find('.accordion-content')).toggle(); + } +}); diff --git a/assets/js/components/chart-project-avg-time-column.js b/assets/js/components/chart-project-avg-time-column.js index 74fe31de..18564367 100644 --- a/assets/js/components/chart-project-avg-time-column.js +++ b/assets/js/components/chart-project-avg-time-column.js @@ -10,7 +10,7 @@ KB.component('chart-project-avg-time-column', function (containerElement, option categories.push(metrics[column_id].title); } - KB.el(containerElement).add(KB.el('div').attr('id', 'chart').build()); + KB.dom(containerElement).add(KB.dom('div').attr('id', 'chart').build()); c3.generate({ data: { diff --git a/assets/js/components/chart-project-burndown.js b/assets/js/components/chart-project-burndown.js index 34a01e4a..abcab925 100644 --- a/assets/js/components/chart-project-burndown.js +++ b/assets/js/components/chart-project-burndown.js @@ -11,29 +11,28 @@ KB.component('chart-project-burndown', function (containerElement, options) { for (var j = 0; j < metrics[i].length; j++) { - if (i == 0) { + if (i === 0) { columns.push([metrics[i][j]]); - } - else { + } else { columns[j + 1].push(metrics[i][j]); if (j > 0) { - if (columns[0][i] == undefined) { + if (columns[0][i] === undefined) { columns[0].push(0); } columns[0][i] += metrics[i][j]; } - if (j == 0) { + if (j === 0) { categories.push(outputFormat(inputFormat.parse(metrics[i][j]))); } } } } - KB.el(containerElement).add(KB.el('div').attr('id', 'chart').build()); + KB.dom(containerElement).add(KB.dom('div').attr('id', 'chart').build()); c3.generate({ data: { diff --git a/assets/js/components/chart-project-cumulative-flow.js b/assets/js/components/chart-project-cumulative-flow.js index aa150397..7b258230 100644 --- a/assets/js/components/chart-project-cumulative-flow.js +++ b/assets/js/components/chart-project-cumulative-flow.js @@ -12,25 +12,24 @@ KB.component('chart-project-cumulative-flow', function (containerElement, option for (var j = 0; j < metrics[i].length; j++) { - if (i == 0) { + if (i === 0) { columns.push([metrics[i][j]]); if (j > 0) { groups.push(metrics[i][j]); } - } - else { + } else { columns[j].push(metrics[i][j]); - if (j == 0) { + if (j === 0) { categories.push(outputFormat(inputFormat.parse(metrics[i][j]))); } } } } - KB.el(containerElement).add(KB.el('div').attr('id', 'chart').build()); + KB.dom(containerElement).add(KB.dom('div').attr('id', 'chart').build()); c3.generate({ data: { diff --git a/assets/js/components/chart-project-lead-cycle-time.js b/assets/js/components/chart-project-lead-cycle-time.js index a81937ff..208f7ce6 100644 --- a/assets/js/components/chart-project-lead-cycle-time.js +++ b/assets/js/components/chart-project-lead-cycle-time.js @@ -20,7 +20,7 @@ KB.component('chart-project-lead-cycle-time', function (containerElement, option categories.push(metrics[i].day); } - KB.el(containerElement).add(KB.el('div').attr('id', 'chart').build()); + KB.dom(containerElement).add(KB.dom('div').attr('id', 'chart').build()); c3.generate({ data: { diff --git a/assets/js/components/chart-project-task-distribution.js b/assets/js/components/chart-project-task-distribution.js index 982aaf7f..3f48d230 100644 --- a/assets/js/components/chart-project-task-distribution.js +++ b/assets/js/components/chart-project-task-distribution.js @@ -7,7 +7,7 @@ KB.component('chart-project-task-distribution', function (containerElement, opti columns.push([options.metrics[i].column_title, options.metrics[i].nb_tasks]); } - KB.el(containerElement).add(KB.el('div').attr('id', 'chart').build()); + KB.dom(containerElement).add(KB.dom('div').attr('id', 'chart').build()); c3.generate({ data: { diff --git a/assets/js/components/chart-project-time-comparison.js b/assets/js/components/chart-project-time-comparison.js index a110e6b4..e4b31a13 100644 --- a/assets/js/components/chart-project-time-comparison.js +++ b/assets/js/components/chart-project-time-comparison.js @@ -11,7 +11,7 @@ KB.component('chart-project-time-comparison', function (containerElement, option categories.push(status === 'open' ? options.labelOpen : options.labelClosed); } - KB.el(containerElement).add(KB.el('div').attr('id', 'chart').build()); + KB.dom(containerElement).add(KB.dom('div').attr('id', 'chart').build()); c3.generate({ data: { diff --git a/assets/js/components/chart-project-user-distribution.js b/assets/js/components/chart-project-user-distribution.js index 8ab61799..d3c88d56 100644 --- a/assets/js/components/chart-project-user-distribution.js +++ b/assets/js/components/chart-project-user-distribution.js @@ -7,7 +7,7 @@ KB.component('chart-project-user-distribution', function (containerElement, opti columns.push([options.metrics[i].user, options.metrics[i].nb_tasks]); } - KB.el(containerElement).add(KB.el('div').attr('id', 'chart').build()); + KB.dom(containerElement).add(KB.dom('div').attr('id', 'chart').build()); c3.generate({ data: { diff --git a/assets/js/components/chart-task-time-column.js b/assets/js/components/chart-task-time-column.js index 02426748..887d24d4 100644 --- a/assets/js/components/chart-task-time-column.js +++ b/assets/js/components/chart-task-time-column.js @@ -10,7 +10,7 @@ KB.component('chart-task-time-column', function (containerElement, options) { categories.push(metrics[i].title); } - KB.el(containerElement).add(KB.el('div').attr('id', 'chart').build()); + KB.dom(containerElement).add(KB.dom('div').attr('id', 'chart').build()); c3.generate({ data: { diff --git a/assets/js/components/external-task-view.js b/assets/js/components/external-task-view.js index b63e79d3..d402640b 100644 --- a/assets/js/components/external-task-view.js +++ b/assets/js/components/external-task-view.js @@ -5,8 +5,8 @@ KB.component('external-task-view', function (containerElement, options) { cache: false, url: options.url, success: function(data) { - KB.el(containerElement).html('<div id="external-task-view">' + data + '</div>'); + KB.dom(containerElement).html('<div id="external-task-view">' + data + '</div>'); } }); - } + }; }); diff --git a/assets/js/components/submit-cancel.js b/assets/js/components/submit-cancel.js index 061b1146..ccb3c1d9 100644 --- a/assets/js/components/submit-cancel.js +++ b/assets/js/components/submit-cancel.js @@ -1,35 +1,52 @@ -Vue.component('submit-cancel', { - props: ['labelButton', 'labelOr', 'labelCancel', 'callback'], - template: '<div class="form-actions">' + - '<button type="button" class="btn btn-blue" @click="onSubmit" :disabled="isLoading">' + - '<span v-show="isLoading"><i class="fa fa-spinner fa-pulse"></i> </span>' + - '{{ labelButton }}' + - '</button> ' + - '{{ labelOr }} <a href="#" v-on:click.prevent="onCancel">{{ labelCancel }}</a>' + - '</div>' - , - data: function () { - return { - loading: false - }; - }, - computed: { - isLoading: function () { - return this.loading; - } - }, - methods: { - onSubmit: function () { - this.loading = true; - this.callback(); - }, - onCancel: function () { - _KB.get('Popover').close(); - } - }, - events: { - 'submitCancelled': function() { - this.loading = false; +KB.component('submit-cancel', function (containerElement, options) { + var isLoading = false; + + function onSubmit() { + isLoading = true; + KB.find('#modal-submit-button').replace(buildButton()); + KB.trigger('modal.submit'); + } + + function onCancel() { + KB.trigger('modal.cancel'); + _KB.get('Popover').close(); + } + + function onStop() { + isLoading = false; + KB.find('#modal-submit-button').replace(buildButton()); + } + + function buildButton() { + var button = KB.dom('button') + .click(onSubmit) + .attr('id', 'modal-submit-button') + .attr('type', 'submit') + .attr('class', 'btn btn-blue'); + + if (isLoading) { + button + .disable() + .add(KB.dom('i').attr('class', 'fa fa-spinner fa-pulse').build()) + .text(' ') + ; } + + return button + .text(options.submitLabel) + .build(); } + + this.render = function () { + KB.on('modal.stop', onStop); + + var element = KB.dom('div') + .attr('class', 'form-actions') + .add(buildButton()) + .text(' ' + options.orLabel + ' ') + .add(KB.dom('a').attr('href', '#').click(onCancel).text(options.cancelLabel).build()) + .build(); + + containerElement.appendChild(element); + }; }); diff --git a/assets/js/components/suggest-menu.js b/assets/js/components/suggest-menu.js new file mode 100644 index 00000000..07539d2c --- /dev/null +++ b/assets/js/components/suggest-menu.js @@ -0,0 +1,225 @@ +KB.component('suggest-menu', function(containerElement, options) { + + function onKeyDown(e) { + switch (e.keyCode) { + case 27: + destroy(); + break; + case 38: + e.preventDefault(); + e.stopImmediatePropagation(); + moveUp(); + break; + case 40: + e.preventDefault(); + e.stopImmediatePropagation(); + moveDown(); + break; + case 13: + e.preventDefault(); + e.stopImmediatePropagation(); + insertSelectedItem(); + break; + } + } + + function onClick() { + insertSelectedItem(); + } + + function onMouseOver(element) { + if (KB.dom(element).hasClass('suggest-menu-item')) { + KB.find('.suggest-menu-item.active').removeClass('active'); + KB.dom(element).addClass('active'); + } + } + + function insertSelectedItem() { + containerElement.focus(); + + var element = KB.find('.suggest-menu-item.active'); + var value = element.data('value'); + var trigger = element.data('trigger'); + var content = containerElement.value; + var text = getLastWord(containerElement); + var substitute = trigger + value + ' '; + var selectionPosition = KB.utils.getSelectionPosition(containerElement); + var before = content.substring(0, selectionPosition.selectionStart - text.length); + var after = content.substring(selectionPosition.selectionEnd); + var position = before.length + substitute.length; + + containerElement.value = before + substitute + after; + containerElement.setSelectionRange(position, position); + + destroy(); + } + + function getLastWord(element) { + var lines = element.value.substring(0, element.selectionEnd).split("\n"); + var lastLine = lines[lines.length - 1]; + var words = lastLine.split(' '); + return words[words.length - 1]; + } + + function getParentElement() { + var selectors = ['.popover-form', '#popover-content', 'body']; + + for (var i = 0; i < selectors.length; i++) { + var element = document.querySelector(selectors[i]); + + if (element !== null) { + return element; + } + } + + return null; + } + + function resetSelection() { + var elements = document.querySelectorAll('.suggest-menu-item'); + + for (var i = 0; i < elements.length; i++) { + if (KB.dom(elements[i]).hasClass('active')) { + KB.dom(elements[i]).removeClass('active'); + break; + } + } + + return {items: elements, index: i}; + } + + function moveUp() { + var result = resetSelection(); + + if (result.index > 0) { + result.index = result.index - 1; + } + + KB.dom(result.items[result.index]).addClass('active'); + } + + function moveDown() { + var result = resetSelection(); + + if (result.index < result.items.length - 1) { + result.index++; + } + + KB.dom(result.items[result.index]).addClass('active'); + } + + function destroy() { + var element = KB.find('#suggest-menu'); + + if (element !== null) { + element.remove(); + } + + document.removeEventListener('keydown', onKeyDown, false); + } + + function search(element) { + var text = getLastWord(element); + var trigger = getTrigger(text, options.triggers); + + destroy(); + + if (trigger !== null) { + fetchItems(trigger, text.substring(trigger.length), options.triggers[trigger]); + } + } + + function getTrigger(text, triggers) { + for (var trigger in triggers) { + if (triggers.hasOwnProperty(trigger) && text.indexOf(trigger) === 0) { + return trigger; + } + } + + return null; + } + + function fetchItems(trigger, text, params) { + if (typeof params === 'string') { + var regex = new RegExp('SEARCH_TERM', 'g'); + var url = params.replace(regex, text); + + KB.http.get(url).success(function (response) { + onItemFetched(trigger, text, response); + }); + } else { + onItemFetched(trigger, text, params); + } + } + + function onItemFetched(trigger, text, items) { + items = filterItems(text, items); + + if (items.length > 0) { + renderMenu(buildItems(trigger, items)); + } + } + + function filterItems(text, items) { + var filteredItems = []; + + if (text.length === 0) { + return items; + } + + for (var i = 0; i < items.length; i++) { + if (items[i].value.toLowerCase().indexOf(text.toLowerCase()) === 0) { + filteredItems.push(items[i]); + } + } + + return filteredItems; + } + + function buildItems(trigger, items) { + var elements = []; + + for (var i = 0; i < items.length; i++) { + var className = 'suggest-menu-item'; + + if (i === 0) { + className += ' active'; + } + + elements.push({ + class: className, + html: items[i].html, + 'data-value': items[i].value, + 'data-trigger': trigger + }); + } + + return elements; + } + + function renderMenu(items) { + var parentElement = getParentElement(); + var caretPosition = getCaretCoordinates(containerElement, containerElement.selectionEnd); + var left = caretPosition.left + containerElement.offsetLeft - containerElement.scrollLeft; + var top = caretPosition.top + containerElement.offsetTop - containerElement.scrollTop + 16; + + document.addEventListener('keydown', onKeyDown, false); + + var menu = KB.dom('ul') + .attr('id', 'suggest-menu') + .click(onClick) + .mouseover(onMouseOver) + .style('left', left + 'px') + .style('top', top + 'px') + .for('li', items) + .build(); + + parentElement.appendChild(menu); + } + + this.render = function () { + containerElement.addEventListener('input', function () { + search(this); + }); + }; +}); diff --git a/assets/js/components/task-move-position.js b/assets/js/components/task-move-position.js index 11e1068c..5e559713 100644 --- a/assets/js/components/task-move-position.js +++ b/assets/js/components/task-move-position.js @@ -1,86 +1,164 @@ -Vue.component('task-move-position', { - props: ['board', 'saveUrl'], - template: '#template-task-move-position', - data: function () { - return { - swimlaneId: 0, - columnId: 0, - position: 1, - columns: [], - tasks: [], - positionChoice: 'before', - errorMessage: '' +KB.component('task-move-position', function (containerElement, options) { + + function getSelectedValue(id) { + var element = KB.dom(document).find('#' + id); + + if (element) { + return parseInt(element.options[element.selectedIndex].value); } - }, - ready: function () { - this.columns = this.board[0].columns; - this.columnId = this.columns[0].id; - this.tasks = this.columns[0].tasks; - this.errorMessage = ''; - }, - methods: { - onChangeSwimlane: function () { - var self = this; - this.columnId = 0; - this.position = 1; - this.columns = []; - this.tasks = []; - this.positionChoice = 'before'; - - this.board.forEach(function(swimlane) { - if (swimlane.id === self.swimlaneId) { - self.columns = swimlane.columns; - self.tasks = self.columns[0].tasks; - self.columnId = self.columns[0].id; - } - }); - }, - onChangeColumn: function () { - var self = this; - this.position = 1; - this.tasks = []; - this.positionChoice = 'before'; - - this.columns.forEach(function(column) { - if (column.id == self.columnId) { - self.tasks = column.tasks; - - if (self.tasks.length > 0) { - self.position = parseInt(self.tasks[0]['position']); - } - } - }); - }, - onSubmit: function () { - var self = this; - - if (this.positionChoice == 'after') { - this.position++; + + return null; + } + + function getSwimlaneId() { + var swimlaneId = getSelectedValue('form-swimlanes'); + return swimlaneId === null ? options.board[0].id : swimlaneId; + } + + function getColumnId() { + var columnId = getSelectedValue('form-columns'); + return columnId === null ? options.board[0].columns[0].id : columnId; + } + + function getPosition() { + var position = getSelectedValue('form-position'); + return position === null ? 1 : position; + } + + function getPositionChoice() { + var element = KB.find('input[name=positionChoice]:checked'); + + if (element) { + return element.value; + } + + return 'before'; + } + + function onSwimlaneChanged() { + var columnSelect = KB.dom(document).find('#form-columns'); + KB.dom(columnSelect).replace(buildColumnSelect()); + + var taskSection = KB.dom(document).find('#form-tasks'); + KB.dom(taskSection).replace(buildTasks()); + } + + function onColumnChanged() { + var taskSection = KB.dom(document).find('#form-tasks'); + KB.dom(taskSection).replace(buildTasks()); + } + + function onError(message) { + KB.trigger('modal.stop'); + + KB.find('#message-container') + .replace(KB.dom('div') + .attr('id', 'message-container') + .attr('class', 'alert alert-error') + .text(message) + .build() + ); + } + + function onSubmit() { + var position = getPosition(); + var positionChoice = getPositionChoice(); + + if (positionChoice === 'after') { + position++; + } + + KB.find('#message-container').replace(KB.dom('div').attr('id', 'message-container').build()); + + KB.http.postJson(options.saveUrl, { + "column_id": getColumnId(), + "swimlane_id": getSwimlaneId(), + "position": position + }).success(function () { + window.location.reload(true); + }).error(function (response) { + if (response) { + onError(response.message); } + }); + } + + function buildSwimlaneSelect() { + var swimlanes = []; + + options.board.forEach(function(swimlane) { + swimlanes.push({'value': swimlane.id, 'text': swimlane.name}); + }); + + return KB.dom('select') + .attr('id', 'form-swimlanes') + .change(onSwimlaneChanged) + .for('option', swimlanes) + .build(); + } + + function buildColumnSelect() { + var columns = []; + var swimlaneId = getSwimlaneId(); - $.ajax({ - cache: false, - url: this.saveUrl, - contentType: "application/json", - type: "POST", - processData: false, - data: JSON.stringify({ - "column_id": this.columnId, - "swimlane_id": this.swimlaneId, - "position": this.position - }), - statusCode: { - 200: function() { - window.location.reload(true); - }, - 403: function(jqXHR) { - var response = JSON.parse(jqXHR.responseText); - self.errorMessage = response.message; - - self.$broadcast('submitCancelled'); + options.board.forEach(function(swimlane) { + if (swimlaneId === swimlane.id) { + swimlane.columns.forEach(function(column) { + columns.push({'value': column.id, 'text': column.title}); + }); + } + }); + + return KB.dom('select') + .attr('id', 'form-columns') + .change(onColumnChanged) + .for('option', columns) + .build(); + } + + function buildTasks() { + var tasks = []; + var swimlaneId = getSwimlaneId(); + var columnId = getColumnId(); + var container = KB.dom('div').attr('id', 'form-tasks'); + + options.board.forEach(function(swimlane) { + if (swimlaneId === swimlane.id) { + swimlane.columns.forEach(function(column) { + if (columnId === column.id) { + column.tasks.forEach(function(task) { + tasks.push({'value': task.position, 'text': '#' + task.id + ' - ' + task.title}); + }); } - } - }); + }); + } + }); + + if (tasks.length > 0) { + container + .add(KB.html.label(options.positionLabel, 'form-position')) + .add(KB.dom('select').attr('id', 'form-position').for('option', tasks).build()) + .add(KB.html.radio(options.beforeLabel, 'positionChoice', 'before')) + .add(KB.html.radio(options.afterLabel, 'positionChoice', 'after')) + ; } + + return container.build(); } + + this.render = function () { + KB.on('modal.submit', onSubmit); + + var form = KB.dom('div') + .on('submit', onSubmit) + .add(KB.dom('div').attr('id', 'message-container').build()) + .add(KB.html.label(options.swimlaneLabel, 'form-swimlanes')) + .add(buildSwimlaneSelect()) + .add(KB.html.label(options.columnLabel, 'form-columns')) + .add(buildColumnSelect()) + .add(buildTasks()) + .build(); + + containerElement.appendChild(form); + }; }); diff --git a/assets/js/components/text-editor.js b/assets/js/components/text-editor.js index 5011318b..57bc0f78 100644 --- a/assets/js/components/text-editor.js +++ b/assets/js/components/text-editor.js @@ -5,26 +5,30 @@ KB.component('text-editor', function (containerElement, options) { writeModeElement = buildWriteMode(); viewModeElement = buildViewMode(); - containerElement.appendChild(KB.el('div') + containerElement.appendChild(KB.dom('div') .attr('class', 'text-editor') .add(viewModeElement) .add(writeModeElement) .build()); + + if (options.autofocus) { + textarea.focus(); + } }; function buildViewMode() { - var toolbarElement = KB.el('div') + var toolbarElement = KB.dom('div') .attr('class', 'text-editor-toolbar') .for('a', [ {href: '#', html: '<i class="fa fa-pencil-square-o fa-fw"></i> ' + options.labelWrite, click: function() { toggleViewMode(); }} ]) .build(); - previewElement = KB.el('div') + previewElement = KB.dom('div') .attr('class', 'text-editor-preview-area markdown') .build(); - return KB.el('div') + return KB.dom('div') .attr('class', 'text-editor-view-mode') .add(toolbarElement) .add(previewElement) @@ -33,7 +37,7 @@ KB.component('text-editor', function (containerElement, options) { } function buildWriteMode() { - var toolbarElement = KB.el('div') + var toolbarElement = KB.dom('div') .attr('class', 'text-editor-toolbar') .for('a', [ {href: '#', html: '<i class="fa fa-eye fa-fw"></i> ' + options.labelPreview, click: function() { toggleViewMode(); }}, @@ -46,16 +50,31 @@ KB.component('text-editor', function (containerElement, options) { ]) .build(); - textarea = KB.el('textarea') - .attr('name', options.name) - .attr('tabindex', options.tabindex || '-1') - .attr('required', options.required || false) - .attr('autofocus', options.autofocus || null) - .attr('placeholder', options.placeholder || '') - .text(options.text) - .build(); + var textareaElement = KB.dom('textarea'); + textareaElement.attr('name', options.name); + + if (options.tabindex) { + textareaElement.attr('tabindex', options.tabindex); + } - return KB.el('div') + if (options.required) { + textareaElement.attr('required', 'required'); + } + + // Order is important for IE11 (especially for the placeholder) + textareaElement.text(options.text); + + if (options.placeholder) { + textareaElement.attr('placeholder', options.placeholder); + } + + textarea = textareaElement.build(); + + if (options.suggestOptions) { + KB.getComponent('suggest-menu', textarea, options.suggestOptions).render(); + } + + return KB.dom('div') .attr('class', 'text-editor-write-mode') .add(toolbarElement) .add(textarea) @@ -63,9 +82,9 @@ KB.component('text-editor', function (containerElement, options) { } function toggleViewMode() { - KB.el(previewElement).html(marked(textarea.value, {sanitize: true})); - KB.el(viewModeElement).toggle(); - KB.el(writeModeElement).toggle(); + KB.dom(previewElement).html(marked(textarea.value, {sanitize: true})); + KB.dom(viewModeElement).toggle(); + KB.dom(writeModeElement).toggle(); } function getSelectedText() { @@ -106,14 +125,18 @@ KB.component('text-editor', function (containerElement, options) { insertText(lines.join('\n')); } + + setCursorBeforeClosingTag(tag, 1); } function insertText(replacedText) { + textarea.focus(); + var result = false; + var selectionPosition = KB.utils.getSelectionPosition(textarea); - selectionStart = textarea.selectionStart; - selectionEnd = textarea.selectionEnd; - textarea.focus(); + selectionStart = selectionPosition.selectionStart; + selectionEnd = selectionPosition.selectionEnd; if (document.queryCommandSupported('insertText')) { result = document.execCommand('insertText', false, replacedText); @@ -124,7 +147,7 @@ KB.component('text-editor', function (containerElement, options) { document.execCommand('ms-beginUndoUnit'); } catch (error) {} - textarea.value = replaceTextRange(text, textarea.selectionStart, textarea.selectionEnd, replacedText); + textarea.value = replaceTextRange(textarea.value, selectionStart, selectionEnd, replacedText); try { document.execCommand('ms-endUndoUnit'); diff --git a/assets/js/core/base.js b/assets/js/core/base.js new file mode 100644 index 00000000..4ea3ffc2 --- /dev/null +++ b/assets/js/core/base.js @@ -0,0 +1,76 @@ +var KB = { + components: {}, + utils: {}, + html: {}, + http: {}, + listeners: { + clicks: {}, + internals: {} + } +}; + +KB.on = function (eventType, callback) { + if (! this.listeners.internals.hasOwnProperty(eventType)) { + this.listeners.internals[eventType] = []; + } + + this.listeners.internals[eventType].push(callback); +}; + +KB.trigger = function (eventType, eventData) { + if (this.listeners.internals.hasOwnProperty(eventType)) { + for (var i = 0; i < this.listeners.internals[eventType].length; i++) { + if (! this.listeners.internals[eventType][i](eventData)) { + break; + } + } + } +}; + +KB.onClick = function (selector, callback) { + this.listeners.clicks[selector] = callback; +}; + +KB.listen = function () { + var self = this; + + function onClick(e) { + for (var selector in self.listeners.clicks) { + if (self.listeners.clicks.hasOwnProperty(selector) && e.target.matches(selector)) { + e.preventDefault(); + self.listeners.clicks[selector](e); + } + } + } + + document.addEventListener('click', onClick, false); +}; + +KB.component = function (name, object) { + this.components[name] = object; +}; + +KB.getComponent = function (name, containerElement, options) { + var object = this.components[name]; + return new object(containerElement, options); +}; + +KB.render = function () { + for (var name in this.components) { + var elementList = document.querySelectorAll('.js-' + name); + + for (var i = 0; i < elementList.length; i++) { + if (this.components.hasOwnProperty(name)) { + var options; + + if (elementList[i].dataset.params) { + options = JSON.parse(elementList[i].dataset.params); + } + + var component = KB.getComponent(name, elementList[i], options); + component.render(); + elementList[i].className = elementList[i].className + '-rendered'; + } + } + } +}; diff --git a/assets/js/core/bootstrap.js b/assets/js/core/bootstrap.js new file mode 100644 index 00000000..3af086f1 --- /dev/null +++ b/assets/js/core/bootstrap.js @@ -0,0 +1,5 @@ + +document.addEventListener('DOMContentLoaded', function () { + KB.render(); + KB.listen(); +}); diff --git a/assets/js/core/dom.js b/assets/js/core/dom.js new file mode 100644 index 00000000..20510d44 --- /dev/null +++ b/assets/js/core/dom.js @@ -0,0 +1,175 @@ +KB.dom = function (tag) { + + function DomManipulation(tag) { + var element = typeof tag === 'string' ? document.createElement(tag) : tag; + + this.attr = function (attribute, value) { + if (value !== null) { + element.setAttribute(attribute, value); + } + return this; + }; + + this.data = function (attribute, value) { + if (arguments.length === 1) { + return element.dataset[attribute]; + } + element.dataset[attribute] = value; + return this; + }; + + this.hide = function () { + element.style.display = 'none'; + return this; + }; + + this.show = function () { + element.style.display = 'block'; + return this; + }; + + this.toggle = function () { + if (element.style.display === 'none') { + this.show(); + } else{ + this.hide(); + } + + return this; + }; + + this.style = function(attribute, value) { + element.style[attribute] = value; + return this; + }; + + this.on = function (eventName, callback) { + element.addEventListener(eventName, function (e) { + e.preventDefault(); + callback(e.target); + }); + + return this; + }; + + this.click = function (callback) { + return this.on('click', callback); + }; + + this.mouseover = function (callback) { + return this.on('mouseover', callback); + }; + + this.change = function (callback) { + return this.on('change', callback); + }; + + this.add = function (node) { + element.appendChild(node); + return this; + }; + + this.replace = function (node) { + element.parentNode.replaceChild(node, element); + return this; + }; + + this.html = function (html) { + element.innerHTML = html; + return this; + }; + + this.text = function (text) { + element.appendChild(document.createTextNode(text)); + return this; + }; + + this.addClass = function (className) { + element.classList.add(className); + return this; + }; + + this.removeClass = function (className) { + element.classList.remove(className); + return this; + }; + + this.toggleClass = function (className) { + element.classList.toggle(className); + return this; + }; + + this.hasClass = function (className) { + return element.classList.contains(className); + }; + + this.disable = function () { + element.disabled = true; + return this; + }; + + this.enable = function () { + element.disabled = false; + return this; + }; + + this.remove = function () { + element.parentNode.removeChild(element); + return this; + }; + + this.parent = function (selector) { + for (; element && element !== document; element = element.parentNode) { + if (element.matches(selector)) { + return element; + } + } + + return null; + }; + + this.find = function (selector) { + return element.querySelector(selector); + }; + + this.for = function (tag, list) { + for (var i = 0; i < list.length; i++) { + var dict = list[i]; + + if (typeof dict !== 'object') { + element.appendChild(KB.dom(tag).text(dict).build()); + } else { + var node = KB.dom(tag); + + for (var attribute in dict) { + if (dict.hasOwnProperty(attribute) && attribute in this && typeof this[attribute] === 'function') { + node[attribute](dict[attribute]); + } else { + node.attr(attribute, dict[attribute]); + } + } + + element.appendChild(node.build()); + } + } + + return this; + }; + + this.build = function () { + return element; + }; + } + + return new DomManipulation(tag); +}; + +KB.find = function (selector) { + var element = document.querySelector(selector); + + if (element) { + return KB.dom(element); + } + + return null; +}; diff --git a/assets/js/core/html.js b/assets/js/core/html.js new file mode 100644 index 00000000..f49a629c --- /dev/null +++ b/assets/js/core/html.js @@ -0,0 +1,25 @@ +KB.html.label = function (label, id) { + return KB.dom('label').attr('for', id).text(label).build(); +}; + +KB.html.radio = function (label, name, value) { + return KB.dom('label') + .add(KB.dom('input') + .attr('type', 'radio') + .attr('name', name) + .attr('value', value) + .build() + ) + .text(label) + .build(); +}; + +KB.html.radios = function (items) { + var html = KB.dom('div'); + + for (var item in items) { + if (items.hasOwnProperty(item)) { + html.add(KB.html.radio(item.label, item.name, item.value)); + } + } +}; diff --git a/assets/js/core/http.js b/assets/js/core/http.js new file mode 100644 index 00000000..b965ad23 --- /dev/null +++ b/assets/js/core/http.js @@ -0,0 +1,66 @@ +KB.http.request = function (method, url, headers, body) { + var successCallback = function() {}; + var errorCallback = function() {}; + + function parseResponse(request) { + try { + return JSON.parse(request.responseText); + } catch (e) { + return request.responseText; + } + } + + this.execute = function () { + var request = new XMLHttpRequest(); + request.open(method, url, true); + request.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + + for (var header in headers) { + if (headers.hasOwnProperty(header)) { + request.setRequestHeader(header, headers[header]); + } + } + + request.onerror = function() { + errorCallback(); + }; + + request.onreadystatechange = function() { + if (request.readyState === XMLHttpRequest.DONE) { + var response = parseResponse(request); + + if (request.status === 200) { + successCallback(response); + } else { + errorCallback(response); + } + } + }; + + request.send(body); + return this; + }; + + this.success = function (callback) { + successCallback = callback; + return this; + }; + + this.error = function (callback) { + errorCallback = callback; + return this; + }; +}; + +KB.http.get = function (url) { + return (new KB.http.request('GET', url)).execute(); +}; + +KB.http.postJson = function (url, body) { + var headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }; + + return (new KB.http.request('POST', url, headers, JSON.stringify(body))).execute(); +}; diff --git a/assets/js/core/utils.js b/assets/js/core/utils.js new file mode 100644 index 00000000..e8e74b17 --- /dev/null +++ b/assets/js/core/utils.js @@ -0,0 +1,34 @@ +KB.utils.formatDuration = function (d) { + if (d >= 86400) { + return Math.round(d/86400) + "d"; + } + else if (d >= 3600) { + return Math.round(d/3600) + "h"; + } + else if (d >= 60) { + return Math.round(d/60) + "m"; + } + + return d + "s"; +}; + +KB.utils.getSelectionPosition = function (element) { + var selectionStart, selectionEnd; + + if (element.value.length < element.selectionStart) { + selectionStart = element.value.length; + } else { + selectionStart = element.selectionStart; + } + + if (element.selectionStart === element.selectionEnd) { + selectionEnd = selectionStart; + } else { + selectionEnd = element.selectionEnd; + } + + return { + selectionStart: selectionStart, + selectionEnd: selectionEnd + }; +}; diff --git a/assets/js/polyfills/matches.js b/assets/js/polyfills/matches.js new file mode 100644 index 00000000..a6f813bf --- /dev/null +++ b/assets/js/polyfills/matches.js @@ -0,0 +1,14 @@ +if (!Element.prototype.matches) { + Element.prototype.matches = + Element.prototype.matchesSelector || + Element.prototype.mozMatchesSelector || + Element.prototype.msMatchesSelector || + Element.prototype.oMatchesSelector || + Element.prototype.webkitMatchesSelector || + function(s) { + var matches = (this.document || this.ownerDocument).querySelectorAll(s), + i = matches.length; + while (--i >= 0 && matches.item(i) !== this) {} + return i > -1; + }; +} diff --git a/assets/js/src/Accordion.js b/assets/js/src/Accordion.js deleted file mode 100644 index f05dc5ff..00000000 --- a/assets/js/src/Accordion.js +++ /dev/null @@ -1,18 +0,0 @@ -Kanboard.Accordion = function(app) { - this.app = app; -}; - -Kanboard.Accordion.prototype.listen = function() { - $(document).on("click", ".accordion-toggle", function(e) { - var section = $(this).parents(".accordion-section"); - e.preventDefault(); - - if (section.hasClass("accordion-collapsed")) { - section.find(".accordion-content").show(); - section.removeClass("accordion-collapsed"); - } else { - section.find(".accordion-content").hide(); - section.addClass("accordion-collapsed"); - } - }); -}; diff --git a/assets/js/src/App.js b/assets/js/src/App.js index 6fb3ccb7..ab8bd190 100644 --- a/assets/js/src/App.js +++ b/assets/js/src/App.js @@ -64,8 +64,10 @@ Kanboard.App.prototype.keyboardShortcuts = function() { // Close popover and dropdown Mousetrap.bindGlobal("esc", function() { - self.get("Popover").close(); - self.get("Dropdown").close(); + if (! document.getElementById('suggest-menu')) { + self.get("Popover").close(); + self.get("Dropdown").close(); + } }); // Show keyboard shortcut @@ -135,7 +137,7 @@ Kanboard.App.prototype.datePicker = function() { Kanboard.App.prototype.tagAutoComplete = function() { $(".tag-autocomplete").select2({ tags: true - }) + }); }; Kanboard.App.prototype.autoComplete = function() { @@ -144,7 +146,7 @@ Kanboard.App.prototype.autoComplete = function() { var field = input.data("dst-field"); var extraField = input.data("dst-extra-field"); - if ($('#form-' + field).val() == '') { + if ($('#form-' + field).val() === '') { input.parent().find("button[type=submit]").attr('disabled','disabled'); } @@ -189,7 +191,7 @@ Kanboard.App.prototype.isVisible = function() { property = "webkitVisibilityState"; } - if (property != "") { + if (property !== "") { return document[property] == "visible"; } diff --git a/assets/js/src/BoardDragAndDrop.js b/assets/js/src/BoardDragAndDrop.js index 5ff6e76a..5d2844de 100644 --- a/assets/js/src/BoardDragAndDrop.js +++ b/assets/js/src/BoardDragAndDrop.js @@ -45,7 +45,7 @@ Kanboard.BoardDragAndDrop.prototype.dragAndDrop = function() { if (isMobile.any) { $(".task-board-sort-handle").css("display", "inline"); - params["handle"] = ".task-board-sort-handle"; + params.handle = ".task-board-sort-handle"; } // Set dropzone height to the height of the table cell diff --git a/assets/js/src/Bootstrap.js b/assets/js/src/Bootstrap.js index 7f722b04..94b1f2ca 100644 --- a/assets/js/src/Bootstrap.js +++ b/assets/js/src/Bootstrap.js @@ -3,6 +3,4 @@ var _KB = null; jQuery(document).ready(function() { _KB = new Kanboard.App(); _KB.execute(); - - KB.render(); }); diff --git a/assets/js/src/Namespace.js b/assets/js/src/Namespace.js index de825be4..ada17047 100644 --- a/assets/js/src/Namespace.js +++ b/assets/js/src/Namespace.js @@ -1,126 +1 @@ -'use strict'; - var Kanboard = {}; - -var KB = { - components: {}, - utils: {} -}; - -KB.component = function (name, object) { - this.components[name] = object; -}; - -KB.render = function () { - for (var name in this.components) { - var elementList = document.querySelectorAll('.js-' + name); - - for (var i = 0; i < elementList.length; i++) { - var object = this.components[name]; - var component = new object(elementList[i], JSON.parse(elementList[i].dataset.params)); - component.render(); - elementList[i].className = elementList[i].className + '-rendered'; - } - } -}; - -KB.el = function (tag) { - - function DOMBuilder(tag) { - var element = typeof tag === 'string' ? document.createElement(tag) : tag; - - this.attr = function (attribute, value) { - if (value !== null) { - element.setAttribute(attribute, value); - } - return this; - }; - - this.hide = function () { - element.style.display = 'none'; - return this; - }; - - this.show = function () { - element.style.display = 'block'; - return this; - }; - - this.toggle = function () { - if (element.style.display === 'none') { - this.show(); - } else{ - this.hide(); - } - - return this; - }; - - this.click = function (callback) { - element.onclick = function (e) { - e.preventDefault(); - callback(); - }; - return this; - }; - - this.add = function (node) { - element.appendChild(node); - return this; - }; - - this.html = function (html) { - element.innerHTML = html; - return this; - }; - - this.text = function (text) { - element.appendChild(document.createTextNode(text)); - return this; - }; - - this.for = function (tag, list) { - for (var i = 0; i < list.length; i++) { - var dict = list[i]; - - if (typeof dict !== 'object') { - element.appendChild(KB.el(tag).text(dict).build()); - } else { - var node = KB.el(tag); - - for (var attribute in dict) { - if (attribute in this && typeof this[attribute] === 'function') { - node[attribute](dict[attribute]); - } else { - node.attr(attribute, dict[attribute]); - } - } - - element.appendChild(node.build()); - } - } - - return this; - }; - - this.build = function () { - return element; - }; - } - - return new DOMBuilder(tag); -}; - -KB.utils.formatDuration = function(d) { - if (d >= 86400) { - return Math.round(d/86400) + "d"; - } - else if (d >= 3600) { - return Math.round(d/3600) + "h"; - } - else if (d >= 60) { - return Math.round(d/60) + "m"; - } - - return d + "s"; -}; diff --git a/assets/js/src/Notification.js b/assets/js/src/Notification.js deleted file mode 100644 index 840ee988..00000000 --- a/assets/js/src/Notification.js +++ /dev/null @@ -1,9 +0,0 @@ -Kanboard.Notification = function(app) { - this.app = app; -}; - -Kanboard.Notification.prototype.execute = function() { - $(".alert-fade-out").delay(4000).fadeOut(800, function() { - $(this).remove(); - }); -}; diff --git a/assets/js/src/Popover.js b/assets/js/src/Popover.js index 6e487efa..ab71505a 100644 --- a/assets/js/src/Popover.js +++ b/assets/js/src/Popover.js @@ -157,9 +157,5 @@ Kanboard.Popover.prototype.afterOpen = function() { this.app.autoComplete(); this.app.tagAutoComplete(); - new Vue({ - el: '#popover-container' - }); - KB.render(); }; diff --git a/assets/js/src/Screenshot.js b/assets/js/src/Screenshot.js index 5c74288b..4f69e9c3 100644 --- a/assets/js/src/Screenshot.js +++ b/assets/js/src/Screenshot.js @@ -44,7 +44,7 @@ Kanboard.Screenshot.prototype.initialize = function() { // Destroy contentEditable element Kanboard.Screenshot.prototype.destroy = function() { - if (this.pasteCatcher != null) { + if (this.pasteCatcher !== null) { document.body.removeChild(this.pasteCatcher); } else if (document.getElementById("screenshot-pastezone")) { diff --git a/assets/js/vendor.min.js b/assets/js/vendor.min.js index 21e13569..2f29db5e 100644 --- a/assets/js/vendor.min.js +++ b/assets/js/vendor.min.js @@ -1297,7 +1297,7 @@ if(c&&c._defaults.timeOnly&&b.input.val()!==b.lastVal)try{$.datepicker._updateDa /*! Select2 4.0.2 | https://github.com/select2/select2/blob/master/LICENSE.md */!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){var b=function(){if(a&&a.fn&&a.fn.select2&&a.fn.select2.amd)var b=a.fn.select2.amd;var b;return function(){if(!b||!b.requirejs){b?c=b:b={};var a,c,d;!function(b){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.slice(0,n.length-1).concat(a),k=0;k<a.length;k+=1)if(m=a[k],"."===m)a.splice(k,1),k-=1;else if(".."===m){if(1===k&&(".."===a[2]||".."===a[0]))break;k>0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if((n||p)&&o){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),n)for(l=n.length;l>0;l-=1)if(e=o[n.slice(0,l).join("/")],e&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&p&&p[d]&&(i=p[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,c){return function(){var d=v.call(arguments,0);return"string"!=typeof d[0]&&1===d.length&&d.push(null),n.apply(b,d.concat([a,c]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){q[a]=b}}function j(a){if(e(r,a)){var c=r[a];delete r[a],t[a]=!0,m.apply(b,c)}if(!e(q,a)&&!e(t,a))throw new Error("No "+a);return q[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return function(){return s&&s.config&&s.config[a]||{}}}var m,n,o,p,q={},r={},s={},t={},u=Object.prototype.hasOwnProperty,v=[].slice,w=/\.js$/;o=function(a,b){var c,d=k(a),e=d[0];return a=d[1],e&&(e=f(e,b),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(b)):f(a,b):(a=f(a,b),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},p={require:function(a){return g(a)},exports:function(a){var b=q[a];return"undefined"!=typeof b?b:q[a]={}},module:function(a){return{id:a,uri:"",exports:q[a],config:l(a)}}},m=function(a,c,d,f){var h,k,l,m,n,s,u=[],v=typeof d;if(f=f||a,"undefined"===v||"function"===v){for(c=!c.length&&d.length?["require","exports","module"]:c,n=0;n<c.length;n+=1)if(m=o(c[n],f),k=m.f,"require"===k)u[n]=p.require(a);else if("exports"===k)u[n]=p.exports(a),s=!0;else if("module"===k)h=u[n]=p.module(a);else if(e(q,k)||e(r,k)||e(t,k))u[n]=j(k);else{if(!m.p)throw new Error(a+" missing "+k);m.p.load(m.n,g(f,!0),i(k),{}),u[n]=q[k]}l=d?d.apply(q[a],u):void 0,a&&(h&&h.exports!==b&&h.exports!==q[a]?q[a]=h.exports:l===b&&s||(q[a]=l))}else a&&(q[a]=d)},a=c=n=function(a,c,d,e,f){if("string"==typeof a)return p[a]?p[a](c):j(o(a,c).f);if(!a.splice){if(s=a,s.deps&&n(s.deps,s.callback),!c)return;c.splice?(a=c,c=d,d=null):a=b}return c=c||function(){},"function"==typeof d&&(d=e,e=f),e?m(b,a,c,d):setTimeout(function(){m(b,a,c,d)},4),n},n.config=function(a){return n(a)},a._defined=q,d=function(a,b,c){if("string"!=typeof a)throw new Error("See almond README: incorrect module build, no module name");b.splice||(c=b,b=[]),e(q,a)||e(r,a)||(r[a]=[a,b,c])},d.amd={jQuery:!0}}(),b.requirejs=a,b.require=c,b.define=d}}(),b.define("almond",function(){}),b.define("jquery",[],function(){var b=a||$;return null==b&&console&&console.error&&console.error("Select2: An instance of jQuery or a jQuery-compatible library was not found. Make sure that you are including jQuery before Select2 on your web page."),b}),b.define("select2/utils",["jquery"],function(a){function b(a){var b=a.prototype,c=[];for(var d in b){var e=b[d];"function"==typeof e&&"constructor"!==d&&c.push(d)}return c}var c={};c.Extend=function(a,b){function c(){this.constructor=a}var d={}.hasOwnProperty;for(var e in b)d.call(b,e)&&(a[e]=b[e]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},c.Decorate=function(a,c){function d(){var b=Array.prototype.unshift,d=c.prototype.constructor.length,e=a.prototype.constructor;d>0&&(b.call(arguments,a.prototype.constructor),e=c.prototype.constructor),e.apply(this,arguments)}function e(){this.constructor=d}var f=b(c),g=b(a);c.displayName=a.displayName,d.prototype=new e;for(var h=0;h<g.length;h++){var i=g[h];d.prototype[i]=a.prototype[i]}for(var j=(function(a){var b=function(){};a in d.prototype&&(b=d.prototype[a]);var e=c.prototype[a];return function(){var a=Array.prototype.unshift;return a.call(arguments,b),e.apply(this,arguments)}}),k=0;k<f.length;k++){var l=f[k];d.prototype[l]=j(l)}return d};var d=function(){this.listeners={}};return d.prototype.on=function(a,b){this.listeners=this.listeners||{},a in this.listeners?this.listeners[a].push(b):this.listeners[a]=[b]},d.prototype.trigger=function(a){var b=Array.prototype.slice;this.listeners=this.listeners||{},a in this.listeners&&this.invoke(this.listeners[a],b.call(arguments,1)),"*"in this.listeners&&this.invoke(this.listeners["*"],arguments)},d.prototype.invoke=function(a,b){for(var c=0,d=a.length;d>c;c++)a[c].apply(this,b)},c.Observable=d,c.generateChars=function(a){for(var b="",c=0;a>c;c++){var d=Math.floor(36*Math.random());b+=d.toString(36)}return b},c.bind=function(a,b){return function(){a.apply(b,arguments)}},c._convertData=function(a){for(var b in a){var c=b.split("-"),d=a;if(1!==c.length){for(var e=0;e<c.length;e++){var f=c[e];f=f.substring(0,1).toLowerCase()+f.substring(1),f in d||(d[f]={}),e==c.length-1&&(d[f]=a[b]),d=d[f]}delete a[b]}}return a},c.hasScroll=function(b,c){var d=a(c),e=c.style.overflowX,f=c.style.overflowY;return e!==f||"hidden"!==f&&"visible"!==f?"scroll"===e||"scroll"===f?!0:d.innerHeight()<c.scrollHeight||d.innerWidth()<c.scrollWidth:!1},c.escapeMarkup=function(a){var b={"\\":"\","&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};return"string"!=typeof a?a:String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})},c.appendMany=function(b,c){if("1.7"===a.fn.jquery.substr(0,3)){var d=a();a.map(c,function(a){d=d.add(a)}),c=d}b.append(c)},c}),b.define("select2/results",["jquery","./utils"],function(a,b){function c(a,b,d){this.$element=a,this.data=d,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('<ul class="select2-results__options" role="tree"></ul>');return this.options.get("multiple")&&b.attr("aria-multiselectable","true"),this.$results=b,b},c.prototype.clear=function(){this.$results.empty()},c.prototype.displayMessage=function(b){var c=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var d=a('<li role="treeitem" aria-live="assertive" class="select2-results__option"></li>'),e=this.options.get("translations").get(b.message);d.append(c(e(b.args))),d[0].className+=" select2-results__message",this.$results.append(d)},c.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()},c.prototype.append=function(a){this.hideLoading();var b=[];if(null==a.results||0===a.results.length)return void(0===this.$results.children().length&&this.trigger("results:message",{message:"noResults"}));a.results=this.sort(a.results);for(var c=0;c<a.results.length;c++){var d=a.results[c],e=this.option(d);b.push(e)}this.$results.append(b)},c.prototype.position=function(a,b){var c=b.find(".select2-results");c.append(a)},c.prototype.sort=function(a){var b=this.options.get("sorter");return b(a)},c.prototype.setClasses=function(){var b=this;this.data.current(function(c){var d=a.map(c,function(a){return a.id.toString()}),e=b.$results.find(".select2-results__option[aria-selected]");e.each(function(){var b=a(this),c=a.data(this,"data"),e=""+c.id;null!=c.element&&c.element.selected||null==c.element&&a.inArray(e,d)>-1?b.attr("aria-selected","true"):b.attr("aria-selected","false")});var f=e.filter("[aria-selected=true]");f.length>0?f.first().trigger("mouseenter"):e.first().trigger("mouseenter")})},c.prototype.showLoading=function(a){this.hideLoading();var b=this.options.get("translations").get("searching"),c={disabled:!0,loading:!0,text:b(a)},d=this.option(c);d.className+=" loading-results",this.$results.prepend(d)},c.prototype.hideLoading=function(){this.$results.find(".loading-results").remove()},c.prototype.option=function(b){var c=document.createElement("li");c.className="select2-results__option";var d={role:"treeitem","aria-selected":"false"};b.disabled&&(delete d["aria-selected"],d["aria-disabled"]="true"),null==b.id&&delete d["aria-selected"],null!=b._resultId&&(c.id=b._resultId),b.title&&(c.title=b.title),b.children&&(d.role="group",d["aria-label"]=b.text,delete d["aria-selected"]);for(var e in d){var f=d[e];c.setAttribute(e,f)}if(b.children){var g=a(c),h=document.createElement("strong");h.className="select2-results__group";a(h);this.template(b,h);for(var i=[],j=0;j<b.children.length;j++){var k=b.children[j],l=this.option(k);i.push(l)}var m=a("<ul></ul>",{"class":"select2-results__options select2-results__options--nested"});m.append(i),g.append(h),g.append(m)}else this.template(b,c);return a.data(c,"data",b),c},c.prototype.bind=function(b,c){var d=this,e=b.id+"-results";this.$results.attr("id",e),b.on("results:all",function(a){d.clear(),d.append(a.data),b.isOpen()&&d.setClasses()}),b.on("results:append",function(a){d.append(a.data),b.isOpen()&&d.setClasses()}),b.on("query",function(a){d.hideMessages(),d.showLoading(a)}),b.on("select",function(){b.isOpen()&&d.setClasses()}),b.on("unselect",function(){b.isOpen()&&d.setClasses()}),b.on("open",function(){d.$results.attr("aria-expanded","true"),d.$results.attr("aria-hidden","false"),d.setClasses(),d.ensureHighlightVisible()}),b.on("close",function(){d.$results.attr("aria-expanded","false"),d.$results.attr("aria-hidden","true"),d.$results.removeAttr("aria-activedescendant")}),b.on("results:toggle",function(){var a=d.getHighlightedResults();0!==a.length&&a.trigger("mouseup")}),b.on("results:select",function(){var a=d.getHighlightedResults();if(0!==a.length){var b=a.data("data");"true"==a.attr("aria-selected")?d.trigger("close",{}):d.trigger("select",{data:b})}}),b.on("results:previous",function(){var a=d.getHighlightedResults(),b=d.$results.find("[aria-selected]"),c=b.index(a);if(0!==c){var e=c-1;0===a.length&&(e=0);var f=b.eq(e);f.trigger("mouseenter");var g=d.$results.offset().top,h=f.offset().top,i=d.$results.scrollTop()+(h-g);0===e?d.$results.scrollTop(0):0>h-g&&d.$results.scrollTop(i)}}),b.on("results:next",function(){var a=d.getHighlightedResults(),b=d.$results.find("[aria-selected]"),c=b.index(a),e=c+1;if(!(e>=b.length)){var f=b.eq(e);f.trigger("mouseenter");var g=d.$results.offset().top+d.$results.outerHeight(!1),h=f.offset().top+f.outerHeight(!1),i=d.$results.scrollTop()+h-g;0===e?d.$results.scrollTop(0):h>g&&d.$results.scrollTop(i)}}),b.on("results:focus",function(a){a.element.addClass("select2-results__option--highlighted")}),b.on("results:message",function(a){d.displayMessage(a)}),a.fn.mousewheel&&this.$results.on("mousewheel",function(a){var b=d.$results.scrollTop(),c=d.$results.get(0).scrollHeight-b+a.deltaY,e=a.deltaY>0&&b-a.deltaY<=0,f=a.deltaY<0&&c<=d.$results.height();e?(d.$results.scrollTop(0),a.preventDefault(),a.stopPropagation()):f&&(d.$results.scrollTop(d.$results.get(0).scrollHeight-d.$results.height()),a.preventDefault(),a.stopPropagation())}),this.$results.on("mouseup",".select2-results__option[aria-selected]",function(b){var c=a(this),e=c.data("data");return"true"===c.attr("aria-selected")?void(d.options.get("multiple")?d.trigger("unselect",{originalEvent:b,data:e}):d.trigger("close",{})):void d.trigger("select",{originalEvent:b,data:e})}),this.$results.on("mouseenter",".select2-results__option[aria-selected]",function(b){var c=a(this).data("data");d.getHighlightedResults().removeClass("select2-results__option--highlighted"),d.trigger("results:focus",{data:c,element:a(this)})})},c.prototype.getHighlightedResults=function(){var a=this.$results.find(".select2-results__option--highlighted");return a},c.prototype.destroy=function(){this.$results.remove()},c.prototype.ensureHighlightVisible=function(){var a=this.getHighlightedResults();if(0!==a.length){var b=this.$results.find("[aria-selected]"),c=b.index(a),d=this.$results.offset().top,e=a.offset().top,f=this.$results.scrollTop()+(e-d),g=e-d;f-=2*a.outerHeight(!1),2>=c?this.$results.scrollTop(0):(g>this.$results.outerHeight()||0>g)&&this.$results.scrollTop(f)}},c.prototype.template=function(b,c){var d=this.options.get("templateResult"),e=this.options.get("escapeMarkup"),f=d(b,c);null==f?c.style.display="none":"string"==typeof f?c.innerHTML=e(f):a(c).append(f)},c}),b.define("select2/keys",[],function(){var a={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46};return a}),b.define("select2/selection/base",["jquery","../utils","../keys"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,b.Observable),d.prototype.render=function(){var b=a('<span class="select2-selection" role="combobox" aria-haspopup="true" aria-expanded="false"></span>');return this._tabindex=0,null!=this.$element.data("old-tabindex")?this._tabindex=this.$element.data("old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),b.attr("title",this.$element.attr("title")),b.attr("tabindex",this._tabindex),this.$selection=b,b},d.prototype.bind=function(a,b){var d=this,e=(a.id+"-container",a.id+"-results");this.container=a,this.$selection.on("focus",function(a){d.trigger("focus",a)}),this.$selection.on("blur",function(a){d._handleBlur(a)}),this.$selection.on("keydown",function(a){d.trigger("keypress",a),a.which===c.SPACE&&a.preventDefault()}),a.on("results:focus",function(a){d.$selection.attr("aria-activedescendant",a.data._resultId)}),a.on("selection:update",function(a){d.update(a.data)}),a.on("open",function(){d.$selection.attr("aria-expanded","true"),d.$selection.attr("aria-owns",e),d._attachCloseHandler(a)}),a.on("close",function(){d.$selection.attr("aria-expanded","false"),d.$selection.removeAttr("aria-activedescendant"),d.$selection.removeAttr("aria-owns"),d.$selection.focus(),d._detachCloseHandler(a)}),a.on("enable",function(){d.$selection.attr("tabindex",d._tabindex)}),a.on("disable",function(){d.$selection.attr("tabindex","-1")})},d.prototype._handleBlur=function(b){var c=this;window.setTimeout(function(){document.activeElement==c.$selection[0]||a.contains(c.$selection[0],document.activeElement)||c.trigger("blur",b)},1)},d.prototype._attachCloseHandler=function(b){a(document.body).on("mousedown.select2."+b.id,function(b){var c=a(b.target),d=c.closest(".select2"),e=a(".select2.select2-container--open");e.each(function(){var b=a(this);if(this!=d[0]){var c=b.data("element");c.select2("close")}})})},d.prototype._detachCloseHandler=function(b){a(document.body).off("mousedown.select2."+b.id)},d.prototype.position=function(a,b){var c=b.find(".selection");c.append(a)},d.prototype.destroy=function(){this._detachCloseHandler(this.container)},d.prototype.update=function(a){throw new Error("The `update` method must be defined in child classes.")},d}),b.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(a,b,c,d){function e(){e.__super__.constructor.apply(this,arguments)}return c.Extend(e,b),e.prototype.render=function(){var a=e.__super__.render.call(this);return a.addClass("select2-selection--single"),a.html('<span class="select2-selection__rendered"></span><span class="select2-selection__arrow" role="presentation"><b role="presentation"></b></span>'),a},e.prototype.bind=function(a,b){var c=this;e.__super__.bind.apply(this,arguments);var d=a.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",d),this.$selection.attr("aria-labelledby",d),this.$selection.on("mousedown",function(a){1===a.which&&c.trigger("toggle",{originalEvent:a})}),this.$selection.on("focus",function(a){}),this.$selection.on("blur",function(a){}),a.on("selection:update",function(a){c.update(a.data)})},e.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},e.prototype.display=function(a,b){var c=this.options.get("templateSelection"),d=this.options.get("escapeMarkup");return d(c(a,b))},e.prototype.selectionContainer=function(){return a("<span></span>")},e.prototype.update=function(a){if(0===a.length)return void this.clear();var b=a[0],c=this.$selection.find(".select2-selection__rendered"),d=this.display(b,c);c.empty().append(d),c.prop("title",b.title||b.text)},e}),b.define("select2/selection/multiple",["jquery","./base","../utils"],function(a,b,c){function d(a,b){d.__super__.constructor.apply(this,arguments)}return c.Extend(d,b),d.prototype.render=function(){var a=d.__super__.render.call(this);return a.addClass("select2-selection--multiple"),a.html('<ul class="select2-selection__rendered"></ul>'),a},d.prototype.bind=function(b,c){var e=this;d.__super__.bind.apply(this,arguments),this.$selection.on("click",function(a){e.trigger("toggle",{originalEvent:a})}),this.$selection.on("click",".select2-selection__choice__remove",function(b){if(!e.options.get("disabled")){var c=a(this),d=c.parent(),f=d.data("data");e.trigger("unselect",{originalEvent:b,data:f})}})},d.prototype.clear=function(){this.$selection.find(".select2-selection__rendered").empty()},d.prototype.display=function(a,b){var c=this.options.get("templateSelection"),d=this.options.get("escapeMarkup");return d(c(a,b))},d.prototype.selectionContainer=function(){var b=a('<li class="select2-selection__choice"><span class="select2-selection__choice__remove" role="presentation">×</span></li>');return b},d.prototype.update=function(a){if(this.clear(),0!==a.length){for(var b=[],d=0;d<a.length;d++){var e=a[d],f=this.selectionContainer(),g=this.display(e,f);f.append(g),f.prop("title",e.title||e.text),f.data("data",e),b.push(f)}var h=this.$selection.find(".select2-selection__rendered");c.appendMany(h,b)}},d}),b.define("select2/selection/placeholder",["../utils"],function(a){function b(a,b,c){this.placeholder=this.normalizePlaceholder(c.get("placeholder")),a.call(this,b,c)}return b.prototype.normalizePlaceholder=function(a,b){return"string"==typeof b&&(b={id:"",text:b}),b},b.prototype.createPlaceholder=function(a,b){var c=this.selectionContainer();return c.html(this.display(b)),c.addClass("select2-selection__placeholder").removeClass("select2-selection__choice"),c},b.prototype.update=function(a,b){var c=1==b.length&&b[0].id!=this.placeholder.id,d=b.length>1;if(d||c)return a.call(this,b);this.clear();var e=this.createPlaceholder(this.placeholder);this.$selection.find(".select2-selection__rendered").append(e)},b}),b.define("select2/selection/allowClear",["jquery","../keys"],function(a,b){function c(){}return c.prototype.bind=function(a,b,c){var d=this;a.call(this,b,c),null==this.placeholder&&this.options.get("debug")&&window.console&&console.error&&console.error("Select2: The `allowClear` option should be used in combination with the `placeholder` option."),this.$selection.on("mousedown",".select2-selection__clear",function(a){d._handleClear(a)}),b.on("keypress",function(a){d._handleKeyboardClear(a,b)})},c.prototype._handleClear=function(a,b){if(!this.options.get("disabled")){var c=this.$selection.find(".select2-selection__clear");if(0!==c.length){b.stopPropagation();for(var d=c.data("data"),e=0;e<d.length;e++){var f={data:d[e]};if(this.trigger("unselect",f),f.prevented)return}this.$element.val(this.placeholder.id).trigger("change"),this.trigger("toggle",{})}}},c.prototype._handleKeyboardClear=function(a,c,d){d.isOpen()||(c.which==b.DELETE||c.which==b.BACKSPACE)&&this._handleClear(c)},c.prototype.update=function(b,c){if(b.call(this,c),!(this.$selection.find(".select2-selection__placeholder").length>0||0===c.length)){var d=a('<span class="select2-selection__clear">×</span>');d.data("data",c),this.$selection.find(".select2-selection__rendered").prepend(d)}},c}),b.define("select2/selection/search",["jquery","../utils","../keys"],function(a,b,c){function d(a,b,c){a.call(this,b,c)}return d.prototype.render=function(b){var c=a('<li class="select2-search select2-search--inline"><input class="select2-search__field" type="search" tabindex="-1" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" role="textbox" aria-autocomplete="list" /></li>');this.$searchContainer=c,this.$search=c.find("input");var d=b.call(this);return this._transferTabIndex(),d},d.prototype.bind=function(a,b,d){var e=this;a.call(this,b,d),b.on("open",function(){e.$search.trigger("focus")}),b.on("close",function(){e.$search.val(""),e.$search.removeAttr("aria-activedescendant"),e.$search.trigger("focus")}),b.on("enable",function(){e.$search.prop("disabled",!1),e._transferTabIndex()}),b.on("disable",function(){e.$search.prop("disabled",!0)}),b.on("focus",function(a){e.$search.trigger("focus")}),b.on("results:focus",function(a){e.$search.attr("aria-activedescendant",a.id)}),this.$selection.on("focusin",".select2-search--inline",function(a){e.trigger("focus",a)}),this.$selection.on("focusout",".select2-search--inline",function(a){e._handleBlur(a)}),this.$selection.on("keydown",".select2-search--inline",function(a){a.stopPropagation(),e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented();var b=a.which;if(b===c.BACKSPACE&&""===e.$search.val()){var d=e.$searchContainer.prev(".select2-selection__choice");if(d.length>0){var f=d.data("data");e.searchRemoveChoice(f),a.preventDefault()}}});var f=document.documentMode,g=f&&11>=f;this.$selection.on("input.searchcheck",".select2-search--inline",function(a){return g?void e.$selection.off("input.search input.searchcheck"):void e.$selection.off("keyup.search")}),this.$selection.on("keyup.search input.search",".select2-search--inline",function(a){if(g&&"input"===a.type)return void e.$selection.off("input.search input.searchcheck");var b=a.which;b!=c.SHIFT&&b!=c.CTRL&&b!=c.ALT&&b!=c.TAB&&e.handleSearch(a)})},d.prototype._transferTabIndex=function(a){this.$search.attr("tabindex",this.$selection.attr("tabindex")),this.$selection.attr("tabindex","-1")},d.prototype.createPlaceholder=function(a,b){this.$search.attr("placeholder",b.text)},d.prototype.update=function(a,b){var c=this.$search[0]==document.activeElement;this.$search.attr("placeholder",""),a.call(this,b),this.$selection.find(".select2-selection__rendered").append(this.$searchContainer),this.resizeSearch(),c&&this.$search.focus()},d.prototype.handleSearch=function(){if(this.resizeSearch(),!this._keyUpPrevented){var a=this.$search.val();this.trigger("query",{term:a})}this._keyUpPrevented=!1},d.prototype.searchRemoveChoice=function(a,b){this.trigger("unselect",{data:b}),this.$search.val(b.text),this.handleSearch()},d.prototype.resizeSearch=function(){this.$search.css("width","25px");var a="";if(""!==this.$search.attr("placeholder"))a=this.$selection.find(".select2-selection__rendered").innerWidth();else{var b=this.$search.val().length+1;a=.75*b+"em"}this.$search.css("width",a)},d}),b.define("select2/selection/eventRelay",["jquery"],function(a){function b(){}return b.prototype.bind=function(b,c,d){var e=this,f=["open","opening","close","closing","select","selecting","unselect","unselecting"],g=["opening","closing","selecting","unselecting"];b.call(this,c,d),c.on("*",function(b,c){if(-1!==a.inArray(b,f)){c=c||{};var d=a.Event("select2:"+b,{params:c});e.$element.trigger(d),-1!==a.inArray(b,g)&&(c.prevented=d.isDefaultPrevented())}})},b}),b.define("select2/translation",["jquery","require"],function(a,b){function c(a){this.dict=a||{}}return c.prototype.all=function(){return this.dict},c.prototype.get=function(a){return this.dict[a]},c.prototype.extend=function(b){this.dict=a.extend({},b.all(),this.dict)},c._cache={},c.loadPath=function(a){if(!(a in c._cache)){var d=b(a);c._cache[a]=d}return new c(c._cache[a])},c}),b.define("select2/diacritics",[],function(){var a={"â’¶":"A","A":"A","À":"A","Ã":"A","Â":"A","Ầ":"A","Ấ":"A","Ẫ":"A","Ẩ":"A","Ã":"A","Ä€":"A","Ä‚":"A","Ằ":"A","Ắ":"A","Ẵ":"A","Ẳ":"A","Ȧ":"A","Ç ":"A","Ä":"A","Çž":"A","Ả":"A","Ã…":"A","Ǻ":"A","Ç":"A","È€":"A","È‚":"A","Ạ":"A","Ậ":"A","Ặ":"A","Ḁ":"A","Ä„":"A","Ⱥ":"A","Ɐ":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ç¢":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","â’·":"B","ï¼¢":"B","Ḃ":"B","Ḅ":"B","Ḇ":"B","Ƀ":"B","Æ‚":"B","Æ":"B","â’¸":"C","ï¼£":"C","Ć":"C","Ĉ":"C","ÄŠ":"C","ÄŒ":"C","Ç":"C","Ḉ":"C","Ƈ":"C","È»":"C","Ꜿ":"C","â’¹":"D","D":"D","Ḋ":"D","ÄŽ":"D","Ḍ":"D","á¸":"D","Ḓ":"D","Ḏ":"D","Ä":"D","Æ‹":"D","ÆŠ":"D","Ɖ":"D","ê¹":"D","DZ":"DZ","Ç„":"DZ","Dz":"Dz","Ç…":"Dz","â’º":"E","ï¼¥":"E","È":"E","É":"E","Ê":"E","Ề":"E","Ế":"E","Ễ":"E","Ể":"E","Ẽ":"E","Ä’":"E","Ḕ":"E","Ḗ":"E","Ä”":"E","Ä–":"E","Ë":"E","Ẻ":"E","Äš":"E","È„":"E","Ȇ":"E","Ẹ":"E","Ệ":"E","Ȩ":"E","Ḝ":"E","Ę":"E","Ḙ":"E","Ḛ":"E","Æ":"E","ÆŽ":"E","â’»":"F","F":"F","Ḟ":"F","Æ‘":"F","ê»":"F","â’¼":"G","G":"G","Ç´":"G","Äœ":"G","Ḡ":"G","Äž":"G","Ä ":"G","Ǧ":"G","Ä¢":"G","Ǥ":"G","Æ“":"G","êž ":"G","ê½":"G","ê¾":"G","â’½":"H","H":"H","Ĥ":"H","Ḣ":"H","Ḧ":"H","Èž":"H","Ḥ":"H","Ḩ":"H","Ḫ":"H","Ħ":"H","Ⱨ":"H","â±µ":"H","êž":"H","â’¾":"I","I":"I","ÃŒ":"I","Ã":"I","ÃŽ":"I","Ĩ":"I","Ī":"I","Ĭ":"I","Ä°":"I","Ã":"I","Ḯ":"I","Ỉ":"I","Ç":"I","Ȉ":"I","ÈŠ":"I","Ị":"I","Ä®":"I","Ḭ":"I","Æ—":"I","â’¿":"J","J":"J","Ä´":"J","Ɉ":"J","â“€":"K","K":"K","Ḱ":"K","Ǩ":"K","Ḳ":"K","Ķ":"K","Ḵ":"K","Ƙ":"K","Ⱪ":"K","ê€":"K","ê‚":"K","ê„":"K","Ꞣ":"K","â“":"L","L":"L","Ä¿":"L","Ĺ":"L","Ľ":"L","Ḷ":"L","Ḹ":"L","Ä»":"L","Ḽ":"L","Ḻ":"L","Å":"L","Ƚ":"L","â±¢":"L","â± ":"L","êˆ":"L","ê†":"L","Ꞁ":"L","LJ":"LJ","Lj":"Lj","â“‚":"M","ï¼":"M","Ḿ":"M","á¹€":"M","Ṃ":"M","â±®":"M","Æœ":"M","Ⓝ":"N","ï¼®":"N","Ǹ":"N","Ń":"N","Ñ":"N","Ṅ":"N","Ň":"N","Ṇ":"N","Å…":"N","Ṋ":"N","Ṉ":"N","È ":"N","Æ":"N","êž":"N","Ꞥ":"N","ÇŠ":"NJ","Ç‹":"Nj","â“„":"O","O":"O","Ã’":"O","Ó":"O","Ô":"O","á»’":"O","á»":"O","á»–":"O","á»”":"O","Õ":"O","Ṍ":"O","Ȭ":"O","Ṏ":"O","ÅŒ":"O","á¹":"O","á¹’":"O","ÅŽ":"O","È®":"O","È°":"O","Ö":"O","Ȫ":"O","Ỏ":"O","Å":"O","Ç‘":"O","ÈŒ":"O","ÈŽ":"O","Æ ":"O","Ờ":"O","Ớ":"O","á» ":"O","Ở":"O","Ợ":"O","Ọ":"O","Ộ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Ɔ":"O","ÆŸ":"O","êŠ":"O","êŒ":"O","Æ¢":"OI","êŽ":"OO","È¢":"OU","â“…":"P","ï¼°":"P","á¹”":"P","á¹–":"P","Ƥ":"P","â±£":"P","ê":"P","ê’":"P","ê”":"P","Ⓠ":"Q","ï¼±":"Q","ê–":"Q","ê˜":"Q","ÉŠ":"Q","Ⓡ":"R","ï¼²":"R","Å”":"R","Ṙ":"R","Ř":"R","È":"R","È’":"R","Ṛ":"R","Ṝ":"R","Å–":"R","Ṟ":"R","ÉŒ":"R","Ɽ":"R","êš":"R","Ꞧ":"R","êž‚":"R","Ⓢ":"S","ï¼³":"S","ẞ":"S","Åš":"S","Ṥ":"S","Åœ":"S","á¹ ":"S","Å ":"S","Ṧ":"S","á¹¢":"S","Ṩ":"S","Ș":"S","Åž":"S","â±¾":"S","Ꞩ":"S","êž„":"S","Ⓣ":"T","ï¼´":"T","Ṫ":"T","Ť":"T","Ṭ":"T","Èš":"T","Å¢":"T","á¹°":"T","á¹®":"T","Ŧ":"T","Ƭ":"T","Æ®":"T","Ⱦ":"T","Ꞇ":"T","Ꜩ":"TZ","â“Š":"U","ï¼µ":"U","Ù":"U","Ú":"U","Û":"U","Ũ":"U","Ṹ":"U","Ū":"U","Ṻ":"U","Ŭ":"U","Ãœ":"U","Ç›":"U","Ç—":"U","Ç•":"U","Ç™":"U","Ủ":"U","Å®":"U","Å°":"U","Ç“":"U","È”":"U","È–":"U","Ư":"U","Ừ":"U","Ứ":"U","á»®":"U","Ử":"U","á»°":"U","Ụ":"U","á¹²":"U","Ų":"U","Ṷ":"U","á¹´":"U","É„":"U","â“‹":"V","V":"V","á¹¼":"V","á¹¾":"V","Ʋ":"V","êž":"V","É…":"V","ê ":"VY","â“Œ":"W","ï¼·":"W","Ẁ":"W","Ẃ":"W","Å´":"W","Ẇ":"W","Ẅ":"W","Ẉ":"W","â±²":"W","â“":"X","X":"X","Ẋ":"X","Ẍ":"X","â“Ž":"Y","ï¼¹":"Y","Ỳ":"Y","Ã":"Y","Ŷ":"Y","Ỹ":"Y","Ȳ":"Y","Ẏ":"Y","Ÿ":"Y","Ỷ":"Y","á»´":"Y","Ƴ":"Y","ÉŽ":"Y","Ỿ":"Y","â“":"Z","Z":"Z","Ź":"Z","áº":"Z","Å»":"Z","Ž":"Z","Ẓ":"Z","Ẕ":"Z","Ƶ":"Z","Ȥ":"Z","Ɀ":"Z","Ⱬ":"Z","ê¢":"Z","â“":"a","ï½":"a","ẚ":"a","à ":"a","á":"a","â":"a","ầ":"a","ấ":"a","ẫ":"a","ẩ":"a","ã":"a","Ä":"a","ă":"a","ằ":"a","ắ":"a","ẵ":"a","ẳ":"a","ȧ":"a","Ç¡":"a","ä":"a","ÇŸ":"a","ả":"a","Ã¥":"a","Ç»":"a","ÇŽ":"a","È":"a","ȃ":"a","ạ":"a","áº":"a","ặ":"a","á¸":"a","Ä…":"a","â±¥":"a","É":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","Ç£":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","â“‘":"b","b":"b","ḃ":"b","ḅ":"b","ḇ":"b","Æ€":"b","ƃ":"b","É“":"b","â“’":"c","c":"c","ć":"c","ĉ":"c","Ä‹":"c","Ä":"c","ç":"c","ḉ":"c","ƈ":"c","ȼ":"c","ꜿ":"c","ↄ":"c","â““":"d","d":"d","ḋ":"d","Ä":"d","á¸":"d","ḑ":"d","ḓ":"d","á¸":"d","Ä‘":"d","ÆŒ":"d","É–":"d","É—":"d","êº":"d","dz":"dz","dž":"dz","â“”":"e","ï½…":"e","è":"e","é":"e","ê":"e","á»":"e","ế":"e","á»…":"e","ể":"e","ẽ":"e","Ä“":"e","ḕ":"e","ḗ":"e","Ä•":"e","Ä—":"e","ë":"e","ẻ":"e","Ä›":"e","È…":"e","ȇ":"e","ẹ":"e","ệ":"e","È©":"e","á¸":"e","Ä™":"e","ḙ":"e","ḛ":"e","ɇ":"e","É›":"e","Ç":"e","â“•":"f","f":"f","ḟ":"f","Æ’":"f","ê¼":"f","â“–":"g","g":"g","ǵ":"g","Ä":"g","ḡ":"g","ÄŸ":"g","Ä¡":"g","ǧ":"g","Ä£":"g","Ç¥":"g","É ":"g","êž¡":"g","áµ¹":"g","ê¿":"g","â“—":"h","h":"h","Ä¥":"h","ḣ":"h","ḧ":"h","ÈŸ":"h","ḥ":"h","ḩ":"h","ḫ":"h","ẖ":"h","ħ":"h","ⱨ":"h","ⱶ":"h","É¥":"h","Æ•":"hv","ⓘ":"i","i":"i","ì":"i","Ã":"i","î":"i","Ä©":"i","Ä«":"i","Ä":"i","ï":"i","ḯ":"i","ỉ":"i","Ç":"i","ȉ":"i","È‹":"i","ị":"i","į":"i","á¸":"i","ɨ":"i","ı":"i","â“™":"j","j":"j","ĵ":"j","Ç°":"j","ɉ":"j","â“š":"k","k":"k","ḱ":"k","Ç©":"k","ḳ":"k","Ä·":"k","ḵ":"k","Æ™":"k","ⱪ":"k","ê":"k","êƒ":"k","ê…":"k","ꞣ":"k","â“›":"l","l":"l","Å€":"l","ĺ":"l","ľ":"l","ḷ":"l","ḹ":"l","ļ":"l","ḽ":"l","ḻ":"l","Å¿":"l","Å‚":"l","Æš":"l","É«":"l","ⱡ":"l","ê‰":"l","êž":"l","ê‡":"l","lj":"lj","â“œ":"m","ï½":"m","ḿ":"m","á¹":"m","ṃ":"m","ɱ":"m","ɯ":"m","â“":"n","n":"n","ǹ":"n","Å„":"n","ñ":"n","á¹…":"n","ň":"n","ṇ":"n","ņ":"n","ṋ":"n","ṉ":"n","Æž":"n","ɲ":"n","ʼn":"n","êž‘":"n","ꞥ":"n","ÇŒ":"nj","â“ž":"o","ï½":"o","ò":"o","ó":"o","ô":"o","ồ":"o","ố":"o","á»—":"o","ổ":"o","õ":"o","á¹":"o","È":"o","á¹":"o","Å":"o","ṑ":"o","ṓ":"o","Å":"o","ȯ":"o","ȱ":"o","ö":"o","È«":"o","á»":"o","Å‘":"o","Ç’":"o","È":"o","È":"o","Æ¡":"o","á»":"o","á»›":"o","ỡ":"o","ở":"o","ợ":"o","á»":"o","á»™":"o","Ç«":"o","Ç":"o","ø":"o","Ç¿":"o","É”":"o","ê‹":"o","ê":"o","ɵ":"o","Æ£":"oi","È£":"ou","ê":"oo","â“Ÿ":"p","ï½":"p","ṕ":"p","á¹—":"p","Æ¥":"p","áµ½":"p","ê‘":"p","ê“":"p","ê•":"p","â“ ":"q","q":"q","É‹":"q","ê—":"q","ê™":"q","â“¡":"r","ï½’":"r","Å•":"r","á¹™":"r","Å™":"r","È‘":"r","È“":"r","á¹›":"r","á¹":"r","Å—":"r","ṟ":"r","É":"r","ɽ":"r","ê›":"r","ꞧ":"r","ꞃ":"r","â“¢":"s","s":"s","ß":"s","Å›":"s","á¹¥":"s","Å":"s","ṡ":"s","Å¡":"s","ṧ":"s","á¹£":"s","ṩ":"s","È™":"s","ÅŸ":"s","È¿":"s","êž©":"s","êž…":"s","ẛ":"s","â“£":"t","ï½”":"t","ṫ":"t","ẗ":"t","Å¥":"t","á¹":"t","È›":"t","Å£":"t","á¹±":"t","ṯ":"t","ŧ":"t","Æ":"t","ʈ":"t","ⱦ":"t","ꞇ":"t","ꜩ":"tz","ⓤ":"u","u":"u","ù":"u","ú":"u","û":"u","Å©":"u","á¹¹":"u","Å«":"u","á¹»":"u","Å":"u","ü":"u","Çœ":"u","ǘ":"u","Ç–":"u","Çš":"u","ủ":"u","ů":"u","ű":"u","Ç”":"u","È•":"u","È—":"u","Æ°":"u","ừ":"u","ứ":"u","ữ":"u","á»":"u","á»±":"u","ụ":"u","á¹³":"u","ų":"u","á¹·":"u","á¹µ":"u","ʉ":"u","â“¥":"v","ï½–":"v","á¹½":"v","ṿ":"v","Ê‹":"v","êŸ":"v","ÊŒ":"v","ê¡":"vy","ⓦ":"w","ï½—":"w","áº":"w","ẃ":"w","ŵ":"w","ẇ":"w","ẅ":"w","ẘ":"w","ẉ":"w","â±³":"w","ⓧ":"x","x":"x","ẋ":"x","áº":"x","ⓨ":"y","ï½™":"y","ỳ":"y","ý":"y","Å·":"y","ỹ":"y","ȳ":"y","áº":"y","ÿ":"y","á»·":"y","ẙ":"y","ỵ":"y","Æ´":"y","É":"y","ỿ":"y","â“©":"z","z":"z","ź":"z","ẑ":"z","ż":"z","ž":"z","ẓ":"z","ẕ":"z","ƶ":"z","È¥":"z","É€":"z","ⱬ":"z","ê£":"z","Ά":"Α","Έ":"Ε","Ή":"Η","Ί":"Ι","Ϊ":"Ι","ÎŒ":"Ο","ÎŽ":"Î¥","Ϋ":"Î¥","Î":"Ω","ά":"α","Î":"ε","ή":"η","ί":"ι","ÏŠ":"ι","Î":"ι","ÏŒ":"ο","Ï":"Ï…","Ï‹":"Ï…","ΰ":"Ï…","ω":"ω","Ï‚":"σ"};return a}),b.define("select2/data/base",["../utils"],function(a){function b(a,c){b.__super__.constructor.call(this)}return a.Extend(b,a.Observable),b.prototype.current=function(a){throw new Error("The `current` method must be defined in child classes.")},b.prototype.query=function(a,b){throw new Error("The `query` method must be defined in child classes.")},b.prototype.bind=function(a,b){},b.prototype.destroy=function(){},b.prototype.generateResultId=function(b,c){var d=b.id+"-result-";return d+=a.generateChars(4),d+=null!=c.id?"-"+c.id.toString():"-"+a.generateChars(4)},b}),b.define("select2/data/select",["./base","../utils","jquery"],function(a,b,c){function d(a,b){this.$element=a,this.options=b,d.__super__.constructor.call(this)}return b.Extend(d,a),d.prototype.current=function(a){var b=[],d=this;this.$element.find(":selected").each(function(){var a=c(this),e=d.item(a);b.push(e)}),a(b)},d.prototype.select=function(a){var b=this;if(a.selected=!0,c(a.element).is("option"))return a.element.selected=!0,void this.$element.trigger("change");if(this.$element.prop("multiple"))this.current(function(d){var e=[];a=[a],a.push.apply(a,d);for(var f=0;f<a.length;f++){var g=a[f].id;-1===c.inArray(g,e)&&e.push(g)}b.$element.val(e),b.$element.trigger("change")});else{var d=a.id;this.$element.val(d),this.$element.trigger("change")}},d.prototype.unselect=function(a){var b=this;if(this.$element.prop("multiple"))return a.selected=!1, c(a.element).is("option")?(a.element.selected=!1,void this.$element.trigger("change")):void this.current(function(d){for(var e=[],f=0;f<d.length;f++){var g=d[f].id;g!==a.id&&-1===c.inArray(g,e)&&e.push(g)}b.$element.val(e),b.$element.trigger("change")})},d.prototype.bind=function(a,b){var c=this;this.container=a,a.on("select",function(a){c.select(a.data)}),a.on("unselect",function(a){c.unselect(a.data)})},d.prototype.destroy=function(){this.$element.find("*").each(function(){c.removeData(this,"data")})},d.prototype.query=function(a,b){var d=[],e=this,f=this.$element.children();f.each(function(){var b=c(this);if(b.is("option")||b.is("optgroup")){var f=e.item(b),g=e.matches(a,f);null!==g&&d.push(g)}}),b({results:d})},d.prototype.addOptions=function(a){b.appendMany(this.$element,a)},d.prototype.option=function(a){var b;a.children?(b=document.createElement("optgroup"),b.label=a.text):(b=document.createElement("option"),void 0!==b.textContent?b.textContent=a.text:b.innerText=a.text),a.id&&(b.value=a.id),a.disabled&&(b.disabled=!0),a.selected&&(b.selected=!0),a.title&&(b.title=a.title);var d=c(b),e=this._normalizeItem(a);return e.element=b,c.data(b,"data",e),d},d.prototype.item=function(a){var b={};if(b=c.data(a[0],"data"),null!=b)return b;if(a.is("option"))b={id:a.val(),text:a.text(),disabled:a.prop("disabled"),selected:a.prop("selected"),title:a.prop("title")};else if(a.is("optgroup")){b={text:a.prop("label"),children:[],title:a.prop("title")};for(var d=a.children("option"),e=[],f=0;f<d.length;f++){var g=c(d[f]),h=this.item(g);e.push(h)}b.children=e}return b=this._normalizeItem(b),b.element=a[0],c.data(a[0],"data",b),b},d.prototype._normalizeItem=function(a){c.isPlainObject(a)||(a={id:a,text:a}),a=c.extend({},{text:""},a);var b={selected:!1,disabled:!1};return null!=a.id&&(a.id=a.id.toString()),null!=a.text&&(a.text=a.text.toString()),null==a._resultId&&a.id&&null!=this.container&&(a._resultId=this.generateResultId(this.container,a)),c.extend({},b,a)},d.prototype.matches=function(a,b){var c=this.options.get("matcher");return c(a,b)},d}),b.define("select2/data/array",["./select","../utils","jquery"],function(a,b,c){function d(a,b){var c=b.get("data")||[];d.__super__.constructor.call(this,a,b),this.addOptions(this.convertToOptions(c))}return b.Extend(d,a),d.prototype.select=function(a){var b=this.$element.find("option").filter(function(b,c){return c.value==a.id.toString()});0===b.length&&(b=this.option(a),this.addOptions(b)),d.__super__.select.call(this,a)},d.prototype.convertToOptions=function(a){function d(a){return function(){return c(this).val()==a.id}}for(var e=this,f=this.$element.find("option"),g=f.map(function(){return e.item(c(this)).id}).get(),h=[],i=0;i<a.length;i++){var j=this._normalizeItem(a[i]);if(c.inArray(j.id,g)>=0){var k=f.filter(d(j)),l=this.item(k),m=c.extend(!0,{},j,l),n=this.option(m);k.replaceWith(n)}else{var o=this.option(j);if(j.children){var p=this.convertToOptions(j.children);b.appendMany(o,p)}h.push(o)}}return h},d}),b.define("select2/data/ajax",["./array","../utils","jquery"],function(a,b,c){function d(a,b){this.ajaxOptions=this._applyDefaults(b.get("ajax")),null!=this.ajaxOptions.processResults&&(this.processResults=this.ajaxOptions.processResults),d.__super__.constructor.call(this,a,b)}return b.Extend(d,a),d.prototype._applyDefaults=function(a){var b={data:function(a){return c.extend({},a,{q:a.term})},transport:function(a,b,d){var e=c.ajax(a);return e.then(b),e.fail(d),e}};return c.extend({},b,a,!0)},d.prototype.processResults=function(a){return a},d.prototype.query=function(a,b){function d(){var d=f.transport(f,function(d){var f=e.processResults(d,a);e.options.get("debug")&&window.console&&console.error&&(f&&f.results&&c.isArray(f.results)||console.error("Select2: The AJAX results did not return an array in the `results` key of the response.")),b(f)},function(){e.trigger("results:message",{message:"errorLoading"})});e._request=d}var e=this;null!=this._request&&(c.isFunction(this._request.abort)&&this._request.abort(),this._request=null);var f=c.extend({type:"GET"},this.ajaxOptions);"function"==typeof f.url&&(f.url=f.url.call(this.$element,a)),"function"==typeof f.data&&(f.data=f.data.call(this.$element,a)),this.ajaxOptions.delay&&""!==a.term?(this._queryTimeout&&window.clearTimeout(this._queryTimeout),this._queryTimeout=window.setTimeout(d,this.ajaxOptions.delay)):d()},d}),b.define("select2/data/tags",["jquery"],function(a){function b(b,c,d){var e=d.get("tags"),f=d.get("createTag");void 0!==f&&(this.createTag=f);var g=d.get("insertTag");if(void 0!==g&&(this.insertTag=g),b.call(this,c,d),a.isArray(e))for(var h=0;h<e.length;h++){var i=e[h],j=this._normalizeItem(i),k=this.option(j);this.$element.append(k)}}return b.prototype.query=function(a,b,c){function d(a,f){for(var g=a.results,h=0;h<g.length;h++){var i=g[h],j=null!=i.children&&!d({results:i.children},!0),k=i.text===b.term;if(k||j)return f?!1:(a.data=g,void c(a))}if(f)return!0;var l=e.createTag(b);if(null!=l){var m=e.option(l);m.attr("data-select2-tag",!0),e.addOptions([m]),e.insertTag(g,l)}a.results=g,c(a)}var e=this;return this._removeOldTags(),null==b.term||null!=b.page?void a.call(this,b,c):void a.call(this,b,d)},b.prototype.createTag=function(b,c){var d=a.trim(c.term);return""===d?null:{id:d,text:d}},b.prototype.insertTag=function(a,b,c){b.unshift(c)},b.prototype._removeOldTags=function(b){var c=(this._lastTag,this.$element.find("option[data-select2-tag]"));c.each(function(){this.selected||a(this).remove()})},b}),b.define("select2/data/tokenizer",["jquery"],function(a){function b(a,b,c){var d=c.get("tokenizer");void 0!==d&&(this.tokenizer=d),a.call(this,b,c)}return b.prototype.bind=function(a,b,c){a.call(this,b,c),this.$search=b.dropdown.$search||b.selection.$search||c.find(".select2-search__field")},b.prototype.query=function(a,b,c){function d(a){e.trigger("select",{data:a})}var e=this;b.term=b.term||"";var f=this.tokenizer(b,this.options,d);f.term!==b.term&&(this.$search.length&&(this.$search.val(f.term),this.$search.focus()),b.term=f.term),a.call(this,b,c)},b.prototype.tokenizer=function(b,c,d,e){for(var f=d.get("tokenSeparators")||[],g=c.term,h=0,i=this.createTag||function(a){return{id:a.term,text:a.term}};h<g.length;){var j=g[h];if(-1!==a.inArray(j,f)){var k=g.substr(0,h),l=a.extend({},c,{term:k}),m=i(l);null!=m?(e(m),g=g.substr(h+1)||"",h=0):h++}else h++}return{term:g}},b}),b.define("select2/data/minimumInputLength",[],function(){function a(a,b,c){this.minimumInputLength=c.get("minimumInputLength"),a.call(this,b,c)}return a.prototype.query=function(a,b,c){return b.term=b.term||"",b.term.length<this.minimumInputLength?void this.trigger("results:message",{message:"inputTooShort",args:{minimum:this.minimumInputLength,input:b.term,params:b}}):void a.call(this,b,c)},a}),b.define("select2/data/maximumInputLength",[],function(){function a(a,b,c){this.maximumInputLength=c.get("maximumInputLength"),a.call(this,b,c)}return a.prototype.query=function(a,b,c){return b.term=b.term||"",this.maximumInputLength>0&&b.term.length>this.maximumInputLength?void this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:b.term,params:b}}):void a.call(this,b,c)},a}),b.define("select2/data/maximumSelectionLength",[],function(){function a(a,b,c){this.maximumSelectionLength=c.get("maximumSelectionLength"),a.call(this,b,c)}return a.prototype.query=function(a,b,c){var d=this;this.current(function(e){var f=null!=e?e.length:0;return d.maximumSelectionLength>0&&f>=d.maximumSelectionLength?void d.trigger("results:message",{message:"maximumSelected",args:{maximum:d.maximumSelectionLength}}):void a.call(d,b,c)})},a}),b.define("select2/dropdown",["jquery","./utils"],function(a,b){function c(a,b){this.$element=a,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('<span class="select2-dropdown"><span class="select2-results"></span></span>');return b.attr("dir",this.options.get("dir")),this.$dropdown=b,b},c.prototype.bind=function(){},c.prototype.position=function(a,b){},c.prototype.destroy=function(){this.$dropdown.remove()},c}),b.define("select2/dropdown/search",["jquery","../utils"],function(a,b){function c(){}return c.prototype.render=function(b){var c=b.call(this),d=a('<span class="select2-search select2-search--dropdown"><input class="select2-search__field" type="search" tabindex="-1" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" role="textbox" /></span>');return this.$searchContainer=d,this.$search=d.find("input"),c.prepend(d),c},c.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),this.$search.on("keydown",function(a){e.trigger("keypress",a),e._keyUpPrevented=a.isDefaultPrevented()}),this.$search.on("input",function(b){a(this).off("keyup")}),this.$search.on("keyup input",function(a){e.handleSearch(a)}),c.on("open",function(){e.$search.attr("tabindex",0),e.$search.focus(),window.setTimeout(function(){e.$search.focus()},0)}),c.on("close",function(){e.$search.attr("tabindex",-1),e.$search.val("")}),c.on("results:all",function(a){if(null==a.query.term||""===a.query.term){var b=e.showSearch(a);b?e.$searchContainer.removeClass("select2-search--hide"):e.$searchContainer.addClass("select2-search--hide")}})},c.prototype.handleSearch=function(a){if(!this._keyUpPrevented){var b=this.$search.val();this.trigger("query",{term:b})}this._keyUpPrevented=!1},c.prototype.showSearch=function(a,b){return!0},c}),b.define("select2/dropdown/hidePlaceholder",[],function(){function a(a,b,c,d){this.placeholder=this.normalizePlaceholder(c.get("placeholder")),a.call(this,b,c,d)}return a.prototype.append=function(a,b){b.results=this.removePlaceholder(b.results),a.call(this,b)},a.prototype.normalizePlaceholder=function(a,b){return"string"==typeof b&&(b={id:"",text:b}),b},a.prototype.removePlaceholder=function(a,b){for(var c=b.slice(0),d=b.length-1;d>=0;d--){var e=b[d];this.placeholder.id===e.id&&c.splice(d,1)}return c},a}),b.define("select2/dropdown/infiniteScroll",["jquery"],function(a){function b(a,b,c,d){this.lastParams={},a.call(this,b,c,d),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return b.prototype.append=function(a,b){this.$loadingMore.remove(),this.loading=!1,a.call(this,b),this.showLoadingMore(b)&&this.$results.append(this.$loadingMore)},b.prototype.bind=function(b,c,d){var e=this;b.call(this,c,d),c.on("query",function(a){e.lastParams=a,e.loading=!0}),c.on("query:append",function(a){e.lastParams=a,e.loading=!0}),this.$results.on("scroll",function(){var b=a.contains(document.documentElement,e.$loadingMore[0]);if(!e.loading&&b){var c=e.$results.offset().top+e.$results.outerHeight(!1),d=e.$loadingMore.offset().top+e.$loadingMore.outerHeight(!1);c+50>=d&&e.loadMore()}})},b.prototype.loadMore=function(){this.loading=!0;var b=a.extend({},{page:1},this.lastParams);b.page++,this.trigger("query:append",b)},b.prototype.showLoadingMore=function(a,b){return b.pagination&&b.pagination.more},b.prototype.createLoadingMore=function(){var b=a('<li class="select2-results__option select2-results__option--load-more"role="treeitem" aria-disabled="true"></li>'),c=this.options.get("translations").get("loadingMore");return b.html(c(this.lastParams)),b},b}),b.define("select2/dropdown/attachBody",["jquery","../utils"],function(a,b){function c(b,c,d){this.$dropdownParent=d.get("dropdownParent")||a(document.body),b.call(this,c,d)}return c.prototype.bind=function(a,b,c){var d=this,e=!1;a.call(this,b,c),b.on("open",function(){d._showDropdown(),d._attachPositioningHandler(b),e||(e=!0,b.on("results:all",function(){d._positionDropdown(),d._resizeDropdown()}),b.on("results:append",function(){d._positionDropdown(),d._resizeDropdown()}))}),b.on("close",function(){d._hideDropdown(),d._detachPositioningHandler(b)}),this.$dropdownContainer.on("mousedown",function(a){a.stopPropagation()})},c.prototype.destroy=function(a){a.call(this),this.$dropdownContainer.remove()},c.prototype.position=function(a,b,c){b.attr("class",c.attr("class")),b.removeClass("select2"),b.addClass("select2-container--open"),b.css({position:"absolute",top:-999999}),this.$container=c},c.prototype.render=function(b){var c=a("<span></span>"),d=b.call(this);return c.append(d),this.$dropdownContainer=c,c},c.prototype._hideDropdown=function(a){this.$dropdownContainer.detach()},c.prototype._attachPositioningHandler=function(c,d){var e=this,f="scroll.select2."+d.id,g="resize.select2."+d.id,h="orientationchange.select2."+d.id,i=this.$container.parents().filter(b.hasScroll);i.each(function(){a(this).data("select2-scroll-position",{x:a(this).scrollLeft(),y:a(this).scrollTop()})}),i.on(f,function(b){var c=a(this).data("select2-scroll-position");a(this).scrollTop(c.y)}),a(window).on(f+" "+g+" "+h,function(a){e._positionDropdown(),e._resizeDropdown()})},c.prototype._detachPositioningHandler=function(c,d){var e="scroll.select2."+d.id,f="resize.select2."+d.id,g="orientationchange.select2."+d.id,h=this.$container.parents().filter(b.hasScroll);h.off(e),a(window).off(e+" "+f+" "+g)},c.prototype._positionDropdown=function(){var b=a(window),c=this.$dropdown.hasClass("select2-dropdown--above"),d=this.$dropdown.hasClass("select2-dropdown--below"),e=null,f=this.$container.offset();f.bottom=f.top+this.$container.outerHeight(!1);var g={height:this.$container.outerHeight(!1)};g.top=f.top,g.bottom=f.top+g.height;var h={height:this.$dropdown.outerHeight(!1)},i={top:b.scrollTop(),bottom:b.scrollTop()+b.height()},j=i.top<f.top-h.height,k=i.bottom>f.bottom+h.height,l={left:f.left,top:g.bottom},m=this.$dropdownParent;"static"===m.css("position")&&(m=m.offsetParent());var n=m.offset();l.top-=n.top,l.left-=n.left,c||d||(e="below"),k||!j||c?!j&&k&&c&&(e="below"):e="above",("above"==e||c&&"below"!==e)&&(l.top=g.top-h.height),null!=e&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+e),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+e)),this.$dropdownContainer.css(l)},c.prototype._resizeDropdown=function(){var a={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(a.minWidth=a.width,a.width="auto"),this.$dropdown.css(a)},c.prototype._showDropdown=function(a){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},c}),b.define("select2/dropdown/minimumResultsForSearch",[],function(){function a(b){for(var c=0,d=0;d<b.length;d++){var e=b[d];e.children?c+=a(e.children):c++}return c}function b(a,b,c,d){this.minimumResultsForSearch=c.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=1/0),a.call(this,b,c,d)}return b.prototype.showSearch=function(b,c){return a(c.data.results)<this.minimumResultsForSearch?!1:b.call(this,c)},b}),b.define("select2/dropdown/selectOnClose",[],function(){function a(){}return a.prototype.bind=function(a,b,c){var d=this;a.call(this,b,c),b.on("close",function(){d._handleSelectOnClose()})},a.prototype._handleSelectOnClose=function(){var a=this.getHighlightedResults();if(!(a.length<1)){var b=a.data("data");null!=b.element&&b.element.selected||null==b.element&&b.selected||this.trigger("select",{data:b})}},a}),b.define("select2/dropdown/closeOnSelect",[],function(){function a(){}return a.prototype.bind=function(a,b,c){var d=this;a.call(this,b,c),b.on("select",function(a){d._selectTriggered(a)}),b.on("unselect",function(a){d._selectTriggered(a)})},a.prototype._selectTriggered=function(a,b){var c=b.originalEvent;c&&c.ctrlKey||this.trigger("close",{})},a}),b.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(a){var b=a.input.length-a.maximum,c="Please delete "+b+" character";return 1!=b&&(c+="s"),c},inputTooShort:function(a){var b=a.minimum-a.input.length,c="Please enter "+b+" or more characters";return c},loadingMore:function(){return"Loading more results…"},maximumSelected:function(a){var b="You can only select "+a.maximum+" item";return 1!=a.maximum&&(b+="s"),b},noResults:function(){return"No results found"},searching:function(){return"Searching…"}}}),b.define("select2/defaults",["jquery","require","./results","./selection/single","./selection/multiple","./selection/placeholder","./selection/allowClear","./selection/search","./selection/eventRelay","./utils","./translation","./diacritics","./data/select","./data/array","./data/ajax","./data/tags","./data/tokenizer","./data/minimumInputLength","./data/maximumInputLength","./data/maximumSelectionLength","./dropdown","./dropdown/search","./dropdown/hidePlaceholder","./dropdown/infiniteScroll","./dropdown/attachBody","./dropdown/minimumResultsForSearch","./dropdown/selectOnClose","./dropdown/closeOnSelect","./i18n/en"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C){function D(){this.reset()}D.prototype.apply=function(l){if(l=a.extend(!0,{},this.defaults,l),null==l.dataAdapter){if(null!=l.ajax?l.dataAdapter=o:null!=l.data?l.dataAdapter=n:l.dataAdapter=m,l.minimumInputLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,r)),l.maximumInputLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,s)),l.maximumSelectionLength>0&&(l.dataAdapter=j.Decorate(l.dataAdapter,t)),l.tags&&(l.dataAdapter=j.Decorate(l.dataAdapter,p)),(null!=l.tokenSeparators||null!=l.tokenizer)&&(l.dataAdapter=j.Decorate(l.dataAdapter,q)),null!=l.query){var C=b(l.amdBase+"compat/query");l.dataAdapter=j.Decorate(l.dataAdapter,C)}if(null!=l.initSelection){var D=b(l.amdBase+"compat/initSelection");l.dataAdapter=j.Decorate(l.dataAdapter,D)}}if(null==l.resultsAdapter&&(l.resultsAdapter=c,null!=l.ajax&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,x)),null!=l.placeholder&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,w)),l.selectOnClose&&(l.resultsAdapter=j.Decorate(l.resultsAdapter,A))),null==l.dropdownAdapter){if(l.multiple)l.dropdownAdapter=u;else{var E=j.Decorate(u,v);l.dropdownAdapter=E}if(0!==l.minimumResultsForSearch&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,z)),l.closeOnSelect&&(l.dropdownAdapter=j.Decorate(l.dropdownAdapter,B)),null!=l.dropdownCssClass||null!=l.dropdownCss||null!=l.adaptDropdownCssClass){var F=b(l.amdBase+"compat/dropdownCss");l.dropdownAdapter=j.Decorate(l.dropdownAdapter,F)}l.dropdownAdapter=j.Decorate(l.dropdownAdapter,y)}if(null==l.selectionAdapter){if(l.multiple?l.selectionAdapter=e:l.selectionAdapter=d,null!=l.placeholder&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,f)),l.allowClear&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,g)),l.multiple&&(l.selectionAdapter=j.Decorate(l.selectionAdapter,h)),null!=l.containerCssClass||null!=l.containerCss||null!=l.adaptContainerCssClass){var G=b(l.amdBase+"compat/containerCss");l.selectionAdapter=j.Decorate(l.selectionAdapter,G)}l.selectionAdapter=j.Decorate(l.selectionAdapter,i)}if("string"==typeof l.language)if(l.language.indexOf("-")>0){var H=l.language.split("-"),I=H[0];l.language=[l.language,I]}else l.language=[l.language];if(a.isArray(l.language)){var J=new k;l.language.push("en");for(var K=l.language,L=0;L<K.length;L++){var M=K[L],N={};try{N=k.loadPath(M)}catch(O){try{M=this.defaults.amdLanguageBase+M,N=k.loadPath(M)}catch(P){l.debug&&window.console&&console.warn&&console.warn('Select2: The language file for "'+M+'" could not be automatically loaded. A fallback will be used instead.');continue}}J.extend(N)}l.translations=J}else{var Q=k.loadPath(this.defaults.amdLanguageBase+"en"),R=new k(l.language);R.extend(Q),l.translations=R}return l},D.prototype.reset=function(){function b(a){function b(a){return l[a]||a}return a.replace(/[^\u0000-\u007E]/g,b)}function c(d,e){if(""===a.trim(d.term))return e;if(e.children&&e.children.length>0){for(var f=a.extend(!0,{},e),g=e.children.length-1;g>=0;g--){var h=e.children[g],i=c(d,h);null==i&&f.children.splice(g,1)}return f.children.length>0?f:c(d,f)}var j=b(e.text).toUpperCase(),k=b(d.term).toUpperCase();return j.indexOf(k)>-1?e:null}this.defaults={amdBase:"./",amdLanguageBase:"./i18n/",closeOnSelect:!0,debug:!1,dropdownAutoWidth:!1,escapeMarkup:j.escapeMarkup,language:C,matcher:c,minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:!1,sorter:function(a){return a},templateResult:function(a){return a.text},templateSelection:function(a){return a.text},theme:"default",width:"resolve"}},D.prototype.set=function(b,c){var d=a.camelCase(b),e={};e[d]=c;var f=j._convertData(e);a.extend(this.defaults,f)};var E=new D;return E}),b.define("select2/options",["require","jquery","./defaults","./utils"],function(a,b,c,d){function e(b,e){if(this.options=b,null!=e&&this.fromElement(e),this.options=c.apply(this.options),e&&e.is("input")){var f=a(this.get("amdBase")+"compat/inputData");this.options.dataAdapter=d.Decorate(this.options.dataAdapter,f)}}return e.prototype.fromElement=function(a){var c=["select2"];null==this.options.multiple&&(this.options.multiple=a.prop("multiple")),null==this.options.disabled&&(this.options.disabled=a.prop("disabled")),null==this.options.language&&(a.prop("lang")?this.options.language=a.prop("lang").toLowerCase():a.closest("[lang]").prop("lang")&&(this.options.language=a.closest("[lang]").prop("lang"))),null==this.options.dir&&(a.prop("dir")?this.options.dir=a.prop("dir"):a.closest("[dir]").prop("dir")?this.options.dir=a.closest("[dir]").prop("dir"):this.options.dir="ltr"),a.prop("disabled",this.options.disabled),a.prop("multiple",this.options.multiple),a.data("select2Tags")&&(this.options.debug&&window.console&&console.warn&&console.warn('Select2: The `data-select2-tags` attribute has been changed to use the `data-data` and `data-tags="true"` attributes and will be removed in future versions of Select2.'),a.data("data",a.data("select2Tags")),a.data("tags",!0)),a.data("ajaxUrl")&&(this.options.debug&&window.console&&console.warn&&console.warn("Select2: The `data-ajax-url` attribute has been changed to `data-ajax--url` and support for the old attribute will be removed in future versions of Select2."),a.attr("ajax--url",a.data("ajaxUrl")),a.data("ajax--url",a.data("ajaxUrl")));var e={};e=b.fn.jquery&&"1."==b.fn.jquery.substr(0,2)&&a[0].dataset?b.extend(!0,{},a[0].dataset,a.data()):a.data();var f=b.extend(!0,{},e);f=d._convertData(f);for(var g in f)b.inArray(g,c)>-1||(b.isPlainObject(this.options[g])?b.extend(this.options[g],f[g]):this.options[g]=f[g]);return this},e.prototype.get=function(a){return this.options[a]},e.prototype.set=function(a,b){this.options[a]=b},e}),b.define("select2/core",["jquery","./options","./utils","./keys"],function(a,b,c,d){var e=function(a,c){null!=a.data("select2")&&a.data("select2").destroy(),this.$element=a,this.id=this._generateId(a),c=c||{},this.options=new b(c,a),e.__super__.constructor.call(this);var d=a.attr("tabindex")||0;a.data("old-tabindex",d),a.attr("tabindex","-1");var f=this.options.get("dataAdapter");this.dataAdapter=new f(a,this.options);var g=this.render();this._placeContainer(g);var h=this.options.get("selectionAdapter");this.selection=new h(a,this.options),this.$selection=this.selection.render(),this.selection.position(this.$selection,g);var i=this.options.get("dropdownAdapter");this.dropdown=new i(a,this.options),this.$dropdown=this.dropdown.render(),this.dropdown.position(this.$dropdown,g);var j=this.options.get("resultsAdapter");this.results=new j(a,this.options,this.dataAdapter),this.$results=this.results.render(),this.results.position(this.$results,this.$dropdown);var k=this;this._bindAdapters(),this._registerDomEvents(),this._registerDataEvents(),this._registerSelectionEvents(),this._registerDropdownEvents(),this._registerResultsEvents(),this._registerEvents(),this.dataAdapter.current(function(a){k.trigger("selection:update",{data:a})}),a.addClass("select2-hidden-accessible"),a.attr("aria-hidden","true"),this._syncAttributes(),a.data("select2",this)};return c.Extend(e,c.Observable),e.prototype._generateId=function(a){var b="";return b=null!=a.attr("id")?a.attr("id"):null!=a.attr("name")?a.attr("name")+"-"+c.generateChars(2):c.generateChars(4),b=b.replace(/(:|\.|\[|\]|,)/g,""),b="select2-"+b},e.prototype._placeContainer=function(a){a.insertAfter(this.$element);var b=this._resolveWidth(this.$element,this.options.get("width"));null!=b&&a.css("width",b)},e.prototype._resolveWidth=function(a,b){var c=/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if("resolve"==b){var d=this._resolveWidth(a,"style");return null!=d?d:this._resolveWidth(a,"element")}if("element"==b){var e=a.outerWidth(!1);return 0>=e?"auto":e+"px"}if("style"==b){var f=a.attr("style");if("string"!=typeof f)return null;for(var g=f.split(";"),h=0,i=g.length;i>h;h+=1){var j=g[h].replace(/\s/g,""),k=j.match(c);if(null!==k&&k.length>=1)return k[1]}return null}return b},e.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container),this.selection.bind(this,this.$container),this.dropdown.bind(this,this.$container),this.results.bind(this,this.$container)},e.prototype._registerDomEvents=function(){var b=this;this.$element.on("change.select2",function(){b.dataAdapter.current(function(a){b.trigger("selection:update",{data:a})})}),this._sync=c.bind(this._syncAttributes,this),this.$element[0].attachEvent&&this.$element[0].attachEvent("onpropertychange",this._sync);var d=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;null!=d?(this._observer=new d(function(c){a.each(c,b._sync)}),this._observer.observe(this.$element[0],{attributes:!0,subtree:!1})):this.$element[0].addEventListener&&this.$element[0].addEventListener("DOMAttrModified",b._sync,!1)},e.prototype._registerDataEvents=function(){var a=this;this.dataAdapter.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerSelectionEvents=function(){var b=this,c=["toggle","focus"];this.selection.on("toggle",function(){b.toggleDropdown()}),this.selection.on("focus",function(a){b.focus(a)}),this.selection.on("*",function(d,e){-1===a.inArray(d,c)&&b.trigger(d,e)})},e.prototype._registerDropdownEvents=function(){var a=this;this.dropdown.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerResultsEvents=function(){var a=this;this.results.on("*",function(b,c){a.trigger(b,c)})},e.prototype._registerEvents=function(){var a=this;this.on("open",function(){a.$container.addClass("select2-container--open")}),this.on("close",function(){a.$container.removeClass("select2-container--open")}),this.on("enable",function(){a.$container.removeClass("select2-container--disabled")}),this.on("disable",function(){a.$container.addClass("select2-container--disabled")}),this.on("blur",function(){a.$container.removeClass("select2-container--focus")}),this.on("query",function(b){a.isOpen()||a.trigger("open",{}),this.dataAdapter.query(b,function(c){a.trigger("results:all",{data:c,query:b})})}),this.on("query:append",function(b){this.dataAdapter.query(b,function(c){a.trigger("results:append",{data:c,query:b})})}),this.on("keypress",function(b){var c=b.which;a.isOpen()?c===d.ESC||c===d.TAB||c===d.UP&&b.altKey?(a.close(),b.preventDefault()):c===d.ENTER?(a.trigger("results:select",{}),b.preventDefault()):c===d.SPACE&&b.ctrlKey?(a.trigger("results:toggle",{}),b.preventDefault()):c===d.UP?(a.trigger("results:previous",{}),b.preventDefault()):c===d.DOWN&&(a.trigger("results:next",{}),b.preventDefault()):(c===d.ENTER||c===d.SPACE||c===d.DOWN&&b.altKey)&&(a.open(),b.preventDefault())})},e.prototype._syncAttributes=function(){this.options.set("disabled",this.$element.prop("disabled")),this.options.get("disabled")?(this.isOpen()&&this.close(),this.trigger("disable",{})):this.trigger("enable",{})},e.prototype.trigger=function(a,b){var c=e.__super__.trigger,d={open:"opening",close:"closing",select:"selecting",unselect:"unselecting"};if(void 0===b&&(b={}),a in d){var f=d[a],g={prevented:!1,name:a,args:b};if(c.call(this,f,g),g.prevented)return void(b.prevented=!0)}c.call(this,a,b)},e.prototype.toggleDropdown=function(){this.options.get("disabled")||(this.isOpen()?this.close():this.open())},e.prototype.open=function(){this.isOpen()||this.trigger("query",{})},e.prototype.close=function(){this.isOpen()&&this.trigger("close",{})},e.prototype.isOpen=function(){return this.$container.hasClass("select2-container--open")},e.prototype.hasFocus=function(){return this.$container.hasClass("select2-container--focus")},e.prototype.focus=function(a){this.hasFocus()||(this.$container.addClass("select2-container--focus"),this.trigger("focus",{}))},e.prototype.enable=function(a){this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("enable")` method has been deprecated and will be removed in later Select2 versions. Use $element.prop("disabled") instead.'),(null==a||0===a.length)&&(a=[!0]);var b=!a[0];this.$element.prop("disabled",b)},e.prototype.data=function(){this.options.get("debug")&&arguments.length>0&&window.console&&console.warn&&console.warn('Select2: Data can no longer be set using `select2("data")`. You should consider setting the value instead using `$element.val()`.');var a=[];return this.dataAdapter.current(function(b){a=b}),a},e.prototype.val=function(b){if(this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("val")` method has been deprecated and will be removed in later Select2 versions. Use $element.val() instead.'),null==b||0===b.length)return this.$element.val();var c=b[0];a.isArray(c)&&(c=a.map(c,function(a){return a.toString()})),this.$element.val(c).trigger("change")},e.prototype.destroy=function(){this.$container.remove(),this.$element[0].detachEvent&&this.$element[0].detachEvent("onpropertychange",this._sync),null!=this._observer?(this._observer.disconnect(),this._observer=null):this.$element[0].removeEventListener&&this.$element[0].removeEventListener("DOMAttrModified",this._sync,!1),this._sync=null,this.$element.off(".select2"),this.$element.attr("tabindex",this.$element.data("old-tabindex")),this.$element.removeClass("select2-hidden-accessible"),this.$element.attr("aria-hidden","false"),this.$element.removeData("select2"),this.dataAdapter.destroy(),this.selection.destroy(),this.dropdown.destroy(),this.results.destroy(),this.dataAdapter=null,this.selection=null,this.dropdown=null,this.results=null},e.prototype.render=function(){var b=a('<span class="select2 select2-container"><span class="selection"></span><span class="dropdown-wrapper" aria-hidden="true"></span></span>');return b.attr("dir",this.options.get("dir")),this.$container=b,this.$container.addClass("select2-container--"+this.options.get("theme")),b.data("element",this.$element),b},e}),b.define("jquery-mousewheel",["jquery"],function(a){return a}),b.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults"],function(a,b,c,d){if(null==a.fn.select2){var e=["open","close","destroy"];a.fn.select2=function(b){if(b=b||{},"object"==typeof b)return this.each(function(){var d=a.extend(!0,{},b);new c(a(this),d)}),this;if("string"==typeof b){var d;return this.each(function(){var c=a(this).data("select2");null==c&&window.console&&console.error&&console.error("The select2('"+b+"') method was called on an element that is not using Select2.");var e=Array.prototype.slice.call(arguments,1);d=c[b].apply(c,e)}),a.inArray(b,e)>-1?this:d}throw new Error("Invalid arguments for Select2: "+b)}}return null==a.fn.select2.defaults&&(a.fn.select2.defaults=d),c}),{define:b.define,require:b.require}}(),c=b.require("jquery.select2");return a.fn.select2.amd=b,c}); //! moment.js -//! version : 2.16.0 +//! version : 2.17.0 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors //! license : MIT //! momentjs.com @@ -1309,11 +1309,11 @@ function b(a){od=a}function c(a){return a instanceof Array||"[object Array]"===O // input != null return null!=a&&"[object Object]"===Object.prototype.toString.call(a)}function e(a){var b;for(b in a) // even if its not own property I'd still call it non-empty -return!1;return!0}function f(a){return"number"==typeof value||"[object Number]"===Object.prototype.toString.call(a)}function g(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function h(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function i(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function j(a,b){for(var c in b)i(b,c)&&(a[c]=b[c]);return i(b,"toString")&&(a.toString=b.toString),i(b,"valueOf")&&(a.valueOf=b.valueOf),a}function k(a,b,c,d){return rb(a,b,c,d,!0).utc()}function l(){ +return!1;return!0}function f(a){return"number"==typeof a||"[object Number]"===Object.prototype.toString.call(a)}function g(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function h(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function i(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function j(a,b){for(var c in b)i(b,c)&&(a[c]=b[c]);return i(b,"toString")&&(a.toString=b.toString),i(b,"valueOf")&&(a.valueOf=b.valueOf),a}function k(a,b,c,d){return rb(a,b,c,d,!0).utc()}function l(){ // We need to deep clone this object. return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function m(a){return null==a._pf&&(a._pf=l()),a._pf}function n(a){if(null==a._isValid){var b=m(a),c=qd.call(b.parsedDateParts,function(a){return null!=a}),d=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c);if(a._strict&&(d=d&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour),null!=Object.isFrozen&&Object.isFrozen(a))return d;a._isValid=d}return a._isValid}function o(a){var b=k(NaN);return null!=a?j(m(b),a):m(b).userInvalidated=!0,b}function p(a){return void 0===a}function q(a,b){var c,d,e;if(p(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),p(b._i)||(a._i=b._i),p(b._f)||(a._f=b._f),p(b._l)||(a._l=b._l),p(b._strict)||(a._strict=b._strict),p(b._tzm)||(a._tzm=b._tzm),p(b._isUTC)||(a._isUTC=b._isUTC),p(b._offset)||(a._offset=b._offset),p(b._pf)||(a._pf=m(b)),p(b._locale)||(a._locale=b._locale),rd.length>0)for(c in rd)d=rd[c],e=b[d],p(e)||(a[d]=e);return a} // Moment prototype object -function r(b){q(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN), +function r(b){q(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)), // Prevent infinite loop in case updateOffset creates new moment // objects. sd===!1&&(sd=!0,a.updateOffset(this),sd=!1)}function s(a){return a instanceof r||null!=a&&null!=a._isAMomentObject}function t(a){return a<0?Math.ceil(a)||0:Math.floor(a)}function u(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=t(b)),c} @@ -1846,7 +1846,7 @@ M:11},qf=Math.abs,rf=wb.prototype; // FORMATTING // PARSING // Side effect imports -return rf.abs=Wc,rf.add=Yc,rf.subtract=Zc,rf.as=cd,rf.asMilliseconds=$e,rf.asSeconds=_e,rf.asMinutes=af,rf.asHours=bf,rf.asDays=cf,rf.asWeeks=df,rf.asMonths=ef,rf.asYears=ff,rf.valueOf=dd,rf._bubble=_c,rf.get=fd,rf.milliseconds=gf,rf.seconds=hf,rf.minutes=jf,rf.hours=kf,rf.days=lf,rf.weeks=hd,rf.months=mf,rf.years=nf,rf.humanize=md,rf.toISOString=nd,rf.toString=nd,rf.toJSON=nd,rf.locale=lc,rf.localeData=mc,rf.toIsoString=x("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",nd),rf.lang=Re,U("X",0,0,"unix"),U("x",0,0,"valueOf"),Z("x",Vd),Z("X",Yd),ba("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),ba("x",function(a,b,c){c._d=new Date(u(a))}),a.version="2.16.0",b(sb),a.fn=Xe,a.min=ub,a.max=vb,a.now=Le,a.utc=k,a.unix=Lc,a.months=Rc,a.isDate=g,a.locale=$a,a.invalid=o,a.duration=Ob,a.isMoment=s,a.weekdays=Tc,a.parseZone=Mc,a.localeData=bb,a.isDuration=xb,a.monthsShort=Sc,a.weekdaysMin=Vc,a.defineLocale=_a,a.updateLocale=ab,a.locales=cb,a.weekdaysShort=Uc,a.normalizeUnits=K,a.relativeTimeRounding=kd,a.relativeTimeThreshold=ld,a.calendarFormat=Ub,a.prototype=Xe,a}); +return rf.abs=Wc,rf.add=Yc,rf.subtract=Zc,rf.as=cd,rf.asMilliseconds=$e,rf.asSeconds=_e,rf.asMinutes=af,rf.asHours=bf,rf.asDays=cf,rf.asWeeks=df,rf.asMonths=ef,rf.asYears=ff,rf.valueOf=dd,rf._bubble=_c,rf.get=fd,rf.milliseconds=gf,rf.seconds=hf,rf.minutes=jf,rf.hours=kf,rf.days=lf,rf.weeks=hd,rf.months=mf,rf.years=nf,rf.humanize=md,rf.toISOString=nd,rf.toString=nd,rf.toJSON=nd,rf.locale=lc,rf.localeData=mc,rf.toIsoString=x("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",nd),rf.lang=Re,U("X",0,0,"unix"),U("x",0,0,"valueOf"),Z("x",Vd),Z("X",Yd),ba("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),ba("x",function(a,b,c){c._d=new Date(u(a))}),a.version="2.17.0",b(sb),a.fn=Xe,a.min=ub,a.max=vb,a.now=Le,a.utc=k,a.unix=Lc,a.months=Rc,a.isDate=g,a.locale=$a,a.invalid=o,a.duration=Ob,a.isMoment=s,a.weekdays=Tc,a.parseZone=Mc,a.localeData=bb,a.isDuration=xb,a.monthsShort=Sc,a.weekdaysMin=Vc,a.defineLocale=_a,a.updateLocale=ab,a.locales=cb,a.weekdaysShort=Uc,a.normalizeUnits=K,a.relativeTimeRounding=kd,a.relativeTimeThreshold=ld,a.calendarFormat=Ub,a.prototype=Xe,a}); /*! * FullCalendar v3.0.1 * Docs & License: http://fullcalendar.io/ @@ -1892,9 +1892,4 @@ SVGPathSeg.call(this,SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL,"v",a),this._y=b},SV * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) * https://github.com/chjj/marked */ -(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]||""});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].split(/ *\| */)}this.tokens.push(item);continue}if(cap=this.rules.lheading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[2]==="="?1:2,text:cap[1]});continue}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull.length>1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&(cap[1]==="pre"||cap[1]==="script"||cap[1]==="style"),text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(item);continue}if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:"paragraph",text:cap[1].charAt(cap[1].length-1)==="\n"?cap[1].slice(0,-1):cap[1]});continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"text",text:cap[0]});continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return this.tokens};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^<a /i.test(cap[0])){this.inLink=true}else if(this.inLink&&/^<\/a>/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(cap[0]):escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.text(escape(this.smartypants(cap[0])));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"â€").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){if(!this.options.mangle)return text;var out="",l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"<pre><code>"+(escaped?code:escape(code,true))+"\n</code></pre>"}return'<pre><code class="'+this.options.langPrefix+escape(lang,true)+'">'+(escaped?code:escape(code,true))+"\n</code></pre>\n"};Renderer.prototype.blockquote=function(quote){return"<blockquote>\n"+quote+"</blockquote>\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"<h"+level+' id="'+this.options.headerPrefix+raw.toLowerCase().replace(/[^\w]+/g,"-")+'">'+text+"</h"+level+">\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"</"+type+">\n"};Renderer.prototype.listitem=function(text){return"<li>"+text+"</li>\n"};Renderer.prototype.paragraph=function(text){return"<p>"+text+"</p>\n"};Renderer.prototype.table=function(header,body){return"<table>\n"+"<thead>\n"+header+"</thead>\n"+"<tbody>\n"+body+"</tbody>\n"+"</table>\n"};Renderer.prototype.tablerow=function(content){return"<tr>\n"+content+"</tr>\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"</"+type+">\n"};Renderer.prototype.strong=function(text){return"<strong>"+text+"</strong>"};Renderer.prototype.em=function(text){return"<em>"+text+"</em>"};Renderer.prototype.codespan=function(text){return"<code>"+text+"</code>"};Renderer.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"};Renderer.prototype.del=function(text){return"<del>"+text+"</del>"};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='<a href="'+href+'"';if(title){out+=' title="'+title+'"'}out+=">"+text+"</a>";return out};Renderer.prototype.image=function(href,title,text){var out='<img src="'+href+'" alt="'+text+'"';if(title){out+=' title="'+title+'"'}out+=this.options.xhtml?"/>":">";return out};Renderer.prototype.text=function(text){return text};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i<this.token.header.length;i++){flags={header:true,align:this.token.align[i]};cell+=this.renderer.tablecell(this.inline.output(this.token.header[i]),{header:true,align:this.token.align[i]})}header+=this.renderer.tablerow(cell);for(i=0;i<this.token.cells.length;i++){row=this.token.cells[i];cell="";for(j=0;j<row.length;j++){cell+=this.renderer.tablecell(this.inline.output(row[j]),{header:false,align:this.token.align[j]})}body+=this.renderer.tablerow(cell)}return this.renderer.table(header,body)}case"blockquote_start":{var body="";while(this.next().type!=="blockquote_end"){body+=this.tok()}return this.renderer.blockquote(body)}case"list_start":{var body="",ordered=this.token.ordered;while(this.next().type!=="list_end"){body+=this.tok()}return this.renderer.list(body,ordered)}case"list_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.token.type==="text"?this.parseText():this.tok()}return this.renderer.listitem(body)}case"loose_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.tok()}return this.renderer.listitem(body)}case"html":{var html=!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;return this.renderer.html(html)}case"paragraph":{return this.renderer.paragraph(this.inline.output(this.token.text))}case"text":{return this.renderer.paragraph(this.parseText())}}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target){if(Object.prototype.hasOwnProperty.call(target,key)){obj[key]=target[key]}}}return obj}function marked(src,opt,callback){if(callback||typeof opt==="function"){if(!callback){callback=opt;opt=null}opt=merge({},marked.defaults,opt||{});var highlight=opt.highlight,tokens,pending,i=0;try{tokens=Lexer.lex(src,opt)}catch(e){return callback(e)}pending=tokens.length;var done=function(err){if(err){opt.highlight=highlight;return callback(err)}var out;try{out=Parser.parse(tokens,opt)}catch(e){err=e}opt.highlight=highlight;return err?callback(err):callback(null,out)};if(!highlight||highlight.length<3){return done()}delete opt.highlight;if(!pending)return done();for(;i<tokens.length;i++){(function(token){if(token.type!=="code"){return--pending||done()}return highlight(token.text,token.lang,function(err,code){if(err)return done(err);if(code==null||code===token.text){return--pending||done()}token.text=code;token.escaped=true;--pending||done()})})(tokens[i])}return}try{if(opt)opt=merge({},marked.defaults,opt);return Parser.parse(Lexer.lex(src,opt),opt)}catch(e){e.message+="\nPlease report this to https://github.com/chjj/marked.";if((opt||marked.defaults).silent){return"<p>An error occured:</p><pre>"+escape(e.message+"",true)+"</pre>"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Vue=t()}(this,function(){"use strict";function e(t,r,i){if(n(t,r))return void(t[r]=i);if(t._isVue)return void e(t._data,r,i);var a=t.__ob__;if(!a)return void(t[r]=i);if(a.convert(r,i),a.dep.notify(),a.vms)for(var o=a.vms.length;o--;){var s=a.vms[o];s._proxy(r),s._digest()}return i}function t(e,t){if(n(e,t)){delete e[t];var r=e.__ob__;if(!r)return void(e._isVue&&(delete e._data[t],e._digest()));if(r.dep.notify(),r.vms)for(var i=r.vms.length;i--;){var a=r.vms[i];a._unproxy(t),a._digest()}}}function n(e,t){return $n.call(e,t)}function r(e){return An.test(e)}function i(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function a(e){return null==e?"":e.toString()}function o(e){if("string"!=typeof e)return e;var t=Number(e);return isNaN(t)?e:t}function s(e){return"true"===e?!0:"false"===e?!1:e}function l(e){var t=e.charCodeAt(0),n=e.charCodeAt(e.length-1);return t!==n||34!==t&&39!==t?e:e.slice(1,-1)}function u(e){return e.replace(Nn,c)}function c(e,t){return t?t.toUpperCase():""}function p(e){return e.replace(Ln,"$1-$2").toLowerCase()}function h(e){return e.replace(In,c)}function f(e,t){return function(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}}function d(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function v(e,t){for(var n=Object.keys(t),r=n.length;r--;)e[n[r]]=t[n[r]];return e}function m(e){return null!==e&&"object"==typeof e}function y(e){return Pn.call(e)===jn}function g(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function b(e,t){var n,r,i,a,o,s=function l(){var s=Date.now()-a;t>s&&s>=0?n=setTimeout(l,t-s):(n=null,o=e.apply(i,r),n||(i=r=null))};return function(){return i=this,r=arguments,a=Date.now(),n||(n=setTimeout(s,t)),o}}function _(e,t){for(var n=e.length;n--;)if(e[n]===t)return n;return-1}function x(e){var t=function n(){return n.cancelled?void 0:e.apply(this,arguments)};return t.cancel=function(){t.cancelled=!0},t}function w(e,t){return e==t||(m(e)&&m(t)?JSON.stringify(e)===JSON.stringify(t):!1)}function k(e){this.size=0,this.limit=e,this.head=this.tail=void 0,this._keymap=Object.create(null)}function S(){var e,t=nr.slice(lr,or).trim();if(t){e={};var n=t.match(vr);e.name=n[0],n.length>1&&(e.args=n.slice(1).map(C))}e&&(rr.filters=rr.filters||[]).push(e),lr=or+1}function C(e){if(mr.test(e))return{value:o(e),dynamic:!1};var t=l(e),n=t===e;return{value:n?e:t,dynamic:n}}function E(e){var t=dr.get(e);if(t)return t;for(nr=e,ur=cr=!1,pr=hr=fr=0,lr=0,rr={},or=0,sr=nr.length;sr>or;or++)if(ar=ir,ir=nr.charCodeAt(or),ur)39===ir&&92!==ar&&(ur=!ur);else if(cr)34===ir&&92!==ar&&(cr=!cr);else if(124===ir&&124!==nr.charCodeAt(or+1)&&124!==nr.charCodeAt(or-1))null==rr.expression?(lr=or+1,rr.expression=nr.slice(0,or).trim()):S();else switch(ir){case 34:cr=!0;break;case 39:ur=!0;break;case 40:fr++;break;case 41:fr--;break;case 91:hr++;break;case 93:hr--;break;case 123:pr++;break;case 125:pr--}return null==rr.expression?rr.expression=nr.slice(0,or).trim():0!==lr&&S(),dr.put(e,rr),rr}function O(e){return e.replace(gr,"\\$&")}function $(){var e=O(Er.delimiters[0]),t=O(Er.delimiters[1]),n=O(Er.unsafeDelimiters[0]),r=O(Er.unsafeDelimiters[1]);_r=new RegExp(n+"((?:.|\\n)+?)"+r+"|"+e+"((?:.|\\n)+?)"+t,"g"),xr=new RegExp("^"+n+"((?:.|\\n)+?)"+r+"$"),br=new k(1e3)}function A(e){br||$();var t=br.get(e);if(t)return t;if(!_r.test(e))return null;for(var n,r,i,a,o,s,l=[],u=_r.lastIndex=0;n=_r.exec(e);)r=n.index,r>u&&l.push({value:e.slice(u,r)}),i=xr.test(n[0]),a=i?n[1]:n[2],o=a.charCodeAt(0),s=42===o,a=s?a.slice(1):a,l.push({tag:!0,value:a.trim(),html:i,oneTime:s}),u=r+n[0].length;return u<e.length&&l.push({value:e.slice(u)}),br.put(e,l),l}function N(e,t){return e.length>1?e.map(function(e){return L(e,t)}).join("+"):L(e[0],t,!0)}function L(e,t,n){return e.tag?e.oneTime&&t?'"'+t.$eval(e.value)+'"':I(e.value,n):'"'+e.value+'"'}function I(e,t){if(wr.test(e)){var n=E(e);return n.filters?"this._applyFilters("+n.expression+",null,"+JSON.stringify(n.filters)+",false)":"("+e+")"}return t?e:"("+e+")"}function P(e,t,n,r){F(e,1,function(){t.appendChild(e)},n,r)}function j(e,t,n,r){F(e,1,function(){V(e,t)},n,r)}function T(e,t,n){F(e,-1,function(){W(e)},t,n)}function F(e,t,n,r,i){var a=e.__v_trans;if(!a||!a.hooks&&!Jn||!r._isCompiled||r.$parent&&!r.$parent._isCompiled)return n(),void(i&&i());var o=t>0?"enter":"leave";a[o](n,i)}function D(e){if("string"==typeof e){e=document.querySelector(e)}return e}function R(e){if(!e)return!1;var t=e.ownerDocument.documentElement,n=e.parentNode;return t===e||t===n||!(!n||1!==n.nodeType||!t.contains(n))}function B(e,t){var n=e.getAttribute(t);return null!==n&&e.removeAttribute(t),n}function U(e,t){var n=B(e,":"+t);return null===n&&(n=B(e,"v-bind:"+t)),n}function M(e,t){return e.hasAttribute(t)||e.hasAttribute(":"+t)||e.hasAttribute("v-bind:"+t)}function V(e,t){t.parentNode.insertBefore(e,t)}function H(e,t){t.nextSibling?V(e,t.nextSibling):t.parentNode.appendChild(e)}function W(e){e.parentNode.removeChild(e)}function z(e,t){t.firstChild?V(e,t.firstChild):t.appendChild(e)}function q(e,t){var n=e.parentNode;n&&n.replaceChild(t,e)}function G(e,t,n,r){e.addEventListener(t,n,r)}function J(e,t,n){e.removeEventListener(t,n)}function K(e){var t=e.className;return"object"==typeof t&&(t=t.baseVal||""),t}function Q(e,t){Mn&&!/svg$/.test(e.namespaceURI)?e.className=t:e.setAttribute("class",t)}function X(e,t){if(e.classList)e.classList.add(t);else{var n=" "+K(e)+" ";n.indexOf(" "+t+" ")<0&&Q(e,(n+t).trim())}}function Z(e,t){if(e.classList)e.classList.remove(t);else{for(var n=" "+K(e)+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");Q(e,n.trim())}e.className||e.removeAttribute("class")}function Y(e,t){var n,r;if(ne(e)&&se(e.content)&&(e=e.content),e.hasChildNodes())for(ee(e),r=t?document.createDocumentFragment():document.createElement("div");n=e.firstChild;)r.appendChild(n);return r}function ee(e){for(var t;t=e.firstChild,te(t);)e.removeChild(t);for(;t=e.lastChild,te(t);)e.removeChild(t)}function te(e){return e&&(3===e.nodeType&&!e.data.trim()||8===e.nodeType)}function ne(e){return e.tagName&&"template"===e.tagName.toLowerCase()}function re(e,t){var n=Er.debug?document.createComment(e):document.createTextNode(t?" ":"");return n.__v_anchor=!0,n}function ie(e){if(e.hasAttributes())for(var t=e.attributes,n=0,r=t.length;r>n;n++){var i=t[n].name;if(Ar.test(i))return u(i.replace(Ar,""))}}function ae(e,t,n){for(var r;e!==t;)r=e.nextSibling,n(e),e=r;n(t)}function oe(e,t,n,r,i){function a(){if(s++,o&&s>=l.length){for(var e=0;e<l.length;e++)r.appendChild(l[e]);i&&i()}}var o=!1,s=0,l=[];ae(e,t,function(e){e===t&&(o=!0),l.push(e),T(e,n,a)})}function se(e){return e&&11===e.nodeType}function le(e){if(e.outerHTML)return e.outerHTML;var t=document.createElement("div");return t.appendChild(e.cloneNode(!0)),t.innerHTML}function ue(e,t){var n=e.tagName.toLowerCase(),r=e.hasAttributes();if(Nr.test(n)||Lr.test(n)){if(r)return ce(e,t)}else{if(ye(t,"components",n))return{id:n};var i=r&&ce(e,t);if(i)return i}}function ce(e,t){var n=e.getAttribute("is");if(null!=n){if(ye(t,"components",n))return e.removeAttribute("is"),{id:n}}else if(n=U(e,"is"),null!=n)return{id:n,dynamic:!0}}function pe(t,r){var i,a,o;for(i in r)a=t[i],o=r[i],n(t,i)?m(a)&&m(o)&&pe(a,o):e(t,i,o);return t}function he(e,t){var n=Object.create(e||null);return t?v(n,ve(t)):n}function fe(e){if(e.components)for(var t,n=e.components=ve(e.components),r=Object.keys(n),i=0,a=r.length;a>i;i++){var o=r[i];Nr.test(o)||Lr.test(o)||(t=n[o],y(t)&&(n[o]=wn.extend(t)))}}function de(e){var t,n,r=e.props;if(Tn(r))for(e.props={},t=r.length;t--;)n=r[t],"string"==typeof n?e.props[n]=null:n.name&&(e.props[n.name]=n);else if(y(r)){var i=Object.keys(r);for(t=i.length;t--;)n=r[i[t]],"function"==typeof n&&(r[i[t]]={type:n})}}function ve(e){if(Tn(e)){for(var t,n={},r=e.length;r--;){t=e[r];var i="function"==typeof t?t.options&&t.options.name||t.id:t.name||t.id;i&&(n[i]=t)}return n}return e}function me(e,t,r){function i(n){var i=Ir[n]||Pr;o[n]=i(e[n],t[n],r,n)}fe(t),de(t);var a,o={};if(t["extends"]&&(e="function"==typeof t["extends"]?me(e,t["extends"].options,r):me(e,t["extends"],r)),t.mixins)for(var s=0,l=t.mixins.length;l>s;s++){var u=t.mixins[s],c=u.prototype instanceof wn?u.options:u;e=me(e,c,r)}for(a in e)i(a);for(a in t)n(e,a)||i(a);return o}function ye(e,t,n,r){if("string"==typeof n){var i,a=e[t],o=a[n]||a[i=u(n)]||a[i.charAt(0).toUpperCase()+i.slice(1)];return o}}function ge(){this.id=jr++,this.subs=[]}function be(e){Rr=!1,e(),Rr=!0}function _e(e){if(this.value=e,this.dep=new ge,g(e,"__ob__",this),Tn(e)){var t=Fn?xe:we;t(e,Fr,Dr),this.observeArray(e)}else this.walk(e)}function xe(e,t){e.__proto__=t}function we(e,t,n){for(var r=0,i=n.length;i>r;r++){var a=n[r];g(e,a,t[a])}}function ke(e,t){if(e&&"object"==typeof e){var r;return n(e,"__ob__")&&e.__ob__ instanceof _e?r=e.__ob__:Rr&&(Tn(e)||y(e))&&Object.isExtensible(e)&&!e._isVue&&(r=new _e(e)),r&&t&&r.addVm(t),r}}function Se(e,t,n){var r=new ge,i=Object.getOwnPropertyDescriptor(e,t);if(!i||i.configurable!==!1){var a=i&&i.get,o=i&&i.set,s=ke(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=a?a.call(e):n;if(ge.target&&(r.depend(),s&&s.dep.depend(),Tn(t)))for(var i,o=0,l=t.length;l>o;o++)i=t[o],i&&i.__ob__&&i.__ob__.dep.depend();return t},set:function(t){var i=a?a.call(e):n;t!==i&&(o?o.call(e,t):n=t,s=ke(t),r.notify())}})}}function Ce(e){e.prototype._init=function(e){e=e||{},this.$el=null,this.$parent=e.parent,this.$root=this.$parent?this.$parent.$root:this,this.$children=[],this.$refs={},this.$els={},this._watchers=[],this._directives=[],this._uid=Ur++,this._isVue=!0,this._events={},this._eventsCount={},this._isFragment=!1,this._fragment=this._fragmentStart=this._fragmentEnd=null,this._isCompiled=this._isDestroyed=this._isReady=this._isAttached=this._isBeingDestroyed=this._vForRemoving=!1,this._unlinkFn=null,this._context=e._context||this.$parent,this._scope=e._scope,this._frag=e._frag,this._frag&&this._frag.children.push(this),this.$parent&&this.$parent.$children.push(this),e=this.$options=me(this.constructor.options,e,this),this._updateRef(),this._data={},this._callHook("init"),this._initState(),this._initEvents(),this._callHook("created"),e.el&&this.$mount(e.el)}}function Ee(e){if(void 0===e)return"eof";var t=e.charCodeAt(0);switch(t){case 91:case 93:case 46:case 34:case 39:case 48:return e;case 95:case 36:return"ident";case 32:case 9:case 10:case 13:case 160:case 65279:case 8232:case 8233:return"ws"}return t>=97&&122>=t||t>=65&&90>=t?"ident":t>=49&&57>=t?"number":"else"}function Oe(e){var t=e.trim();return"0"===e.charAt(0)&&isNaN(e)?!1:r(t)?l(t):"*"+t}function $e(e){function t(){var t=e[c+1];return p===ii&&"'"===t||p===ai&&'"'===t?(c++,r="\\"+t,f[Kr](),!0):void 0}var n,r,i,a,o,s,l,u=[],c=-1,p=Yr,h=0,f=[];for(f[Qr]=function(){void 0!==i&&(u.push(i),i=void 0)},f[Kr]=function(){void 0===i?i=r:i+=r},f[Xr]=function(){f[Kr](),h++},f[Zr]=function(){if(h>0)h--,p=ri,f[Kr]();else{if(h=0,i=Oe(i),i===!1)return!1;f[Qr]()}};null!=p;)if(c++,n=e[c],"\\"!==n||!t()){if(a=Ee(n),l=li[p],o=l[a]||l["else"]||si,o===si)return;if(p=o[0],s=f[o[1]],s&&(r=o[2],r=void 0===r?n:r,s()===!1))return;if(p===oi)return u.raw=e,u}}function Ae(e){var t=Jr.get(e);return t||(t=$e(e),t&&Jr.put(e,t)),t}function Ne(e,t){return Be(t).get(e)}function Le(t,n,r){var i=t;if("string"==typeof n&&(n=$e(n)),!n||!m(t))return!1;for(var a,o,s=0,l=n.length;l>s;s++)a=t,o=n[s],"*"===o.charAt(0)&&(o=Be(o.slice(1)).get.call(i,i)),l-1>s?(t=t[o],m(t)||(t={},e(a,o,t))):Tn(t)?t.$set(o,r):o in t?t[o]=r:e(t,o,r);return!0}function Ie(){}function Pe(e,t){var n=wi.length;return wi[n]=t?e.replace(mi,"\\n"):e,'"'+n+'"'}function je(e){var t=e.charAt(0),n=e.slice(1);return hi.test(n)?e:(n=n.indexOf('"')>-1?n.replace(gi,Te):n,t+"scope."+n)}function Te(e,t){return wi[t]}function Fe(e){di.test(e),wi.length=0;var t=e.replace(yi,Pe).replace(vi,"");return t=(" "+t).replace(_i,je).replace(gi,Te),De(t)}function De(e){try{var t=qr.Function("scope","Math","return "+e);return function(e){return t.call(this,e,Math)}}catch(n){return Ie}}function Re(e){var t=Ae(e);return t?function(e,n){Le(e,t,n)}:void 0}function Be(e,t){e=e.trim();var n=ci.get(e);if(n)return t&&!n.set&&(n.set=Re(n.exp)),n;var r={exp:e};return r.get=Ue(e)&&e.indexOf("[")<0?De("scope."+e):Fe(e),t&&(r.set=Re(e)),ci.put(e,r),r}function Ue(e){return bi.test(e)&&!xi.test(e)&&"Math."!==e.slice(0,5)}function Me(){Si.length=0,Ci.length=0,Ei={},Oi={},$i=!1}function Ve(){for(var e=!0;e;)e=!1,He(Si),He(Ci),Si.length?e=!0:(Rn&&Er.devtools&&Rn.emit("flush"),Me())}function He(e){for(var t=0;t<e.length;t++){var n=e[t],r=n.id;Ei[r]=null,n.run()}e.length=0}function We(e){var t=e.id;if(null==Ei[t]){var n=e.user?Ci:Si;Ei[t]=n.length,n.push(e),$i||($i=!0,Yn(Ve))}}function ze(e,t,n,r){r&&v(this,r);var i="function"==typeof t;if(this.vm=e,e._watchers.push(this),this.expression=t,this.cb=n,this.id=++Ai,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new er,this.newDepIds=new er,this.prevError=null,i)this.getter=t,this.setter=void 0;else{var a=Be(t,this.twoWay);this.getter=a.get,this.setter=a.set}this.value=this.lazy?void 0:this.get(),this.queued=this.shallow=!1}function qe(e,t){var n=void 0,r=void 0;t||(t=Ni,t.clear());var i=Tn(e),a=m(e);if((i||a)&&Object.isExtensible(e)){if(e.__ob__){var o=e.__ob__.dep.id;if(t.has(o))return;t.add(o)}if(i)for(n=e.length;n--;)qe(e[n],t);else if(a)for(r=Object.keys(e),n=r.length;n--;)qe(e[r[n]],t)}}function Ge(e){return ne(e)&&se(e.content)}function Je(e,t){var n=t?e:e.trim(),r=Ii.get(n);if(r)return r;var i=document.createDocumentFragment(),a=e.match(Ti),o=Fi.test(e),s=Di.test(e);if(a||o||s){var l=a&&a[1],u=ji[l]||ji.efault,c=u[0],p=u[1],h=u[2],f=document.createElement("div");for(f.innerHTML=p+e+h;c--;)f=f.lastChild;for(var d;d=f.firstChild;)i.appendChild(d)}else i.appendChild(document.createTextNode(e));return t||ee(i),Ii.put(n,i),i}function Ke(e){if(Ge(e))return Je(e.innerHTML);if("SCRIPT"===e.tagName)return Je(e.textContent);for(var t,n=Qe(e),r=document.createDocumentFragment();t=n.firstChild;)r.appendChild(t);return ee(r),r}function Qe(e){if(!e.querySelectorAll)return e.cloneNode();var t,n,r,i=e.cloneNode(!0);if(Ri){var a=i;if(Ge(e)&&(e=e.content,a=i.content),n=e.querySelectorAll("template"),n.length)for(r=a.querySelectorAll("template"),t=r.length;t--;)r[t].parentNode.replaceChild(Qe(n[t]),r[t])}if(Bi)if("TEXTAREA"===e.tagName)i.value=e.value;else if(n=e.querySelectorAll("textarea"),n.length)for(r=i.querySelectorAll("textarea"),t=r.length;t--;)r[t].value=n[t].value;return i}function Xe(e,t,n){var r,i;return se(e)?(ee(e),t?Qe(e):e):("string"==typeof e?n||"#"!==e.charAt(0)?i=Je(e,n):(i=Pi.get(e),i||(r=document.getElementById(e.slice(1)),r&&(i=Ke(r),Pi.put(e,i)))):e.nodeType&&(i=Ke(e)),i&&t?Qe(i):i)}function Ze(e,t,n,r,i,a){this.children=[],this.childFrags=[],this.vm=t,this.scope=i,this.inserted=!1,this.parentFrag=a,a&&a.childFrags.push(this),this.unlink=e(t,n,r,i,this);var o=this.single=1===n.childNodes.length&&!n.childNodes[0].__v_anchor;o?(this.node=n.childNodes[0],this.before=Ye,this.remove=et):(this.node=re("fragment-start"),this.end=re("fragment-end"),this.frag=n,z(this.node,n),n.appendChild(this.end),this.before=tt,this.remove=nt),this.node.__v_frag=this}function Ye(e,t){this.inserted=!0;var n=t!==!1?j:V;n(this.node,e,this.vm),R(this.node)&&this.callHook(rt)}function et(){this.inserted=!1;var e=R(this.node),t=this;this.beforeRemove(),T(this.node,this.vm,function(){e&&t.callHook(it),t.destroy()})}function tt(e,t){this.inserted=!0;var n=this.vm,r=t!==!1?j:V;ae(this.node,this.end,function(t){r(t,e,n)}),R(this.node)&&this.callHook(rt)}function nt(){this.inserted=!1;var e=this,t=R(this.node);this.beforeRemove(),oe(this.node,this.end,this.vm,this.frag,function(){t&&e.callHook(it),e.destroy()})}function rt(e){!e._isAttached&&R(e.$el)&&e._callHook("attached")}function it(e){e._isAttached&&!R(e.$el)&&e._callHook("detached")}function at(e,t){this.vm=e;var n,r="string"==typeof t;r||ne(t)&&!t.hasAttribute("v-if")?n=Xe(t,!0):(n=document.createDocumentFragment(),n.appendChild(t)),this.template=n;var i,a=e.constructor.cid;if(a>0){var o=a+(r?t:le(t));i=Vi.get(o),i||(i=jt(n,e.$options,!0),Vi.put(o,i))}else i=jt(n,e.$options,!0);this.linker=i}function ot(e,t,n){var r=e.node.previousSibling;if(r){for(e=r.__v_frag;!(e&&e.forId===n&&e.inserted||r===t);){if(r=r.previousSibling,!r)return;e=r.__v_frag}return e}}function st(e){var t=e.node;if(e.end)for(;!t.__vue__&&t!==e.end&&t.nextSibling;)t=t.nextSibling;return t.__vue__}function lt(e){for(var t=-1,n=new Array(Math.floor(e));++t<e;)n[t]=t;return n}function ut(e,t,n,r){return r?"$index"===r?e:r.charAt(0).match(/\w/)?Ne(n,r):n[r]:t||n}function ct(e,t,n){for(var r,i,a,o=t?[]:null,s=0,l=e.options.length;l>s;s++)if(r=e.options[s],a=n?r.hasAttribute("selected"):r.selected){if(i=r.hasOwnProperty("_value")?r._value:r.value,!t)return i;o.push(i)}return o}function pt(e,t){for(var n=e.length;n--;)if(w(e[n],t))return n;return-1}function ht(e,t){var n=t.map(function(e){var t=e.charCodeAt(0);return t>47&&58>t?parseInt(e,10):1===e.length&&(t=e.toUpperCase().charCodeAt(0),t>64&&91>t)?t:ua[e]});return n=[].concat.apply([],n),function(t){return n.indexOf(t.keyCode)>-1?e.call(this,t):void 0}}function ft(e){return function(t){return t.stopPropagation(),e.call(this,t)}}function dt(e){return function(t){return t.preventDefault(),e.call(this,t)}}function vt(e){return function(t){return t.target===t.currentTarget?e.call(this,t):void 0}}function mt(e){if(da[e])return da[e];var t=yt(e);return da[e]=da[t]=t,t}function yt(e){e=p(e);var t=u(e),n=t.charAt(0).toUpperCase()+t.slice(1);va||(va=document.createElement("div"));var r,i=pa.length;if("filter"!==t&&t in va.style)return{kebab:e,camel:t};for(;i--;)if(r=ha[i]+n,r in va.style)return{kebab:pa[i]+e,camel:r}}function gt(e){var t=[];if(Tn(e))for(var n=0,r=e.length;r>n;n++){var i=e[n];if(i)if("string"==typeof i)t.push(i);else for(var a in i)i[a]&&t.push(a)}else if(m(e))for(var o in e)e[o]&&t.push(o);return t}function bt(e,t,n){if(t=t.trim(),-1===t.indexOf(" "))return void n(e,t);for(var r=t.split(/\s+/),i=0,a=r.length;a>i;i++)n(e,r[i])}function _t(e,t,n){function r(){++a>=i?n():e[a].call(t,r)}var i=e.length,a=0;e[0].call(t,r)}function xt(e,t,n){for(var i,a,o,s,l,c,h,f=[],d=Object.keys(t),v=d.length;v--;)a=d[v],i=t[a]||La,l=u(a),Ia.test(l)&&(h={name:a,path:l,options:i,mode:Na.ONE_WAY,raw:null},o=p(a),null===(s=U(e,o))&&(null!==(s=U(e,o+".sync"))?h.mode=Na.TWO_WAY:null!==(s=U(e,o+".once"))&&(h.mode=Na.ONE_TIME)),null!==s?(h.raw=s,c=E(s),s=c.expression,h.filters=c.filters,r(s)&&!c.filters?h.optimizedLiteral=!0:h.dynamic=!0,h.parentPath=s):null!==(s=B(e,o))&&(h.raw=s),f.push(h));return wt(f)}function wt(e){return function(t,r){t._props={};for(var i,a,u,c,h,f=t.$options.propsData,d=e.length;d--;)if(i=e[d],h=i.raw,a=i.path,u=i.options,t._props[a]=i,f&&n(f,a)&&St(t,i,f[a]),null===h)St(t,i,void 0);else if(i.dynamic)i.mode===Na.ONE_TIME?(c=(r||t._context||t).$get(i.parentPath),St(t,i,c)):t._context?t._bindDir({name:"prop",def:ja,prop:i},null,null,r):St(t,i,t.$get(i.parentPath));else if(i.optimizedLiteral){var v=l(h);c=v===h?s(o(h)):v,St(t,i,c)}else c=u.type!==Boolean||""!==h&&h!==p(i.name)?h:!0,St(t,i,c)}}function kt(e,t,n,r){var i=t.dynamic&&Ue(t.parentPath),a=n;void 0===a&&(a=Et(e,t)),a=$t(t,a,e);var o=a!==n;Ot(t,a,e)||(a=void 0),i&&!o?be(function(){r(a)}):r(a)}function St(e,t,n){kt(e,t,n,function(n){Se(e,t.path,n)})}function Ct(e,t,n){kt(e,t,n,function(n){e[t.path]=n})}function Et(e,t){var r=t.options;if(!n(r,"default"))return r.type===Boolean?!1:void 0;var i=r["default"];return m(i),"function"==typeof i&&r.type!==Function?i.call(e):i}function Ot(e,t,n){if(!e.options.required&&(null===e.raw||null==t))return!0;var r=e.options,i=r.type,a=!i,o=[];if(i){Tn(i)||(i=[i]);for(var s=0;s<i.length&&!a;s++){var l=At(t,i[s]);o.push(l.expectedType),a=l.valid}}if(!a)return!1;var u=r.validator;return!u||u(t)}function $t(e,t,n){var r=e.options.coerce;return r&&"function"==typeof r?r(t):t}function At(e,t){var n,r;return t===String?(r="string",n=typeof e===r):t===Number?(r="number",n=typeof e===r):t===Boolean?(r="boolean",n=typeof e===r):t===Function?(r="function",n=typeof e===r):t===Object?(r="object",n=y(e)):t===Array?(r="array",n=Tn(e)):n=e instanceof t,{valid:n,expectedType:r}}function Nt(e){Ta.push(e),Fa||(Fa=!0,Yn(Lt))}function Lt(){for(var e=document.documentElement.offsetHeight,t=0;t<Ta.length;t++)Ta[t]();return Ta=[],Fa=!1,e}function It(e,t,n,r){this.id=t,this.el=e,this.enterClass=n&&n.enterClass||t+"-enter",this.leaveClass=n&&n.leaveClass||t+"-leave",this.hooks=n,this.vm=r,this.pendingCssEvent=this.pendingCssCb=this.cancel=this.pendingJsCb=this.op=this.cb=null,this.justEntered=!1,this.entered=this.left=!1,this.typeCache={},this.type=n&&n.type;var i=this;["enterNextTick","enterDone","leaveNextTick","leaveDone"].forEach(function(e){i[e]=f(i[e],i)})}function Pt(e){if(/svg$/.test(e.namespaceURI)){var t=e.getBoundingClientRect();return!(t.width||t.height)}return!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)}function jt(e,t,n){var r=n||!t._asComponent?Mt(e,t):null,i=r&&r.terminal||an(e)||!e.hasChildNodes()?null:Gt(e.childNodes,t);return function(e,t,n,a,o){var s=d(t.childNodes),l=Tt(function(){r&&r(e,t,n,a,o),i&&i(e,s,n,a,o)},e);return Dt(e,l)}}function Tt(e,t){t._directives=[];var n=t._directives.length;e();var r=t._directives.slice(n);r.sort(Ft);for(var i=0,a=r.length;a>i;i++)r[i]._bind();return r}function Ft(e,t){return e=e.descriptor.def.priority||Xa,t=t.descriptor.def.priority||Xa,e>t?-1:e===t?0:1}function Dt(e,t,n,r){function i(i){Rt(e,t,i),n&&r&&Rt(n,r)}return i.dirs=t,i}function Rt(e,t,n){for(var r=t.length;r--;)t[r]._teardown()}function Bt(e,t,n,r){var i=xt(t,n,e),a=Tt(function(){i(e,r)},e);return Dt(e,a)}function Ut(e,t,n){var r,i,a=t._containerAttrs,o=t._replacerAttrs;return 11!==e.nodeType&&(t._asComponent?(a&&n&&(r=en(a,n)),o&&(i=en(o,t))):i=en(e.attributes,t)),t._containerAttrs=t._replacerAttrs=null,function(e,t,n){var a,o=e._context;o&&r&&(a=Tt(function(){r(o,t,null,n)},o));var s=Tt(function(){i&&i(e,t)},e);return Dt(e,s,o,a)}}function Mt(e,t){var n=e.nodeType;return 1!==n||an(e)?3===n&&e.data.trim()?Ht(e,t):null:Vt(e,t)}function Vt(e,t){if("TEXTAREA"===e.tagName){var n=A(e.value);n&&(e.setAttribute(":value",N(n)),e.value="")}var r,i=e.hasAttributes(),a=i&&d(e.attributes);return i&&(r=Xt(e,a,t)),r||(r=Kt(e,t)),r||(r=Qt(e,t)),!r&&i&&(r=en(a,t)),r}function Ht(e,t){if(e._skip)return Wt;var n=A(e.wholeText);if(!n)return null;for(var r=e.nextSibling;r&&3===r.nodeType;)r._skip=!0,r=r.nextSibling;for(var i,a,o=document.createDocumentFragment(),s=0,l=n.length;l>s;s++)a=n[s],i=a.tag?zt(a,t):document.createTextNode(a.value),o.appendChild(i);return qt(n,o,t)}function Wt(e,t){W(t)}function zt(e,t){function n(t){if(!e.descriptor){var n=E(e.value);e.descriptor={name:t,def:Oa[t],expression:n.expression,filters:n.filters}}}var r;return e.oneTime?r=document.createTextNode(e.value):e.html?(r=document.createComment("v-html"),n("html")):(r=document.createTextNode(" "),n("text")),r}function qt(e,t){return function(n,r,i,o){for(var s,l,u,c=t.cloneNode(!0),p=d(c.childNodes),h=0,f=e.length;f>h;h++)s=e[h],l=s.value,s.tag&&(u=p[h],s.oneTime?(l=(o||n).$eval(l),s.html?q(u,Xe(l,!0)):u.data=a(l)):n._bindDir(s.descriptor,u,i,o));q(r,c)}}function Gt(e,t){for(var n,r,i,a=[],o=0,s=e.length;s>o;o++)i=e[o],n=Mt(i,t),r=n&&n.terminal||"SCRIPT"===i.tagName||!i.hasChildNodes()?null:Gt(i.childNodes,t),a.push(n,r);return a.length?Jt(a):null}function Jt(e){return function(t,n,r,i,a){for(var o,s,l,u=0,c=0,p=e.length;p>u;c++){o=n[c],s=e[u++],l=e[u++];var h=d(o.childNodes);s&&s(t,o,r,i,a),l&&l(t,h,r,i,a)}}}function Kt(e,t){var n=e.tagName.toLowerCase();if(!Nr.test(n)){var r=ye(t,"elementDirectives",n);return r?Yt(e,n,"",t,r):void 0}}function Qt(e,t){var n=ue(e,t);if(n){var r=ie(e),i={name:"component",ref:r,expression:n.id,def:za.component,modifiers:{literal:!n.dynamic}},a=function(e,t,n,a,o){r&&Se((a||e).$refs,r,null),e._bindDir(i,t,n,a,o)};return a.terminal=!0,a}}function Xt(e,t,n){if(null!==B(e,"v-pre"))return Zt;if(e.hasAttribute("v-else")){var r=e.previousElementSibling;if(r&&r.hasAttribute("v-if"))return Zt}for(var i,a,o,s,l,u,c,p,h,f,d=0,v=t.length;v>d;d++)i=t[d],a=i.name.replace(Ka,""),(l=a.match(Ja))&&(h=ye(n,"directives",l[1]),h&&h.terminal&&(!f||(h.priority||Za)>f.priority)&&(f=h,c=i.name,s=tn(i.name),o=i.value,u=l[1],p=l[2]));return f?Yt(e,u,o,n,f,c,p,s):void 0}function Zt(){}function Yt(e,t,n,r,i,a,o,s){var l=E(n),u={name:t,arg:o,expression:l.expression,filters:l.filters,raw:n,attr:a,modifiers:s,def:i};"for"!==t&&"router-view"!==t||(u.ref=ie(e));var c=function(e,t,n,r,i){u.ref&&Se((r||e).$refs,u.ref,null),e._bindDir(u,t,n,r,i)};return c.terminal=!0,c}function en(e,t){function n(e,t,n){var r=n&&rn(n),i=!r&&E(a);v.push({name:e,attr:o,raw:s,def:t,arg:u,modifiers:c,expression:i&&i.expression,filters:i&&i.filters,interp:n,hasOneTime:r})}for(var r,i,a,o,s,l,u,c,p,h,f,d=e.length,v=[];d--;)if(r=e[d],i=o=r.name,a=s=r.value,h=A(a),u=null,c=tn(i),i=i.replace(Ka,""),h)a=N(h),u=i,n("bind",Oa.bind,h);else if(Qa.test(i))c.literal=!qa.test(i),n("transition",za.transition);else if(Ga.test(i))u=i.replace(Ga,""),n("on",Oa.on);else if(qa.test(i))l=i.replace(qa,""),"style"===l||"class"===l?n(l,za[l]):(u=l,n("bind",Oa.bind));else if(f=i.match(Ja)){if(l=f[1],u=f[2],"else"===l)continue;p=ye(t,"directives",l,!0),p&&n(l,p)}return v.length?nn(v):void 0}function tn(e){var t=Object.create(null),n=e.match(Ka);if(n)for(var r=n.length;r--;)t[n[r].slice(1)]=!0;return t}function nn(e){return function(t,n,r,i,a){for(var o=e.length;o--;)t._bindDir(e[o],n,r,i,a)}}function rn(e){for(var t=e.length;t--;)if(e[t].oneTime)return!0}function an(e){return"SCRIPT"===e.tagName&&(!e.hasAttribute("type")||"text/javascript"===e.getAttribute("type"))}function on(e,t){return t&&(t._containerAttrs=ln(e)),ne(e)&&(e=Xe(e)),t&&(t._asComponent&&!t.template&&(t.template="<slot></slot>"),t.template&&(t._content=Y(e),e=sn(e,t))),se(e)&&(z(re("v-start",!0),e),e.appendChild(re("v-end",!0))),e}function sn(e,t){var n=t.template,r=Xe(n,!0);if(r){var i=r.firstChild,a=i.tagName&&i.tagName.toLowerCase();return t.replace?(e===document.body,r.childNodes.length>1||1!==i.nodeType||"component"===a||ye(t,"components",a)||M(i,"is")||ye(t,"elementDirectives",a)||i.hasAttribute("v-for")||i.hasAttribute("v-if")?r:(t._replacerAttrs=ln(i),un(e,i),i)):(e.appendChild(r),e)}}function ln(e){return 1===e.nodeType&&e.hasAttributes()?d(e.attributes):void 0}function un(e,t){for(var n,r,i=e.attributes,a=i.length;a--;)n=i[a].name,r=i[a].value,t.hasAttribute(n)||Ya.test(n)?"class"===n&&!A(r)&&(r=r.trim())&&r.split(/\s+/).forEach(function(e){X(t,e)}):t.setAttribute(n,r)}function cn(e,t){if(t){for(var n,r,i=e._slotContents=Object.create(null),a=0,o=t.children.length;o>a;a++)n=t.children[a],(r=n.getAttribute("slot"))&&(i[r]||(i[r]=[])).push(n);for(r in i)i[r]=pn(i[r],t);if(t.hasChildNodes()){var s=t.childNodes;if(1===s.length&&3===s[0].nodeType&&!s[0].data.trim())return;i["default"]=pn(t.childNodes,t)}}}function pn(e,t){var n=document.createDocumentFragment();e=d(e);for(var r=0,i=e.length;i>r;r++){var a=e[r];!ne(a)||a.hasAttribute("v-if")||a.hasAttribute("v-for")||(t.removeChild(a),a=Xe(a,!0)),n.appendChild(a)}return n}function hn(e){function t(){}function r(e,t){var n=new ze(t,e,null,{lazy:!0});return function(){return n.dirty&&n.evaluate(),ge.target&&n.depend(),n.value}}Object.defineProperty(e.prototype,"$data",{get:function(){return this._data},set:function(e){e!==this._data&&this._setData(e)}}),e.prototype._initState=function(){this._initProps(),this._initMeta(),this._initMethods(),this._initData(),this._initComputed()},e.prototype._initProps=function(){var e=this.$options,t=e.el,n=e.props;t=e.el=D(t),this._propsUnlinkFn=t&&1===t.nodeType&&n?Bt(this,t,n,this._scope):null},e.prototype._initData=function(){var e=this.$options.data,t=this._data=e?e():{};y(t)||(t={});var r,i,a=this._props,o=Object.keys(t);for(r=o.length;r--;)i=o[r],a&&n(a,i)||this._proxy(i);ke(t,this)},e.prototype._setData=function(e){e=e||{};var t=this._data;this._data=e;var r,i,a;for(r=Object.keys(t),a=r.length;a--;)i=r[a],i in e||this._unproxy(i);for(r=Object.keys(e),a=r.length;a--;)i=r[a],n(this,i)||this._proxy(i);t.__ob__.removeVm(this),ke(e,this),this._digest()},e.prototype._proxy=function(e){if(!i(e)){var t=this;Object.defineProperty(t,e,{configurable:!0,enumerable:!0,get:function(){return t._data[e]},set:function(n){t._data[e]=n}})}},e.prototype._unproxy=function(e){i(e)||delete this[e]},e.prototype._digest=function(){for(var e=0,t=this._watchers.length;t>e;e++)this._watchers[e].update(!0)},e.prototype._initComputed=function(){var e=this.$options.computed;if(e)for(var n in e){var i=e[n],a={enumerable:!0,configurable:!0};"function"==typeof i?(a.get=r(i,this),a.set=t):(a.get=i.get?i.cache!==!1?r(i.get,this):f(i.get,this):t,a.set=i.set?f(i.set,this):t),Object.defineProperty(this,n,a)}},e.prototype._initMethods=function(){var e=this.$options.methods;if(e)for(var t in e)this[t]=f(e[t],this)},e.prototype._initMeta=function(){var e=this.$options._meta;if(e)for(var t in e)Se(this,t,e[t])}}function fn(e){function t(e,t){for(var n,r,i,a=t.attributes,o=0,s=a.length;s>o;o++)n=a[o].name,to.test(n)&&(n=n.replace(to,""),r=a[o].value,Ue(r)&&(r+=".apply(this, $arguments)"),i=(e._scope||e._context).$eval(r,!0),i._fromParent=!0,e.$on(n.replace(to),i))}function n(e,t,n){if(n){var i,a,o,s;for(a in n)if(i=n[a],Tn(i))for(o=0,s=i.length;s>o;o++)r(e,t,a,i[o]);else r(e,t,a,i)}}function r(e,t,n,i,a){var o=typeof i;if("function"===o)e[t](n,i,a);else if("string"===o){var s=e.$options.methods,l=s&&s[i];l&&e[t](n,l,a)}else i&&"object"===o&&r(e,t,n,i.handler,i)}function i(){this._isAttached||(this._isAttached=!0,this.$children.forEach(a))}function a(e){!e._isAttached&&R(e.$el)&&e._callHook("attached")}function o(){this._isAttached&&(this._isAttached=!1,this.$children.forEach(s))}function s(e){e._isAttached&&!R(e.$el)&&e._callHook("detached")}e.prototype._initEvents=function(){var e=this.$options;e._asComponent&&t(this,e.el),n(this,"$on",e.events),n(this,"$watch",e.watch)},e.prototype._initDOMHooks=function(){this.$on("hook:attached",i),this.$on("hook:detached",o)},e.prototype._callHook=function(e){this.$emit("pre-hook:"+e);var t=this.$options[e];if(t)for(var n=0,r=t.length;r>n;n++)t[n].call(this);this.$emit("hook:"+e)}}function dn(){}function vn(e,t,n,r,i,a){this.vm=t,this.el=n,this.descriptor=e,this.name=e.name,this.expression=e.expression,this.arg=e.arg,this.modifiers=e.modifiers,this.filters=e.filters,this.literal=this.modifiers&&this.modifiers.literal,this._locked=!1,this._bound=!1,this._listeners=null,this._host=r,this._scope=i,this._frag=a}function mn(e){e.prototype._updateRef=function(e){var t=this.$options._ref;if(t){var n=(this._scope||this._context).$refs;e?n[t]===this&&(n[t]=null):n[t]=this}},e.prototype._compile=function(e){var t=this.$options,n=e;if(e=on(e,t),this._initElement(e),1!==e.nodeType||null===B(e,"v-pre")){var r=this._context&&this._context.$options,i=Ut(e,t,r);cn(this,t._content);var a,o=this.constructor;t._linkerCachable&&(a=o.linker,a||(a=o.linker=jt(e,t)));var s=i(this,e,this._scope),l=a?a(this,e):jt(e,t)(this,e);this._unlinkFn=function(){s(),l(!0)},t.replace&&q(n,e),this._isCompiled=!0,this._callHook("compiled")}},e.prototype._initElement=function(e){se(e)?(this._isFragment=!0,this.$el=this._fragmentStart=e.firstChild,this._fragmentEnd=e.lastChild,3===this._fragmentStart.nodeType&&(this._fragmentStart.data=this._fragmentEnd.data=""),this._fragment=e):this.$el=e,this.$el.__vue__=this,this._callHook("beforeCompile")},e.prototype._bindDir=function(e,t,n,r,i){this._directives.push(new vn(e,this,t,n,r,i))},e.prototype._destroy=function(e,t){if(this._isBeingDestroyed)return void(t||this._cleanup());var n,r,i=this,a=function(){!n||r||t||i._cleanup(); -};e&&this.$el&&(r=!0,this.$remove(function(){r=!1,a()})),this._callHook("beforeDestroy"),this._isBeingDestroyed=!0;var o,s=this.$parent;for(s&&!s._isBeingDestroyed&&(s.$children.$remove(this),this._updateRef(!0)),o=this.$children.length;o--;)this.$children[o].$destroy();for(this._propsUnlinkFn&&this._propsUnlinkFn(),this._unlinkFn&&this._unlinkFn(),o=this._watchers.length;o--;)this._watchers[o].teardown();this.$el&&(this.$el.__vue__=null),n=!0,a()},e.prototype._cleanup=function(){this._isDestroyed||(this._frag&&this._frag.children.$remove(this),this._data&&this._data.__ob__&&this._data.__ob__.removeVm(this),this.$el=this.$parent=this.$root=this.$children=this._watchers=this._context=this._scope=this._directives=null,this._isDestroyed=!0,this._callHook("destroyed"),this.$off())}}function yn(e){e.prototype._applyFilters=function(e,t,n,r){var i,a,o,s,l,u,c,p,h;for(u=0,c=n.length;c>u;u++)if(i=n[r?c-u-1:u],a=ye(this.$options,"filters",i.name,!0),a&&(a=r?a.write:a.read||a,"function"==typeof a)){if(o=r?[e,t]:[e],l=r?2:1,i.args)for(p=0,h=i.args.length;h>p;p++)s=i.args[p],o[p+l]=s.dynamic?this.$get(s.value):s.value;e=a.apply(this,o)}return e},e.prototype._resolveComponent=function(t,n){var r;if(r="function"==typeof t?t:ye(this.$options,"components",t,!0))if(r.options)n(r);else if(r.resolved)n(r.resolved);else if(r.requested)r.pendingCallbacks.push(n);else{r.requested=!0;var i=r.pendingCallbacks=[n];r.call(this,function(t){y(t)&&(t=e.extend(t)),r.resolved=t;for(var n=0,a=i.length;a>n;n++)i[n](t)},function(e){})}}}function gn(e){function n(e){return JSON.parse(JSON.stringify(e))}e.prototype.$get=function(e,t){var n=Be(e);if(n){if(t){var r=this;return function(){r.$arguments=d(arguments);var e=n.get.call(r,r);return r.$arguments=null,e}}try{return n.get.call(this,this)}catch(i){}}},e.prototype.$set=function(e,t){var n=Be(e,!0);n&&n.set&&n.set.call(this,this,t)},e.prototype.$delete=function(e){t(this._data,e)},e.prototype.$watch=function(e,t,n){var r,i=this;"string"==typeof e&&(r=E(e),e=r.expression);var a=new ze(i,e,t,{deep:n&&n.deep,sync:n&&n.sync,filters:r&&r.filters,user:!n||n.user!==!1});return n&&n.immediate&&t.call(i,a.value),function(){a.teardown()}},e.prototype.$eval=function(e,t){if(no.test(e)){var n=E(e),r=this.$get(n.expression,t);return n.filters?this._applyFilters(r,null,n.filters):r}return this.$get(e,t)},e.prototype.$interpolate=function(e){var t=A(e),n=this;return t?1===t.length?n.$eval(t[0].value)+"":t.map(function(e){return e.tag?n.$eval(e.value):e.value}).join(""):e},e.prototype.$log=function(e){var t=e?Ne(this._data,e):this._data;if(t&&(t=n(t)),!e){var r;for(r in this.$options.computed)t[r]=n(this[r]);if(this._props)for(r in this._props)t[r]=n(this[r])}console.log(t)}}function bn(e){function t(e,t,r,i,a,o){t=n(t);var s=!R(t),l=i===!1||s?a:o,u=!s&&!e._isAttached&&!R(e.$el);return e._isFragment?(ae(e._fragmentStart,e._fragmentEnd,function(n){l(n,t,e)}),r&&r()):l(e.$el,t,e,r),u&&e._callHook("attached"),e}function n(e){return"string"==typeof e?document.querySelector(e):e}function r(e,t,n,r){t.appendChild(e),r&&r()}function i(e,t,n,r){V(e,t),r&&r()}function a(e,t,n){W(e),n&&n()}e.prototype.$nextTick=function(e){Yn(e,this)},e.prototype.$appendTo=function(e,n,i){return t(this,e,n,i,r,P)},e.prototype.$prependTo=function(e,t,r){return e=n(e),e.hasChildNodes()?this.$before(e.firstChild,t,r):this.$appendTo(e,t,r),this},e.prototype.$before=function(e,n,r){return t(this,e,n,r,i,j)},e.prototype.$after=function(e,t,r){return e=n(e),e.nextSibling?this.$before(e.nextSibling,t,r):this.$appendTo(e.parentNode,t,r),this},e.prototype.$remove=function(e,t){if(!this.$el.parentNode)return e&&e();var n=this._isAttached&&R(this.$el);n||(t=!1);var r=this,i=function(){n&&r._callHook("detached"),e&&e()};if(this._isFragment)oe(this._fragmentStart,this._fragmentEnd,this,this._fragment,i);else{var o=t===!1?a:T;o(this.$el,this,i)}return this}}function _n(e){function t(e,t,r){var i=e.$parent;if(i&&r&&!n.test(t))for(;i;)i._eventsCount[t]=(i._eventsCount[t]||0)+r,i=i.$parent}e.prototype.$on=function(e,n){return(this._events[e]||(this._events[e]=[])).push(n),t(this,e,1),this},e.prototype.$once=function(e,t){function n(){r.$off(e,n),t.apply(this,arguments)}var r=this;return n.fn=t,this.$on(e,n),this},e.prototype.$off=function(e,n){var r;if(!arguments.length){if(this.$parent)for(e in this._events)r=this._events[e],r&&t(this,e,-r.length);return this._events={},this}if(r=this._events[e],!r)return this;if(1===arguments.length)return t(this,e,-r.length),this._events[e]=null,this;for(var i,a=r.length;a--;)if(i=r[a],i===n||i.fn===n){t(this,e,-1),r.splice(a,1);break}return this},e.prototype.$emit=function(e){var t="string"==typeof e;e=t?e:e.name;var n=this._events[e],r=t||!n;if(n){n=n.length>1?d(n):n;var i=t&&n.some(function(e){return e._fromParent});i&&(r=!1);for(var a=d(arguments,1),o=0,s=n.length;s>o;o++){var l=n[o],u=l.apply(this,a);u!==!0||i&&!l._fromParent||(r=!0)}}return r},e.prototype.$broadcast=function(e){var t="string"==typeof e;if(e=t?e:e.name,this._eventsCount[e]){var n=this.$children,r=d(arguments);t&&(r[0]={name:e,source:this});for(var i=0,a=n.length;a>i;i++){var o=n[i],s=o.$emit.apply(o,r);s&&o.$broadcast.apply(o,r)}return this}},e.prototype.$dispatch=function(e){var t=this.$emit.apply(this,arguments);if(t){var n=this.$parent,r=d(arguments);for(r[0]={name:e,source:this};n;)t=n.$emit.apply(n,r),n=t?n.$parent:null;return this}};var n=/^hook:/}function xn(e){function t(){this._isAttached=!0,this._isReady=!0,this._callHook("ready")}e.prototype.$mount=function(e){return this._isCompiled?void 0:(e=D(e),e||(e=document.createElement("div")),this._compile(e),this._initDOMHooks(),R(this.$el)?(this._callHook("attached"),t.call(this)):this.$once("hook:attached",t),this)},e.prototype.$destroy=function(e,t){this._destroy(e,t)},e.prototype.$compile=function(e,t,n,r){return jt(e,this.$options,!0)(this,e,t,n,r)}}function wn(e){this._init(e)}function kn(e,t,n){return n=n?parseInt(n,10):0,t=o(t),"number"==typeof t?e.slice(n,n+t):e}function Sn(e,t,n){if(e=oo(e),null==t)return e;if("function"==typeof t)return e.filter(t);t=(""+t).toLowerCase();for(var r,i,a,o,s="in"===n?3:2,l=Array.prototype.concat.apply([],d(arguments,s)),u=[],c=0,p=e.length;p>c;c++)if(r=e[c],a=r&&r.$value||r,o=l.length){for(;o--;)if(i=l[o],"$key"===i&&En(r.$key,t)||En(Ne(a,i),t)){u.push(r);break}}else En(r,t)&&u.push(r);return u}function Cn(e){function t(e,t,n){var i=r[n];return i&&("$key"!==i&&(m(e)&&"$value"in e&&(e=e.$value),m(t)&&"$value"in t&&(t=t.$value)),e=m(e)?Ne(e,i):e,t=m(t)?Ne(t,i):t),e===t?0:e>t?a:-a}var n=null,r=void 0;e=oo(e);var i=d(arguments,1),a=i[i.length-1];"number"==typeof a?(a=0>a?-1:1,i=i.length>1?i.slice(0,-1):i):a=1;var o=i[0];return o?("function"==typeof o?n=function(e,t){return o(e,t)*a}:(r=Array.prototype.concat.apply([],i),n=function(e,i,a){return a=a||0,a>=r.length-1?t(e,i,a):t(e,i,a)||n(e,i,a+1)}),e.slice().sort(n)):e}function En(e,t){var n;if(y(e)){var r=Object.keys(e);for(n=r.length;n--;)if(En(e[r[n]],t))return!0}else if(Tn(e)){for(n=e.length;n--;)if(En(e[n],t))return!0}else if(null!=e)return e.toString().toLowerCase().indexOf(t)>-1}function On(n){n.options={directives:Oa,elementDirectives:ao,filters:lo,transitions:{},components:{},partials:{},replace:!0},n.util=Br,n.config=Er,n.set=e,n["delete"]=t,n.nextTick=Yn,n.compiler=eo,n.FragmentFactory=at,n.internalDirectives=za,n.parsers={path:ui,text:kr,template:Ui,directive:yr,expression:ki},n.cid=0;var r=1;n.extend=function(e){e=e||{};var t=this,i=0===t.cid;if(i&&e._Ctor)return e._Ctor;var a=e.name||t.options.name,o=function(e){n.call(this,e)};return o.prototype=Object.create(t.prototype),o.prototype.constructor=o,o.cid=r++,o.options=me(t.options,e),o["super"]=t,o.extend=t.extend,Er._assetTypes.forEach(function(e){o[e]=t[e]}),a&&(o.options.components[a]=o),i&&(e._Ctor=o),o},n.use=function(e){if(!e.installed){var t=d(arguments,1);return t.unshift(this),"function"==typeof e.install?e.install.apply(e,t):e.apply(null,t),e.installed=!0,this}},n.mixin=function(e){n.options=me(n.options,e)},Er._assetTypes.forEach(function(e){n[e]=function(t,r){return r?("component"===e&&y(r)&&(r.name||(r.name=t),r=n.extend(r)),this.options[e+"s"][t]=r,r):this.options[e+"s"][t]}}),v(n.transition,$r)}var $n=Object.prototype.hasOwnProperty,An=/^\s?(true|false|-?[\d\.]+|'[^']*'|"[^"]*")\s?$/,Nn=/-(\w)/g,Ln=/([a-z\d])([A-Z])/g,In=/(?:^|[-_\/])(\w)/g,Pn=Object.prototype.toString,jn="[object Object]",Tn=Array.isArray,Fn="__proto__"in{},Dn="undefined"!=typeof window&&"[object Object]"!==Object.prototype.toString.call(window),Rn=Dn&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,Bn=Dn&&window.navigator.userAgent.toLowerCase(),Un=Bn&&Bn.indexOf("trident")>0,Mn=Bn&&Bn.indexOf("msie 9.0")>0,Vn=Bn&&Bn.indexOf("android")>0,Hn=Bn&&/(iphone|ipad|ipod|ios)/i.test(Bn),Wn=Hn&&Bn.match(/os ([\d_]+)/),zn=Wn&&Wn[1].split("_"),qn=zn&&Number(zn[0])>=9&&Number(zn[1])>=3&&!window.indexedDB,Gn=void 0,Jn=void 0,Kn=void 0,Qn=void 0;if(Dn&&!Mn){var Xn=void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend,Zn=void 0===window.onanimationend&&void 0!==window.onwebkitanimationend;Gn=Xn?"WebkitTransition":"transition",Jn=Xn?"webkitTransitionEnd":"transitionend",Kn=Zn?"WebkitAnimation":"animation",Qn=Zn?"webkitAnimationEnd":"animationend"}var Yn=function(){function e(){r=!1;var e=n.slice(0);n=[];for(var t=0;t<e.length;t++)e[t]()}var t,n=[],r=!1;if("undefined"==typeof MutationObserver||qn){var i=Dn?window:"undefined"!=typeof global?global:{};t=i.setImmediate||setTimeout}else{var a=1,o=new MutationObserver(e),s=document.createTextNode(a);o.observe(s,{characterData:!0}),t=function(){a=(a+1)%2,s.data=a}}return function(i,a){var o=a?function(){i.call(a)}:i;n.push(o),r||(r=!0,t(e,0))}}(),er=void 0;"undefined"!=typeof Set&&Set.toString().match(/native code/)?er=Set:(er=function(){this.set=Object.create(null)},er.prototype.has=function(e){return void 0!==this.set[e]},er.prototype.add=function(e){this.set[e]=1},er.prototype.clear=function(){this.set=Object.create(null)});var tr=k.prototype;tr.put=function(e,t){var n,r=this.get(e,!0);return r||(this.size===this.limit&&(n=this.shift()),r={key:e},this._keymap[e]=r,this.tail?(this.tail.newer=r,r.older=this.tail):this.head=r,this.tail=r,this.size++),r.value=t,n},tr.shift=function(){var e=this.head;return e&&(this.head=this.head.newer,this.head.older=void 0,e.newer=e.older=void 0,this._keymap[e.key]=void 0,this.size--),e},tr.get=function(e,t){var n=this._keymap[e];if(void 0!==n)return n===this.tail?t?n:n.value:(n.newer&&(n===this.head&&(this.head=n.newer),n.newer.older=n.older),n.older&&(n.older.newer=n.newer),n.newer=void 0,n.older=this.tail,this.tail&&(this.tail.newer=n),this.tail=n,t?n:n.value)};var nr,rr,ir,ar,or,sr,lr,ur,cr,pr,hr,fr,dr=new k(1e3),vr=/[^\s'"]+|'[^']*'|"[^"]*"/g,mr=/^in$|^-?\d+/,yr=Object.freeze({parseDirective:E}),gr=/[-.*+?^${}()|[\]\/\\]/g,br=void 0,_r=void 0,xr=void 0,wr=/[^|]\|[^|]/,kr=Object.freeze({compileRegex:$,parseText:A,tokensToExp:N}),Sr=["{{","}}"],Cr=["{{{","}}}"],Er=Object.defineProperties({debug:!1,silent:!1,async:!0,warnExpressionErrors:!0,devtools:!1,_delimitersChanged:!0,_assetTypes:["component","directive","elementDirective","filter","transition","partial"],_propBindingModes:{ONE_WAY:0,TWO_WAY:1,ONE_TIME:2},_maxUpdateCount:100},{delimiters:{get:function(){return Sr},set:function(e){Sr=e,$()},configurable:!0,enumerable:!0},unsafeDelimiters:{get:function(){return Cr},set:function(e){Cr=e,$()},configurable:!0,enumerable:!0}}),Or=void 0,$r=Object.freeze({appendWithTransition:P,beforeWithTransition:j,removeWithTransition:T,applyTransition:F}),Ar=/^v-ref:/,Nr=/^(div|p|span|img|a|b|i|br|ul|ol|li|h1|h2|h3|h4|h5|h6|code|pre|table|th|td|tr|form|label|input|select|option|nav|article|section|header|footer)$/i,Lr=/^(slot|partial|component)$/i,Ir=Er.optionMergeStrategies=Object.create(null);Ir.data=function(e,t,n){return n?e||t?function(){var r="function"==typeof t?t.call(n):t,i="function"==typeof e?e.call(n):void 0;return r?pe(r,i):i}:void 0:t?"function"!=typeof t?e:e?function(){return pe(t.call(this),e.call(this))}:t:e},Ir.el=function(e,t,n){if(n||!t||"function"==typeof t){var r=t||e;return n&&"function"==typeof r?r.call(n):r}},Ir.init=Ir.created=Ir.ready=Ir.attached=Ir.detached=Ir.beforeCompile=Ir.compiled=Ir.beforeDestroy=Ir.destroyed=Ir.activate=function(e,t){return t?e?e.concat(t):Tn(t)?t:[t]:e},Er._assetTypes.forEach(function(e){Ir[e+"s"]=he}),Ir.watch=Ir.events=function(e,t){if(!t)return e;if(!e)return t;var n={};v(n,e);for(var r in t){var i=n[r],a=t[r];i&&!Tn(i)&&(i=[i]),n[r]=i?i.concat(a):[a]}return n},Ir.props=Ir.methods=Ir.computed=function(e,t){if(!t)return e;if(!e)return t;var n=Object.create(null);return v(n,e),v(n,t),n};var Pr=function(e,t){return void 0===t?e:t},jr=0;ge.target=null,ge.prototype.addSub=function(e){this.subs.push(e)},ge.prototype.removeSub=function(e){this.subs.$remove(e)},ge.prototype.depend=function(){ge.target.addDep(this)},ge.prototype.notify=function(){for(var e=d(this.subs),t=0,n=e.length;n>t;t++)e[t].update()};var Tr=Array.prototype,Fr=Object.create(Tr);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(e){var t=Tr[e];g(Fr,e,function(){for(var n=arguments.length,r=new Array(n);n--;)r[n]=arguments[n];var i,a=t.apply(this,r),o=this.__ob__;switch(e){case"push":i=r;break;case"unshift":i=r;break;case"splice":i=r.slice(2)}return i&&o.observeArray(i),o.dep.notify(),a})}),g(Tr,"$set",function(e,t){return e>=this.length&&(this.length=Number(e)+1),this.splice(e,1,t)[0]}),g(Tr,"$remove",function(e){if(this.length){var t=_(this,e);return t>-1?this.splice(t,1):void 0}});var Dr=Object.getOwnPropertyNames(Fr),Rr=!0;_e.prototype.walk=function(e){for(var t=Object.keys(e),n=0,r=t.length;r>n;n++)this.convert(t[n],e[t[n]])},_e.prototype.observeArray=function(e){for(var t=0,n=e.length;n>t;t++)ke(e[t])},_e.prototype.convert=function(e,t){Se(this.value,e,t)},_e.prototype.addVm=function(e){(this.vms||(this.vms=[])).push(e)},_e.prototype.removeVm=function(e){this.vms.$remove(e)};var Br=Object.freeze({defineReactive:Se,set:e,del:t,hasOwn:n,isLiteral:r,isReserved:i,_toString:a,toNumber:o,toBoolean:s,stripQuotes:l,camelize:u,hyphenate:p,classify:h,bind:f,toArray:d,extend:v,isObject:m,isPlainObject:y,def:g,debounce:b,indexOf:_,cancellable:x,looseEqual:w,isArray:Tn,hasProto:Fn,inBrowser:Dn,devtools:Rn,isIE:Un,isIE9:Mn,isAndroid:Vn,isIos:Hn,iosVersionMatch:Wn,iosVersion:zn,hasMutationObserverBug:qn,get transitionProp(){return Gn},get transitionEndEvent(){return Jn},get animationProp(){return Kn},get animationEndEvent(){return Qn},nextTick:Yn,get _Set(){return er},query:D,inDoc:R,getAttr:B,getBindAttr:U,hasBindAttr:M,before:V,after:H,remove:W,prepend:z,replace:q,on:G,off:J,setClass:Q,addClass:X,removeClass:Z,extractContent:Y,trimNode:ee,isTemplate:ne,createAnchor:re,findRef:ie,mapNodeRange:ae,removeNodeRange:oe,isFragment:se,getOuterHTML:le,mergeOptions:me,resolveAsset:ye,checkComponentAttr:ue,commonTagRE:Nr,reservedTagRE:Lr,warn:Or}),Ur=0,Mr="undefined"!=typeof window?window:"undefined"!=typeof global?global:this,Vr=function(e,t){function n(e){if(!(this instanceof n))return new n(e);this.context=e;for(var t=0;t<s.length;t++)this.context[s[t]]||(this.context[s[t]]=o(u[t]))}function r(e){return e.prototype}function i(e){return t[e]}function a(e,t){e.__proto__=t}function o(e){var t=Object.create(e.prototype),n=function(){if(!(this instanceof n)){var r=e.apply(null,arguments);return a(r,t),r}e.apply(this,arguments)};return a(n,e),n.prototype=t,n.wrapped=!0,n}var s=(e.exports,["Object","String","Boolean","Number","RegExp","Date","Array"]),l={string:"String","boolean":"Boolean",number:"Number"},u=s.map(i),c=u.map(r);return e.exports=n,n.prototype.replace=function(e){var t=u.indexOf(e),n=c.indexOf(e);if(~t){var r=s[t];return this.context[r]}if(~n){var r=s[n];return this.context[r].prototype}return e},n.prototype.getPropertyObject=function(e,t){return l[typeof e]?this.getPrototypeOf(e):e},n.prototype.isPrimitive=function(e){return!!~u.indexOf(e)||!!~c.indexOf(e)},n.prototype.getPrototypeOf=function(e){if(null==e)return e;var t=l[typeof e];if(t)var n=this.context[t].prototype;else var n=Object.getPrototypeOf(e);if(n&&n!==Object.prototype){var r=this.replace(n);return r===e&&(r=this.replace(Object.prototype)),r}return null},n.prototype.applyNew=function(e,t){if(e.wrapped){var n=Object.getPrototypeOf(e),r=new(Function.prototype.bind.apply(n,arguments));return a(r,e.prototype),r}return new(Function.prototype.bind.apply(e,arguments))},e.exports}({exports:{}},Mr),Hr=function(e){function t(e){return this instanceof t?(this.maxIterations=e,void(this.count=0)):new t(e)}e.exports;return e.exports=t,t.prototype.check=function(){if(this.count+=1,this.count>this.maxIterations)throw new Error("Infinite loop detected - reached max iterations")},e.exports}({exports:{}}),Wr=function(e){function t(e){function i(e){for(var t=null,n=0;n<e.length;n++){var r=e[n];if("EmptyStatement"!==r.type){var t=a(r);"remove"===t&&e.splice(n--,1)}}}function a(e){var r=o[o.length-1],u=!1;o.push(e);var c=!1;n(e,r)&&(t(e.body),c=!0),"VariableDeclarator"===e.type&&s.push(e),"FunctionDeclaration"===e.type&&(l.push(e),u=!0);for(var p in e)"type"===p||c&&"body"===p||p in e&&e[p]&&"object"==typeof e[p]&&(e[p].type?a(e[p]):Array.isArray(e[p])&&i(e[p]));return o.pop(),u?"remove":void 0}var o=[],s=[],l=[];return Array.isArray(e)?(i(e),r(e,s,l)):a(e),e}function n(e,t){return"Program"===e.type?!0:"BlockStatement"!==e.type||!t||"FunctionExpression"!==t.type&&"FunctionDeclaration"!==t.type?void 0:!0}function r(e,t,n){if(t&&t.length){for(var r=[],i=0;i<t.length;i++)r.push({type:"VariableDeclarator",id:t[i].id,init:null});e.unshift({type:"VariableDeclaration",kind:"var",declarations:r})}if(n&&n.length)for(var i=0;i<n.length;i++)e.unshift(n[i])}e.exports;return e.exports=t,e.exports}({exports:{}}),zr=function(e){var t=e.exports;return function(e,n){"function"==typeof define&&define.amd?define(["exports"],n):n("undefined"!=typeof t?t:e.esprima={})}(this,function(e){function t(e,t){if(!e)throw new Error("ASSERT: "+t)}function n(e,t){return ht.slice(e,t)}function r(e){return"0123456789".indexOf(e)>=0}function i(e){return"0123456789abcdefABCDEF".indexOf(e)>=0}function a(e){return"01234567".indexOf(e)>=0}function o(e){return" "===e||" "===e||"\x0B"===e||"\f"===e||"\xa0"===e||e.charCodeAt(0)>=5760&&"\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff".indexOf(e)>=0}function s(e){return"\n"===e||"\r"===e||"\u2028"===e||"\u2029"===e}function l(e){return"$"===e||"_"===e||"\\"===e||e>="a"&&"z">=e||e>="A"&&"Z">=e||e.charCodeAt(0)>=128&&pt.NonAsciiIdentifierStart.test(e)}function u(e){return"$"===e||"_"===e||"\\"===e||e>="a"&&"z">=e||e>="A"&&"Z">=e||e>="0"&&"9">=e||e.charCodeAt(0)>=128&&pt.NonAsciiIdentifierPart.test(e)}function c(e){switch(e){case"class":case"enum":case"export":case"extends":case"import":case"super":return!0}return!1}function p(e){switch(e){case"implements":case"interface":case"package":case"private":case"protected":case"public":case"static":case"yield":case"let":return!0}return!1}function h(e){return"eval"===e||"arguments"===e}function f(e){var t=!1;switch(e.length){case 2:t="if"===e||"in"===e||"do"===e;break;case 3:t="var"===e||"for"===e||"new"===e||"try"===e;break;case 4:t="this"===e||"else"===e||"case"===e||"void"===e||"with"===e;break;case 5:t="while"===e||"break"===e||"catch"===e||"throw"===e;break;case 6:t="return"===e||"typeof"===e||"delete"===e||"switch"===e;break;case 7:t="default"===e||"finally"===e;break;case 8:t="function"===e||"continue"===e||"debugger"===e;break;case 10:t="instanceof"===e}if(t)return!0;switch(e){case"const":return!0;case"yield":case"let":return!0}return ft&&p(e)?!0:c(e)}function d(){var e,t,n;for(t=!1,n=!1;yt>dt;)if(e=ht[dt],n)e=ht[dt++],s(e)&&(n=!1,"\r"===e&&"\n"===ht[dt]&&++dt,++vt,mt=dt);else if(t)s(e)?("\r"===e&&"\n"===ht[dt+1]&&++dt,++vt,++dt,mt=dt,dt>=yt&&E({},ct.UnexpectedToken,"ILLEGAL")):(e=ht[dt++],dt>=yt&&E({},ct.UnexpectedToken,"ILLEGAL"),"*"===e&&(e=ht[dt],"/"===e&&(++dt,t=!1)));else if("/"===e)if(e=ht[dt+1],"/"===e)dt+=2,n=!0;else{if("*"!==e)break;dt+=2,t=!0,dt>=yt&&E({},ct.UnexpectedToken,"ILLEGAL")}else if(o(e))++dt;else{if(!s(e))break;++dt,"\r"===e&&"\n"===ht[dt]&&++dt,++vt,mt=dt}}function v(e){var t,n,r,a=0;for(n="u"===e?4:2,t=0;n>t;++t){if(!(yt>dt&&i(ht[dt])))return"";r=ht[dt++],a=16*a+"0123456789abcdef".indexOf(r.toLowerCase())}return String.fromCharCode(a)}function m(){var e,t,n,r;if(e=ht[dt],l(e)){if(t=dt,"\\"===e){if(++dt,"u"!==ht[dt])return;if(++dt,r=dt,e=v("u")){if("\\"===e||!l(e))return;n=e}else dt=r,n="u"}else n=ht[dt++];for(;yt>dt&&(e=ht[dt],u(e));)if("\\"===e){if(++dt,"u"!==ht[dt])return;if(++dt,r=dt,e=v("u")){if("\\"===e||!u(e))return;n+=e}else dt=r,n+="u"}else n+=ht[dt++];return 1===n.length?{type:ot.Identifier,value:n,lineNumber:vt,lineStart:mt,range:[t,dt]}:f(n)?{type:ot.Keyword,value:n,lineNumber:vt,lineStart:mt,range:[t,dt]}:"null"===n?{type:ot.NullLiteral,value:n,lineNumber:vt,lineStart:mt,range:[t,dt]}:"true"===n||"false"===n?{type:ot.BooleanLiteral,value:n,lineNumber:vt,lineStart:mt,range:[t,dt]}:{type:ot.Identifier,value:n,lineNumber:vt,lineStart:mt,range:[t,dt]}}}function y(){var e,t,n,i=dt,a=ht[dt];return";"===a||"{"===a||"}"===a?(++dt,{type:ot.Punctuator,value:a,lineNumber:vt,lineStart:mt,range:[i,dt]}):","===a||"("===a||")"===a?(++dt,{type:ot.Punctuator,value:a,lineNumber:vt,lineStart:mt,range:[i,dt]}):(e=ht[dt+1],"."!==a||r(e)?(t=ht[dt+2],n=ht[dt+3],">"===a&&">"===e&&">"===t&&"="===n?(dt+=4,{type:ot.Punctuator,value:">>>=",lineNumber:vt,lineStart:mt,range:[i,dt]}):"="===a&&"="===e&&"="===t?(dt+=3,{type:ot.Punctuator,value:"===",lineNumber:vt,lineStart:mt,range:[i,dt]}):"!"===a&&"="===e&&"="===t?(dt+=3,{type:ot.Punctuator,value:"!==",lineNumber:vt,lineStart:mt,range:[i,dt]}):">"===a&&">"===e&&">"===t?(dt+=3,{type:ot.Punctuator,value:">>>",lineNumber:vt,lineStart:mt,range:[i,dt]}):"<"===a&&"<"===e&&"="===t?(dt+=3,{type:ot.Punctuator,value:"<<=",lineNumber:vt,lineStart:mt,range:[i,dt]}):">"===a&&">"===e&&"="===t?(dt+=3,{type:ot.Punctuator,value:">>=",lineNumber:vt,lineStart:mt,range:[i,dt]}):"="===e&&"<>=!+-*%&|^/".indexOf(a)>=0?(dt+=2,{type:ot.Punctuator,value:a+e,lineNumber:vt,lineStart:mt,range:[i,dt]}):a===e&&"+-<>&|".indexOf(a)>=0&&"+-<>&|".indexOf(e)>=0?(dt+=2,{type:ot.Punctuator,value:a+e,lineNumber:vt,lineStart:mt,range:[i,dt]}):"[]<>+-*%&|^!~?:=/".indexOf(a)>=0?{type:ot.Punctuator,value:ht[dt++],lineNumber:vt,lineStart:mt,range:[i,dt]}:void 0):{type:ot.Punctuator,value:ht[dt++],lineNumber:vt,lineStart:mt,range:[i,dt]})}function g(){var e,n,o;if(o=ht[dt],t(r(o)||"."===o,"Numeric literal must start with a decimal digit or a decimal point"),n=dt,e="","."!==o){if(e=ht[dt++],o=ht[dt],"0"===e){if("x"===o||"X"===o){for(e+=ht[dt++];yt>dt&&(o=ht[dt],i(o));)e+=ht[dt++];return e.length<=2&&E({},ct.UnexpectedToken,"ILLEGAL"),yt>dt&&(o=ht[dt],l(o)&&E({},ct.UnexpectedToken,"ILLEGAL")),{type:ot.NumericLiteral,value:parseInt(e,16),lineNumber:vt,lineStart:mt,range:[n,dt]}}if(a(o)){for(e+=ht[dt++];yt>dt&&(o=ht[dt],a(o));)e+=ht[dt++];return yt>dt&&(o=ht[dt],(l(o)||r(o))&&E({},ct.UnexpectedToken,"ILLEGAL")),{type:ot.NumericLiteral,value:parseInt(e,8),octal:!0,lineNumber:vt,lineStart:mt,range:[n,dt]}}r(o)&&E({},ct.UnexpectedToken,"ILLEGAL")}for(;yt>dt&&(o=ht[dt],r(o));)e+=ht[dt++]}if("."===o)for(e+=ht[dt++];yt>dt&&(o=ht[dt],r(o));)e+=ht[dt++];if("e"===o||"E"===o)if(e+=ht[dt++],o=ht[dt],"+"!==o&&"-"!==o||(e+=ht[dt++]),o=ht[dt],r(o))for(e+=ht[dt++];yt>dt&&(o=ht[dt],r(o));)e+=ht[dt++];else o="character "+o,dt>=yt&&(o="<end>"),E({},ct.UnexpectedToken,"ILLEGAL");return yt>dt&&(o=ht[dt],l(o)&&E({},ct.UnexpectedToken,"ILLEGAL")),{type:ot.NumericLiteral,value:parseFloat(e),lineNumber:vt,lineStart:mt,range:[n,dt]}}function b(){var e,n,r,i,o,l,u="",c=!1;for(e=ht[dt],t("'"===e||'"'===e,"String literal must starts with a quote"),n=dt,++dt;yt>dt;){if(r=ht[dt++],r===e){e="";break}if("\\"===r)if(r=ht[dt++],s(r))++vt,"\r"===r&&"\n"===ht[dt]&&++dt;else switch(r){case"n":u+="\n";break;case"r":u+="\r";break;case"t":u+=" ";break;case"u":case"x":l=dt,o=v(r),o?u+=o:(dt=l,u+=r);break;case"b":u+="\b";break;case"f":u+="\f";break;case"v":u+="\x0B";break;default:a(r)?(i="01234567".indexOf(r),0!==i&&(c=!0),yt>dt&&a(ht[dt])&&(c=!0,i=8*i+"01234567".indexOf(ht[dt++]),"0123".indexOf(r)>=0&&yt>dt&&a(ht[dt])&&(i=8*i+"01234567".indexOf(ht[dt++]))),u+=String.fromCharCode(i)):u+=r}else{if(s(r))break;u+=r}}return""!==e&&E({},ct.UnexpectedToken,"ILLEGAL"),{type:ot.StringLiteral,value:u,octal:c,lineNumber:vt,lineStart:mt,range:[n,dt]}}function _(){var e,n,r,i,a,o,l,c=!1,p=!1;for(gt=null,d(),r=dt,n=ht[dt],t("/"===n,"Regular expression literal must start with a slash"),e=ht[dt++];yt>dt;)if(n=ht[dt++],e+=n,"\\"===n)n=ht[dt++],s(n)&&E({},ct.UnterminatedRegExp),e+=n;else if(c)"]"===n&&(c=!1);else{if("/"===n){p=!0;break}"["===n?c=!0:s(n)&&E({},ct.UnterminatedRegExp)}for(p||E({},ct.UnterminatedRegExp),i=e.substr(1,e.length-2),a="";yt>dt&&(n=ht[dt],u(n));)if(++dt,"\\"===n&&yt>dt)if(n=ht[dt],"u"===n)if(++dt,l=dt,n=v("u"))for(a+=n,e+="\\u";dt>l;++l)e+=ht[l];else dt=l,a+="u",e+="\\u";else e+="\\";else a+=n,e+=n;try{o=new RegExp(i,a)}catch(h){E({},ct.InvalidRegExp)}return{literal:e,value:o,range:[r,dt]}}function x(e){return e.type===ot.Identifier||e.type===ot.Keyword||e.type===ot.BooleanLiteral||e.type===ot.NullLiteral}function w(){var e,t;return d(),dt>=yt?{type:ot.EOF,lineNumber:vt,lineStart:mt,range:[dt,dt]}:(t=y(),"undefined"!=typeof t?t:(e=ht[dt],"'"===e||'"'===e?b():"."===e||r(e)?g():(t=m(),"undefined"!=typeof t?t:void E({},ct.UnexpectedToken,"ILLEGAL"))))}function k(){var e;return gt?(dt=gt.range[1],vt=gt.lineNumber,mt=gt.lineStart,e=gt,gt=null,e):(gt=null,w())}function S(){var e,t,n;return null!==gt?gt:(e=dt,t=vt,n=mt,gt=w(),dt=e,vt=t,mt=n,gt)}function C(){var e,t,n,r;return e=dt,t=vt,n=mt,d(),r=vt!==t,dt=e,vt=t,mt=n,r}function E(e,t){var n,r=Array.prototype.slice.call(arguments,2),i=t.replace(/%(\d)/g,function(e,t){return r[t]||""});throw"number"==typeof e.lineNumber?(n=new Error("Line "+e.lineNumber+": "+i),n.index=e.range[0],n.lineNumber=e.lineNumber,n.column=e.range[0]-mt+1):(n=new Error("Line "+vt+": "+i),n.index=dt,n.lineNumber=vt,n.column=dt-mt+1),n}function O(){try{E.apply(null,arguments)}catch(e){if(!_t.errors)throw e;_t.errors.push(e)}}function $(e){if(e.type===ot.EOF&&E(e,ct.UnexpectedEOS),e.type===ot.NumericLiteral&&E(e,ct.UnexpectedNumber),e.type===ot.StringLiteral&&E(e,ct.UnexpectedString),e.type===ot.Identifier&&E(e,ct.UnexpectedIdentifier),e.type===ot.Keyword){if(c(e.value))E(e,ct.UnexpectedReserved);else if(ft&&p(e.value))return void O(e,ct.StrictReservedWord);E(e,ct.UnexpectedToken,e.value)}E(e,ct.UnexpectedToken,e.value)}function A(e){var t=k();t.type===ot.Punctuator&&t.value===e||$(t)}function N(e){var t=k();t.type===ot.Keyword&&t.value===e||$(t)}function L(e){var t=S();return t.type===ot.Punctuator&&t.value===e}function I(e){var t=S();return t.type===ot.Keyword&&t.value===e}function P(){var e=S(),t=e.value;return e.type!==ot.Punctuator?!1:"="===t||"*="===t||"/="===t||"%="===t||"+="===t||"-="===t||"<<="===t||">>="===t||">>>="===t||"&="===t||"^="===t||"|="===t}function j(){var e,t;if(";"===ht[dt])return void k();if(t=vt,d(),vt===t){if(L(";"))return void k();e=S(),e.type===ot.EOF||L("}")||$(e)}}function T(e){return e.type===lt.Identifier||e.type===lt.MemberExpression}function F(){var e=[];for(A("[");!L("]");)L(",")?(k(),e.push(null)):(e.push(ue()),L("]")||A(","));return A("]"),{type:lt.ArrayExpression,elements:e}}function D(e,t){var n,r;return n=ft,r=Fe(),t&&ft&&h(e[0].name)&&O(t,ct.StrictParamName),ft=n,{type:lt.FunctionExpression,id:null,params:e,defaults:[],body:r,rest:null,generator:!1,expression:!1}}function R(){var e=k();return e.type===ot.StringLiteral||e.type===ot.NumericLiteral?(ft&&e.octal&&O(e,ct.StrictOctalLiteral),Je(e)):{type:lt.Identifier,name:e.value}}function B(){var e,t,n,r;return e=S(),e.type===ot.Identifier?(n=R(),"get"!==e.value||L(":")?"set"!==e.value||L(":")?(A(":"),{type:lt.Property,key:n,value:ue(),kind:"init"}):(t=R(),A("("),e=S(),e.type!==ot.Identifier?(A(")"),O(e,ct.UnexpectedToken,e.value),{type:lt.Property,key:t,value:D([]),kind:"set"}):(r=[fe()],A(")"),{type:lt.Property,key:t,value:D(r,e),kind:"set"})):(t=R(),A("("),A(")"),{type:lt.Property,key:t,value:D([]),kind:"get"})):e.type!==ot.EOF&&e.type!==ot.Punctuator?(t=R(),A(":"),{type:lt.Property,key:t,value:ue(),kind:"init"}):void $(e)}function U(){var e,t,n,r=[],i={},a=String;for(A("{");!L("}");)e=B(),t=e.key.type===lt.Identifier?e.key.name:a(e.key.value),n="init"===e.kind?ut.Data:"get"===e.kind?ut.Get:ut.Set,Object.prototype.hasOwnProperty.call(i,t)?(i[t]===ut.Data?ft&&n===ut.Data?O({},ct.StrictDuplicateProperty):n!==ut.Data&&O({},ct.AccessorDataProperty):n===ut.Data?O({},ct.AccessorDataProperty):i[t]&n&&O({},ct.AccessorGetSet),i[t]|=n):i[t]=n,r.push(e),L("}")||A(",");return A("}"),{type:lt.ObjectExpression,properties:r}}function M(){var e;return A("("),e=ce(),A(")"),e}function V(){var e=S(),t=e.type;if(t===ot.Identifier)return{type:lt.Identifier,name:k().value};if(t===ot.StringLiteral||t===ot.NumericLiteral)return ft&&e.octal&&O(e,ct.StrictOctalLiteral),Je(k());if(t===ot.Keyword){if(I("this"))return k(),{type:lt.ThisExpression};if(I("function"))return Re()}return t===ot.BooleanLiteral?(k(),e.value="true"===e.value,Je(e)):t===ot.NullLiteral?(k(),e.value=null,Je(e)):L("[")?F():L("{")?U():L("(")?M():L("/")||L("/=")?Je(_()):$(k())}function H(){var e=[];if(A("("),!L(")"))for(;yt>dt&&(e.push(ue()),!L(")"));)A(",");return A(")"),e}function W(){var e=k();return x(e)||$(e),{type:lt.Identifier,name:e.value}}function z(){return A("."),W()}function q(){var e;return A("["),e=ce(),A("]"),e}function G(){var e;return N("new"),e={type:lt.NewExpression,callee:K(),arguments:[]},L("(")&&(e.arguments=H()),e}function J(){var e;for(e=I("new")?G():V();L(".")||L("[")||L("(");)e=L("(")?{type:lt.CallExpression,callee:e,arguments:H()}:L("[")?{type:lt.MemberExpression,computed:!0,object:e,property:q()}:{type:lt.MemberExpression,computed:!1,object:e,property:z()};return e}function K(){var e;for(e=I("new")?G():V();L(".")||L("[");)e=L("[")?{type:lt.MemberExpression,computed:!0,object:e,property:q()}:{type:lt.MemberExpression,computed:!1,object:e,property:z()};return e}function Q(){var e,t=J();return e=S(),e.type!==ot.Punctuator?t:(!L("++")&&!L("--")||C()||(ft&&t.type===lt.Identifier&&h(t.name)&&O({},ct.StrictLHSPostfix),T(t)||O({},ct.InvalidLHSInAssignment),t={type:lt.UpdateExpression,operator:k().value,argument:t,prefix:!1}),t)}function X(){var e,t;return e=S(),e.type!==ot.Punctuator&&e.type!==ot.Keyword?Q():L("++")||L("--")?(e=k(),t=X(),ft&&t.type===lt.Identifier&&h(t.name)&&O({},ct.StrictLHSPrefix),T(t)||O({},ct.InvalidLHSInAssignment),t={type:lt.UpdateExpression,operator:e.value,argument:t,prefix:!0}):L("+")||L("-")||L("~")||L("!")?t={type:lt.UnaryExpression,operator:k().value,argument:X(),prefix:!0}:I("delete")||I("void")||I("typeof")?(t={type:lt.UnaryExpression,operator:k().value,argument:X(),prefix:!0},ft&&"delete"===t.operator&&t.argument.type===lt.Identifier&&O({},ct.StrictDelete),t):Q()}function Z(){for(var e=X();L("*")||L("/")||L("%");)e={type:lt.BinaryExpression,operator:k().value,left:e,right:X()};return e}function Y(){for(var e=Z();L("+")||L("-");)e={type:lt.BinaryExpression,operator:k().value,left:e,right:Z()};return e}function ee(){for(var e=Y();L("<<")||L(">>")||L(">>>");)e={type:lt.BinaryExpression,operator:k().value,left:e,right:Y()};return e}function te(){var e,t;for(t=bt.allowIn,bt.allowIn=!0,e=ee();L("<")||L(">")||L("<=")||L(">=")||t&&I("in")||I("instanceof");)e={type:lt.BinaryExpression,operator:k().value,left:e,right:ee()};return bt.allowIn=t,e}function ne(){for(var e=te();L("==")||L("!=")||L("===")||L("!==");)e={type:lt.BinaryExpression,operator:k().value,left:e,right:te()};return e}function re(){for(var e=ne();L("&");)k(),e={type:lt.BinaryExpression,operator:"&",left:e,right:ne()};return e}function ie(){for(var e=re();L("^");)k(),e={ -type:lt.BinaryExpression,operator:"^",left:e,right:re()};return e}function ae(){for(var e=ie();L("|");)k(),e={type:lt.BinaryExpression,operator:"|",left:e,right:ie()};return e}function oe(){for(var e=ae();L("&&");)k(),e={type:lt.LogicalExpression,operator:"&&",left:e,right:ae()};return e}function se(){for(var e=oe();L("||");)k(),e={type:lt.LogicalExpression,operator:"||",left:e,right:oe()};return e}function le(){var e,t,n;return e=se(),L("?")&&(k(),t=bt.allowIn,bt.allowIn=!0,n=ue(),bt.allowIn=t,A(":"),e={type:lt.ConditionalExpression,test:e,consequent:n,alternate:ue()}),e}function ue(){var e,t;return e=S(),t=le(),P()&&(T(t)||O({},ct.InvalidLHSInAssignment),ft&&t.type===lt.Identifier&&h(t.name)&&O(e,ct.StrictLHSAssignment),t={type:lt.AssignmentExpression,operator:k().value,left:t,right:ue()}),t}function ce(){var e=ue();if(L(","))for(e={type:lt.SequenceExpression,expressions:[e]};yt>dt&&L(",");)k(),e.expressions.push(ue());return e}function pe(){for(var e,t=[];yt>dt&&!L("}")&&(e=Be(),"undefined"!=typeof e);)t.push(e);return t}function he(){var e;return A("{"),e=pe(),A("}"),{type:lt.BlockStatement,body:e}}function fe(){var e=k();return e.type!==ot.Identifier&&$(e),{type:lt.Identifier,name:e.value}}function de(e){var t=fe(),n=null;return ft&&h(t.name)&&O({},ct.StrictVarName),"const"===e?(A("="),n=ue()):L("=")&&(k(),n=ue()),{type:lt.VariableDeclarator,id:t,init:n}}function ve(e){var t=[];do{if(t.push(de(e)),!L(","))break;k()}while(yt>dt);return t}function me(){var e;return N("var"),e=ve(),j(),{type:lt.VariableDeclaration,declarations:e,kind:"var"}}function ye(e){var t;return N(e),t=ve(e),j(),{type:lt.VariableDeclaration,declarations:t,kind:e}}function ge(){return A(";"),{type:lt.EmptyStatement}}function be(){var e=ce();return j(),{type:lt.ExpressionStatement,expression:e}}function _e(){var e,t,n;return N("if"),A("("),e=ce(),A(")"),t=Te(),I("else")?(k(),n=Te()):n=null,{type:lt.IfStatement,test:e,consequent:t,alternate:n}}function xe(){var e,t,n;return N("do"),n=bt.inIteration,bt.inIteration=!0,e=Te(),bt.inIteration=n,N("while"),A("("),t=ce(),A(")"),L(";")&&k(),{type:lt.DoWhileStatement,body:e,test:t}}function we(){var e,t,n;return N("while"),A("("),e=ce(),A(")"),n=bt.inIteration,bt.inIteration=!0,t=Te(),bt.inIteration=n,{type:lt.WhileStatement,test:e,body:t}}function ke(){var e=k();return{type:lt.VariableDeclaration,declarations:ve(),kind:e.value}}function Se(){var e,t,n,r,i,a,o;return e=t=n=null,N("for"),A("("),L(";")?k():(I("var")||I("let")?(bt.allowIn=!1,e=ke(),bt.allowIn=!0,1===e.declarations.length&&I("in")&&(k(),r=e,i=ce(),e=null)):(bt.allowIn=!1,e=ce(),bt.allowIn=!0,I("in")&&(T(e)||O({},ct.InvalidLHSInForIn),k(),r=e,i=ce(),e=null)),"undefined"==typeof r&&A(";")),"undefined"==typeof r&&(L(";")||(t=ce()),A(";"),L(")")||(n=ce())),A(")"),o=bt.inIteration,bt.inIteration=!0,a=Te(),bt.inIteration=o,"undefined"==typeof r?{type:lt.ForStatement,init:e,test:t,update:n,body:a}:{type:lt.ForInStatement,left:r,right:i,body:a,each:!1}}function Ce(){var e,t=null;return N("continue"),";"===ht[dt]?(k(),bt.inIteration||E({},ct.IllegalContinue),{type:lt.ContinueStatement,label:null}):C()?(bt.inIteration||E({},ct.IllegalContinue),{type:lt.ContinueStatement,label:null}):(e=S(),e.type===ot.Identifier&&(t=fe(),Object.prototype.hasOwnProperty.call(bt.labelSet,t.name)||E({},ct.UnknownLabel,t.name)),j(),null!==t||bt.inIteration||E({},ct.IllegalContinue),{type:lt.ContinueStatement,label:t})}function Ee(){var e,t=null;return N("break"),";"===ht[dt]?(k(),bt.inIteration||bt.inSwitch||E({},ct.IllegalBreak),{type:lt.BreakStatement,label:null}):C()?(bt.inIteration||bt.inSwitch||E({},ct.IllegalBreak),{type:lt.BreakStatement,label:null}):(e=S(),e.type===ot.Identifier&&(t=fe(),Object.prototype.hasOwnProperty.call(bt.labelSet,t.name)||E({},ct.UnknownLabel,t.name)),j(),null!==t||bt.inIteration||bt.inSwitch||E({},ct.IllegalBreak),{type:lt.BreakStatement,label:t})}function Oe(){var e,t=null;return N("return"),bt.inFunctionBody||O({},ct.IllegalReturn)," "===ht[dt]&&l(ht[dt+1])?(t=ce(),j(),{type:lt.ReturnStatement,argument:t}):C()?{type:lt.ReturnStatement,argument:null}:(L(";")||(e=S(),L("}")||e.type===ot.EOF||(t=ce())),j(),{type:lt.ReturnStatement,argument:t})}function $e(){var e,t;return ft&&O({},ct.StrictModeWith),N("with"),A("("),e=ce(),A(")"),t=Te(),{type:lt.WithStatement,object:e,body:t}}function Ae(){var e,t,n=[];for(I("default")?(k(),e=null):(N("case"),e=ce()),A(":");yt>dt&&!(L("}")||I("default")||I("case"))&&(t=Te(),"undefined"!=typeof t);)n.push(t);return{type:lt.SwitchCase,test:e,consequent:n}}function Ne(){var e,t,n,r,i;if(N("switch"),A("("),e=ce(),A(")"),A("{"),t=[],L("}"))return k(),{type:lt.SwitchStatement,discriminant:e,cases:t};for(r=bt.inSwitch,bt.inSwitch=!0,i=!1;yt>dt&&!L("}");)n=Ae(),null===n.test&&(i&&E({},ct.MultipleDefaultsInSwitch),i=!0),t.push(n);return bt.inSwitch=r,A("}"),{type:lt.SwitchStatement,discriminant:e,cases:t}}function Le(){var e;return N("throw"),C()&&E({},ct.NewlineAfterThrow),e=ce(),j(),{type:lt.ThrowStatement,argument:e}}function Ie(){var e;return N("catch"),A("("),L(")")&&$(S()),e=fe(),ft&&h(e.name)&&O({},ct.StrictCatchVariable),A(")"),{type:lt.CatchClause,param:e,body:he()}}function Pe(){var e,t=[],n=null;return N("try"),e=he(),I("catch")&&t.push(Ie()),I("finally")&&(k(),n=he()),0!==t.length||n||E({},ct.NoCatchOrFinally),{type:lt.TryStatement,block:e,guardedHandlers:[],handlers:t,finalizer:n}}function je(){return N("debugger"),j(),{type:lt.DebuggerStatement}}function Te(){var e,t,n=S();if(n.type===ot.EOF&&$(n),n.type===ot.Punctuator)switch(n.value){case";":return ge();case"{":return he();case"(":return be()}if(n.type===ot.Keyword)switch(n.value){case"break":return Ee();case"continue":return Ce();case"debugger":return je();case"do":return xe();case"for":return Se();case"function":return De();case"if":return _e();case"return":return Oe();case"switch":return Ne();case"throw":return Le();case"try":return Pe();case"var":return me();case"while":return we();case"with":return $e()}return e=ce(),e.type===lt.Identifier&&L(":")?(k(),Object.prototype.hasOwnProperty.call(bt.labelSet,e.name)&&E({},ct.Redeclaration,"Label",e.name),bt.labelSet[e.name]=!0,t=Te(),delete bt.labelSet[e.name],{type:lt.LabeledStatement,label:e,body:t}):(j(),{type:lt.ExpressionStatement,expression:e})}function Fe(){var e,t,r,i,a,o,s,l,u=[];for(A("{");yt>dt&&(t=S(),t.type===ot.StringLiteral)&&(e=Be(),u.push(e),e.expression.type===lt.Literal);)r=n(t.range[0]+1,t.range[1]-1),"use strict"===r?(ft=!0,i&&O(i,ct.StrictOctalLiteral)):!i&&t.octal&&(i=t);for(a=bt.labelSet,o=bt.inIteration,s=bt.inSwitch,l=bt.inFunctionBody,bt.labelSet={},bt.inIteration=!1,bt.inSwitch=!1,bt.inFunctionBody=!0;yt>dt&&!L("}")&&(e=Be(),"undefined"!=typeof e);)u.push(e);return A("}"),bt.labelSet=a,bt.inIteration=o,bt.inSwitch=s,bt.inFunctionBody=l,{type:lt.BlockStatement,body:u}}function De(){var e,t,n,r,i,a,o,s,l,u=[];if(N("function"),r=S(),e=fe(),ft?h(r.value)&&O(r,ct.StrictFunctionName):h(r.value)?(a=r,o=ct.StrictFunctionName):p(r.value)&&(a=r,o=ct.StrictReservedWord),A("("),!L(")"))for(l={};yt>dt&&(r=S(),t=fe(),ft?(h(r.value)&&(i=r,o=ct.StrictParamName),Object.prototype.hasOwnProperty.call(l,r.value)&&(i=r,o=ct.StrictParamDupe)):a||(h(r.value)?(a=r,o=ct.StrictParamName):p(r.value)?(a=r,o=ct.StrictReservedWord):Object.prototype.hasOwnProperty.call(l,r.value)&&(a=r,o=ct.StrictParamDupe)),u.push(t),l[t.name]=!0,!L(")"));)A(",");return A(")"),s=ft,n=Fe(),ft&&a&&E(a,o),ft&&i&&O(i,o),ft=s,{type:lt.FunctionDeclaration,id:e,params:u,defaults:[],body:n,rest:null,generator:!1,expression:!1}}function Re(){var e,t,n,r,i,a,o,s,l=null,u=[];if(N("function"),L("(")||(e=S(),l=fe(),ft?h(e.value)&&O(e,ct.StrictFunctionName):h(e.value)?(n=e,r=ct.StrictFunctionName):p(e.value)&&(n=e,r=ct.StrictReservedWord)),A("("),!L(")"))for(s={};yt>dt&&(e=S(),i=fe(),ft?(h(e.value)&&(t=e,r=ct.StrictParamName),Object.prototype.hasOwnProperty.call(s,e.value)&&(t=e,r=ct.StrictParamDupe)):n||(h(e.value)?(n=e,r=ct.StrictParamName):p(e.value)?(n=e,r=ct.StrictReservedWord):Object.prototype.hasOwnProperty.call(s,e.value)&&(n=e,r=ct.StrictParamDupe)),u.push(i),s[i.name]=!0,!L(")"));)A(",");return A(")"),o=ft,a=Fe(),ft&&n&&E(n,r),ft&&t&&O(t,r),ft=o,{type:lt.FunctionExpression,id:l,params:u,defaults:[],body:a,rest:null,generator:!1,expression:!1}}function Be(){var e=S();if(e.type===ot.Keyword)switch(e.value){case"const":case"let":return ye(e.value);case"function":return De();default:return Te()}return e.type!==ot.EOF?Te():void 0}function Ue(){for(var e,t,r,i,a=[];yt>dt&&(t=S(),t.type===ot.StringLiteral)&&(e=Be(),a.push(e),e.expression.type===lt.Literal);)r=n(t.range[0]+1,t.range[1]-1),"use strict"===r?(ft=!0,i&&O(i,ct.StrictOctalLiteral)):!i&&t.octal&&(i=t);for(;yt>dt&&(e=Be(),"undefined"!=typeof e);)a.push(e);return a}function Me(){var e;return ft=!1,e={type:lt.Program,body:Ue()}}function Ve(e,n,r,i,a){t("number"==typeof r,"Comment must have valid position"),_t.comments.length>0&&_t.comments[_t.comments.length-1].range[1]>r||_t.comments.push({type:e,value:n,range:[r,i],loc:a})}function He(){var e,t,n,r,i,a;for(e="",i=!1,a=!1;yt>dt;)if(t=ht[dt],a)t=ht[dt++],s(t)?(n.end={line:vt,column:dt-mt-1},a=!1,Ve("Line",e,r,dt-1,n),"\r"===t&&"\n"===ht[dt]&&++dt,++vt,mt=dt,e=""):dt>=yt?(a=!1,e+=t,n.end={line:vt,column:yt-mt},Ve("Line",e,r,yt,n)):e+=t;else if(i)s(t)?("\r"===t&&"\n"===ht[dt+1]?(++dt,e+="\r\n"):e+=t,++vt,++dt,mt=dt,dt>=yt&&E({},ct.UnexpectedToken,"ILLEGAL")):(t=ht[dt++],dt>=yt&&E({},ct.UnexpectedToken,"ILLEGAL"),e+=t,"*"===t&&(t=ht[dt],"/"===t&&(e=e.substr(0,e.length-1),i=!1,++dt,n.end={line:vt,column:dt-mt},Ve("Block",e,r,dt,n),e="")));else if("/"===t)if(t=ht[dt+1],"/"===t)n={start:{line:vt,column:dt-mt}},r=dt,dt+=2,a=!0,dt>=yt&&(n.end={line:vt,column:dt-mt},a=!1,Ve("Line",e,r,dt,n));else{if("*"!==t)break;r=dt,dt+=2,i=!0,n={start:{line:vt,column:dt-mt-2}},dt>=yt&&E({},ct.UnexpectedToken,"ILLEGAL")}else if(o(t))++dt;else{if(!s(t))break;++dt,"\r"===t&&"\n"===ht[dt]&&++dt,++vt,mt=dt}}function We(){var e,t,n,r=[];for(e=0;e<_t.comments.length;++e)t=_t.comments[e],n={type:t.type,value:t.value},_t.range&&(n.range=t.range),_t.loc&&(n.loc=t.loc),r.push(n);_t.comments=r}function ze(){var e,t,r,i,a;return d(),e=dt,t={start:{line:vt,column:dt-mt}},r=_t.advance(),t.end={line:vt,column:dt-mt},r.type!==ot.EOF&&(i=[r.range[0],r.range[1]],a=n(r.range[0],r.range[1]),_t.tokens.push({type:st[r.type],value:a,range:i,loc:t})),r}function qe(){var e,t,n,r;return d(),e=dt,t={start:{line:vt,column:dt-mt}},n=_t.scanRegExp(),t.end={line:vt,column:dt-mt},_t.tokens.length>0&&(r=_t.tokens[_t.tokens.length-1],r.range[0]===e&&"Punctuator"===r.type&&("/"!==r.value&&"/="!==r.value||_t.tokens.pop())),_t.tokens.push({type:"RegularExpression",value:n.literal,range:[e,dt],loc:t}),n}function Ge(){var e,t,n,r=[];for(e=0;e<_t.tokens.length;++e)t=_t.tokens[e],n={type:t.type,value:t.value},_t.range&&(n.range=t.range),_t.loc&&(n.loc=t.loc),r.push(n);_t.tokens=r}function Je(e){return{type:lt.Literal,value:e.value}}function Ke(e){return{type:lt.Literal,value:e.value,raw:n(e.range[0],e.range[1])}}function Qe(){var e={};return e.range=[dt,dt],e.loc={start:{line:vt,column:dt-mt},end:{line:vt,column:dt-mt}},e.end=function(){this.range[1]=dt,this.loc.end.line=vt,this.loc.end.column=dt-mt},e.applyGroup=function(e){_t.range&&(e.groupRange=[this.range[0],this.range[1]]),_t.loc&&(e.groupLoc={start:{line:this.loc.start.line,column:this.loc.start.column},end:{line:this.loc.end.line,column:this.loc.end.column}})},e.apply=function(e){_t.range&&(e.range=[this.range[0],this.range[1]]),_t.loc&&(e.loc={start:{line:this.loc.start.line,column:this.loc.start.column},end:{line:this.loc.end.line,column:this.loc.end.column}})},e}function Xe(){var e,t;return d(),e=Qe(),A("("),t=ce(),A(")"),e.end(),e.applyGroup(t),t}function Ze(){var e,t;for(d(),e=Qe(),t=I("new")?G():V();L(".")||L("[");)L("[")?(t={type:lt.MemberExpression,computed:!0,object:t,property:q()},e.end(),e.apply(t)):(t={type:lt.MemberExpression,computed:!1,object:t,property:z()},e.end(),e.apply(t));return t}function Ye(){var e,t;for(d(),e=Qe(),t=I("new")?G():V();L(".")||L("[")||L("(");)L("(")?(t={type:lt.CallExpression,callee:t,arguments:H()},e.end(),e.apply(t)):L("[")?(t={type:lt.MemberExpression,computed:!0,object:t,property:q()},e.end(),e.apply(t)):(t={type:lt.MemberExpression,computed:!1,object:t,property:z()},e.end(),e.apply(t));return t}function et(e){var t,n,r;t="[object Array]"===Object.prototype.toString.apply(e)?[]:{};for(n in e)e.hasOwnProperty(n)&&"groupRange"!==n&&"groupLoc"!==n&&(r=e[n],null===r||"object"!=typeof r||r instanceof RegExp?t[n]=r:t[n]=et(r));return t}function tt(e,t){return function(n){function r(e){return e.type===lt.LogicalExpression||e.type===lt.BinaryExpression}function i(n){var a,o;r(n.left)&&i(n.left),r(n.right)&&i(n.right),e&&(n.left.groupRange||n.right.groupRange?(a=n.left.groupRange?n.left.groupRange[0]:n.left.range[0],o=n.right.groupRange?n.right.groupRange[1]:n.right.range[1],n.range=[a,o]):"undefined"==typeof n.range&&(a=n.left.range[0],o=n.right.range[1],n.range=[a,o])),t&&(n.left.groupLoc||n.right.groupLoc?(a=n.left.groupLoc?n.left.groupLoc.start:n.left.loc.start,o=n.right.groupLoc?n.right.groupLoc.end:n.right.loc.end,n.loc={start:a,end:o}):"undefined"==typeof n.loc&&(n.loc={start:n.left.loc.start,end:n.right.loc.end}))}return function(){var a,o;return d(),a=Qe(),o=n.apply(null,arguments),a.end(),e&&"undefined"==typeof o.range&&a.apply(o),t&&"undefined"==typeof o.loc&&a.apply(o),r(o)&&i(o),o}}}function nt(){var e;_t.comments&&(_t.skipComment=d,d=He),_t.raw&&(_t.createLiteral=Je,Je=Ke),(_t.range||_t.loc)&&(_t.parseGroupExpression=M,_t.parseLeftHandSideExpression=K,_t.parseLeftHandSideExpressionAllowCall=J,M=Xe,K=Ze,J=Ye,e=tt(_t.range,_t.loc),_t.parseAdditiveExpression=Y,_t.parseAssignmentExpression=ue,_t.parseBitwiseANDExpression=re,_t.parseBitwiseORExpression=ae,_t.parseBitwiseXORExpression=ie,_t.parseBlock=he,_t.parseFunctionSourceElements=Fe,_t.parseCatchClause=Ie,_t.parseComputedMember=q,_t.parseConditionalExpression=le,_t.parseConstLetDeclaration=ye,_t.parseEqualityExpression=ne,_t.parseExpression=ce,_t.parseForVariableDeclaration=ke,_t.parseFunctionDeclaration=De,_t.parseFunctionExpression=Re,_t.parseLogicalANDExpression=oe,_t.parseLogicalORExpression=se,_t.parseMultiplicativeExpression=Z,_t.parseNewExpression=G,_t.parseNonComputedProperty=W,_t.parseObjectProperty=B,_t.parseObjectPropertyKey=R,_t.parsePostfixExpression=Q,_t.parsePrimaryExpression=V,_t.parseProgram=Me,_t.parsePropertyFunction=D,_t.parseRelationalExpression=te,_t.parseStatement=Te,_t.parseShiftExpression=ee,_t.parseSwitchCase=Ae,_t.parseUnaryExpression=X,_t.parseVariableDeclaration=de,_t.parseVariableIdentifier=fe,Y=e(_t.parseAdditiveExpression),ue=e(_t.parseAssignmentExpression),re=e(_t.parseBitwiseANDExpression),ae=e(_t.parseBitwiseORExpression),ie=e(_t.parseBitwiseXORExpression),he=e(_t.parseBlock),Fe=e(_t.parseFunctionSourceElements),Ie=e(_t.parseCatchClause),q=e(_t.parseComputedMember),le=e(_t.parseConditionalExpression),ye=e(_t.parseConstLetDeclaration),ne=e(_t.parseEqualityExpression),ce=e(_t.parseExpression),ke=e(_t.parseForVariableDeclaration),De=e(_t.parseFunctionDeclaration),Re=e(_t.parseFunctionExpression),K=e(K),oe=e(_t.parseLogicalANDExpression),se=e(_t.parseLogicalORExpression),Z=e(_t.parseMultiplicativeExpression),G=e(_t.parseNewExpression),W=e(_t.parseNonComputedProperty),B=e(_t.parseObjectProperty),R=e(_t.parseObjectPropertyKey),Q=e(_t.parsePostfixExpression),V=e(_t.parsePrimaryExpression),Me=e(_t.parseProgram),D=e(_t.parsePropertyFunction),te=e(_t.parseRelationalExpression),Te=e(_t.parseStatement),ee=e(_t.parseShiftExpression),Ae=e(_t.parseSwitchCase),X=e(_t.parseUnaryExpression),de=e(_t.parseVariableDeclaration),fe=e(_t.parseVariableIdentifier)),"undefined"!=typeof _t.tokens&&(_t.advance=w,_t.scanRegExp=_,w=ze,_=qe)}function rt(){"function"==typeof _t.skipComment&&(d=_t.skipComment),_t.raw&&(Je=_t.createLiteral),(_t.range||_t.loc)&&(Y=_t.parseAdditiveExpression,ue=_t.parseAssignmentExpression,re=_t.parseBitwiseANDExpression,ae=_t.parseBitwiseORExpression,ie=_t.parseBitwiseXORExpression,he=_t.parseBlock,Fe=_t.parseFunctionSourceElements,Ie=_t.parseCatchClause,q=_t.parseComputedMember,le=_t.parseConditionalExpression,ye=_t.parseConstLetDeclaration,ne=_t.parseEqualityExpression,ce=_t.parseExpression,ke=_t.parseForVariableDeclaration,De=_t.parseFunctionDeclaration,Re=_t.parseFunctionExpression,M=_t.parseGroupExpression,K=_t.parseLeftHandSideExpression,J=_t.parseLeftHandSideExpressionAllowCall,oe=_t.parseLogicalANDExpression,se=_t.parseLogicalORExpression,Z=_t.parseMultiplicativeExpression,G=_t.parseNewExpression,W=_t.parseNonComputedProperty,B=_t.parseObjectProperty,R=_t.parseObjectPropertyKey,V=_t.parsePrimaryExpression,Q=_t.parsePostfixExpression,Me=_t.parseProgram,D=_t.parsePropertyFunction,te=_t.parseRelationalExpression,Te=_t.parseStatement,ee=_t.parseShiftExpression,Ae=_t.parseSwitchCase,X=_t.parseUnaryExpression,de=_t.parseVariableDeclaration,fe=_t.parseVariableIdentifier),"function"==typeof _t.scanRegExp&&(w=_t.advance,_=_t.scanRegExp)}function it(e){var t,n=e.length,r=[];for(t=0;n>t;++t)r[t]=e.charAt(t);return r}function at(e,t){var n,r;r=String,"string"==typeof e||e instanceof String||(e=r(e)),ht=e,dt=0,vt=ht.length>0?1:0,mt=0,yt=ht.length,gt=null,bt={allowIn:!0,labelSet:{},inFunctionBody:!1,inIteration:!1,inSwitch:!1},_t={},"undefined"!=typeof t&&(_t.range="boolean"==typeof t.range&&t.range,_t.loc="boolean"==typeof t.loc&&t.loc,_t.raw="boolean"==typeof t.raw&&t.raw,"boolean"==typeof t.tokens&&t.tokens&&(_t.tokens=[]),"boolean"==typeof t.comment&&t.comment&&(_t.comments=[]),"boolean"==typeof t.tolerant&&t.tolerant&&(_t.errors=[])),yt>0&&"undefined"==typeof ht[0]&&(e instanceof String&&(ht=e.valueOf()),"undefined"==typeof ht[0]&&(ht=it(e))),nt();try{n=Me(),"undefined"!=typeof _t.comments&&(We(),n.comments=_t.comments),"undefined"!=typeof _t.tokens&&(Ge(),n.tokens=_t.tokens),"undefined"!=typeof _t.errors&&(n.errors=_t.errors),(_t.range||_t.loc)&&(n.body=et(n.body))}catch(i){throw i}finally{rt(),_t={}}return n}var ot,st,lt,ut,ct,pt,ht,ft,dt,vt,mt,yt,gt,bt,_t;ot={BooleanLiteral:1,EOF:2,Identifier:3,Keyword:4,NullLiteral:5,NumericLiteral:6,Punctuator:7,StringLiteral:8},st={},st[ot.BooleanLiteral]="Boolean",st[ot.EOF]="<end>",st[ot.Identifier]="Identifier",st[ot.Keyword]="Keyword",st[ot.NullLiteral]="Null",st[ot.NumericLiteral]="Numeric",st[ot.Punctuator]="Punctuator",st[ot.StringLiteral]="String",lt={AssignmentExpression:"AssignmentExpression",ArrayExpression:"ArrayExpression",BlockStatement:"BlockStatement",BinaryExpression:"BinaryExpression",BreakStatement:"BreakStatement",CallExpression:"CallExpression",CatchClause:"CatchClause",ConditionalExpression:"ConditionalExpression",ContinueStatement:"ContinueStatement",DoWhileStatement:"DoWhileStatement",DebuggerStatement:"DebuggerStatement",EmptyStatement:"EmptyStatement",ExpressionStatement:"ExpressionStatement",ForStatement:"ForStatement",ForInStatement:"ForInStatement",FunctionDeclaration:"FunctionDeclaration",FunctionExpression:"FunctionExpression",Identifier:"Identifier",IfStatement:"IfStatement",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",NewExpression:"NewExpression",ObjectExpression:"ObjectExpression",Program:"Program",Property:"Property",ReturnStatement:"ReturnStatement",SequenceExpression:"SequenceExpression",SwitchStatement:"SwitchStatement",SwitchCase:"SwitchCase",ThisExpression:"ThisExpression",ThrowStatement:"ThrowStatement",TryStatement:"TryStatement",UnaryExpression:"UnaryExpression",UpdateExpression:"UpdateExpression",VariableDeclaration:"VariableDeclaration",VariableDeclarator:"VariableDeclarator",WhileStatement:"WhileStatement",WithStatement:"WithStatement"},ut={Data:1,Get:2,Set:4},ct={UnexpectedToken:"Unexpected token %0",UnexpectedNumber:"Unexpected number",UnexpectedString:"Unexpected string",UnexpectedIdentifier:"Unexpected identifier",UnexpectedReserved:"Unexpected reserved word",UnexpectedEOS:"Unexpected end of input",NewlineAfterThrow:"Illegal newline after throw",InvalidRegExp:"Invalid regular expression",UnterminatedRegExp:"Invalid regular expression: missing /",InvalidLHSInAssignment:"Invalid left-hand side in assignment",InvalidLHSInForIn:"Invalid left-hand side in for-in",MultipleDefaultsInSwitch:"More than one default clause in switch statement",NoCatchOrFinally:"Missing catch or finally after try",UnknownLabel:"Undefined label '%0'",Redeclaration:"%0 '%1' has already been declared",IllegalContinue:"Illegal continue statement",IllegalBreak:"Illegal break statement",IllegalReturn:"Illegal return statement",StrictModeWith:"Strict mode code may not include a with statement",StrictCatchVariable:"Catch variable may not be eval or arguments in strict mode",StrictVarName:"Variable name may not be eval or arguments in strict mode",StrictParamName:"Parameter name eval or arguments is not allowed in strict mode",StrictParamDupe:"Strict mode function may not have duplicate parameter names",StrictFunctionName:"Function name may not be eval or arguments in strict mode",StrictOctalLiteral:"Octal literals are not allowed in strict mode.",StrictDelete:"Delete of an unqualified identifier in strict mode.",StrictDuplicateProperty:"Duplicate data property in object literal not allowed in strict mode",AccessorDataProperty:"Object literal may not have data and accessor property with the same name",AccessorGetSet:"Object literal may not have multiple get/set accessors with the same name",StrictLHSAssignment:"Assignment to eval or arguments is not allowed in strict mode",StrictLHSPostfix:"Postfix increment/decrement may not have eval or arguments operand in strict mode",StrictLHSPrefix:"Prefix increment/decrement may not have eval or arguments operand in strict mode",StrictReservedWord:"Use of future reserved word in strict mode"},pt={NonAsciiIdentifierStart:new RegExp("[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]"),NonAsciiIdentifierPart:new RegExp("[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]")},"undefined"==typeof"esprima"[0]&&(n=function(e,t){return ht.slice(e,t).join("")}),e.version="1.0.4",e.parse=at,e.Syntax=function(){var e,t={};"function"==typeof Object.create&&(t=Object.create(null));for(e in lt)lt.hasOwnProperty(e)&&(t[e]=lt[e]);return"function"==typeof Object.freeze&&Object.freeze(t),t}()}),e.exports}({exports:{}}),qr=function(e,t){function n(e,t){var n=i(e),r=Object.create(t||{});return f(a(n,r))}function r(e){var t=Object.create(e||{});return function(){var e=Array.prototype.slice.call(arguments),n=e.slice(-1)[0];e=e.slice(0,-1),"string"==typeof n&&(n=m("function a(){"+n+"}").body[0].body);var r=i(n);return h(r,e,t)}}function i(e){var t="string"==typeof e?m(e):e;return y(t)}function a(e,t){function n(e){for(var t=void 0,n=0;n<e.length;n++){var r=e[n];if("EmptyStatement"!==r.type&&(t=i(r), -t instanceof v))return t}return t}function i(e){if(e)switch(e.type){case"Program":return n(e.body);case"BlockStatement":u();var r=n(e.body);return c(),r;case"FunctionDeclaration":var s=e.params.map(d),p=h(e.body,s,w);return t[e.id.name]=p;case"FunctionExpression":var s=e.params.map(d);return h(e.body,s,w);case"ReturnStatement":var p=i(e.argument);return new v("return",p);case"BreakStatement":return new v("break");case"ContinueStatement":return new v("continue");case"ExpressionStatement":return i(e.expression);case"AssignmentExpression":return m(w,e.left,e.right,e.operator);case"UpdateExpression":return m(w,e.argument,null,e.operator);case"VariableDeclaration":e.declarations.forEach(function(n){var r="let"===e.kind?w:t;n.init?r[n.id.name]=i(n.init):r[n.id.name]=void 0});break;case"SwitchStatement":var y=null,b=!1,p=i(e.discriminant),r=void 0;u();for(var k=0;null==r;)if(k<e.cases.length){if(e.cases[k].test?b=b||i(e.cases[k].test)===p:null==y&&(y=k),b){var S=n(e.cases[k].consequent);if(S instanceof v){if("break"==S.type)break;r=S}}k+=1}else{if(b||null==y)break;k=y,b=!0}return c(),r;case"IfStatement":if(i(e.test))return i(e.consequent);if(e.alternate)return i(e.alternate);case"ForStatement":var C=g(_),r=void 0;for(u(),i(e.init);i(e.test);i(e.update)){var S=i(e.body);if(S instanceof v){if("continue"==S.type)continue;if("break"==S.type)break;r=S;break}C.check()}return c(),r;case"ForInStatement":var C=g(_),r=void 0,p=i(e.right),E=e.left,O=t;u(),"VariableDeclaration"==E.type&&(i(E),E=E.declarations[0].id,"let"===E.kind&&(O=w));for(var $ in p){m(O,E,{type:"Literal",value:$});var S=i(e.body);if(S instanceof v){if("continue"==S.type)continue;if("break"==S.type)break;r=S;break}C.check()}return c(),r;case"WhileStatement":for(var C=g(_);i(e.test);)i(e.body),C.check();break;case"TryStatement":try{i(e.block)}catch(A){u();var N=e.handlers[0];N&&(w[N.param.name]=A,i(N.body)),c()}finally{e.finalizer&&i(e.finalizer)}break;case"Literal":return e.value;case"UnaryExpression":var L=i(e.argument);switch(e.operator){case"+":return+L;case"-":return-L;case"~":return~L;case"!":return!L;case"typeof":return typeof L;default:return o(e)}case"ArrayExpression":for(var I=w.Array(),k=0;k<e.elements.length;k++)I.push(i(e.elements[k]));return I;case"ObjectExpression":for(var I=w.Object(),k=0;k<e.properties.length;k++){var P=e.properties[k],p=null===P.value?P.value:i(P.value);I[P.key.value||P.key.name]=p}return I;case"NewExpression":var j=e.arguments.map(function(e){return i(e)}),O=i(e.callee);return x.applyNew(O,j);case"BinaryExpression":var T=i(e.left),S=i(e.right);switch(e.operator){case"==":return T===S;case"===":return T===S;case"!=":return T!=S;case"!==":return T!==S;case"+":return T+S;case"-":return T-S;case"*":return T*S;case"/":return T/S;case"%":return T%S;case"<":return S>T;case"<=":return S>=T;case">":return T>S;case">=":return T>=S;case"|":return T|S;case"&":return T&S;case"^":return T^S;case"instanceof":return T instanceof S;default:return o(e)}case"LogicalExpression":switch(e.operator){case"&&":return i(e.left)&&i(e.right);case"||":return i(e.left)||i(e.right);default:return o(e)}case"ThisExpression":return w["this"];case"Identifier":if("undefined"===e.name)return;if(l(w,e.name,x))return f(w[e.name]);throw new ReferenceError(e.name+" is not defined");case"CallExpression":var j=e.arguments.map(function(e){return i(e)}),F=null,O=i(e.callee);return"MemberExpression"===e.callee.type&&(F=i(e.callee.object)),O.apply(F,j);case"MemberExpression":var I=i(e.object);if(e.computed)var P=i(e.property);else var P=e.property.name;return I=x.getPropertyObject(I,P),a(I[P]);case"ConditionalExpression":var L=i(e.test);return i(L?e.consequent:e.alternate);case"EmptyStatement":return;default:return o(e)}}function a(e){return e===Gr&&(e=y),f(e)}function u(){w=Object.create(w)}function c(){w=Object.getPrototypeOf(w)}function m(e,t,n,r){var a=null;if("Identifier"===t.type?(a=t.name,e=s(e,a,x)):"MemberExpression"===t.type&&(a=t.computed?i(t.property):t.property.name,e=i(t.object)),p(e,a,x))switch(r){case void 0:return e[a]=i(n);case"=":return e[a]=i(n);case"+=":return e[a]+=i(n);case"-=":return e[a]-=i(n);case"++":return e[a]++;case"--":return e[a]--}}var y=r(t),x=b(t),w=t;return i(e)}function o(e){console.error(e);var t=new Error("Unsupported expression: "+e.type);throw t.node=e,t}function s(e,t,n){var r=n.getPrototypeOf(e);return!r||u(e,t)?e:s(r,t,n)}function l(e,t,n){var r=n.getPrototypeOf(e),i=u(e,t);return void 0!==e[t]?!0:!r||i?i:l(r,t,n)}function u(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function c(e,t){return Object.prototype.propertyIsEnumerable.call(e,t)}function p(e,t,n){return"__proto__"===t||n.isPrimitive(e)?!1:null!=e?u(e,t)?!!c(e,t):p(n.getPrototypeOf(e),t,n):!0}function h(e,n,r){return function(){var i=Object.create(r);this==t?i["this"]=null:i["this"]=this;var o=Array.prototype.slice.call(arguments);i.arguments=arguments,o.forEach(function(e,t){var r=n[t];r&&(i[r]=e)});var s=a(e,i);return s instanceof v?s.value:void 0}}function f(e){return e instanceof v?e.value:e}function d(e){return e.name}function v(e,t){this.type=e,this.value=t}var m=(e.exports,zr.parse),y=Wr,g=Hr,b=Vr;e.exports=n,e.exports.FunctionFactory=r,e.exports.Function=r();var _=1e6;return e.exports}({exports:{}},Mr),Gr=qr.Function,Jr=new k(1e3),Kr=0,Qr=1,Xr=2,Zr=3,Yr=0,ei=1,ti=2,ni=3,ri=4,ii=5,ai=6,oi=7,si=8,li=[];li[Yr]={ws:[Yr],ident:[ni,Kr],"[":[ri],eof:[oi]},li[ei]={ws:[ei],".":[ti],"[":[ri],eof:[oi]},li[ti]={ws:[ti],ident:[ni,Kr]},li[ni]={ident:[ni,Kr],0:[ni,Kr],number:[ni,Kr],ws:[ei,Qr],".":[ti,Qr],"[":[ri,Qr],eof:[oi,Qr]},li[ri]={"'":[ii,Kr],'"':[ai,Kr],"[":[ri,Xr],"]":[ei,Zr],eof:si,"else":[ri,Kr]},li[ii]={"'":[ri,Kr],eof:si,"else":[ii,Kr]},li[ai]={'"':[ri,Kr],eof:si,"else":[ai,Kr]};var ui=Object.freeze({parsePath:Ae,getPath:Ne,setPath:Le}),ci=new k(1e3),pi="Math,Date,this,true,false,null,undefined,Infinity,NaN,isNaN,isFinite,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,parseInt,parseFloat",hi=new RegExp("^("+pi.replace(/,/g,"\\b|")+"\\b)"),fi="break,case,class,catch,const,continue,debugger,default,delete,do,else,export,extends,finally,for,function,if,import,in,instanceof,let,return,super,switch,throw,try,var,while,with,yield,enum,await,implements,package,protected,static,interface,private,public",di=new RegExp("^("+fi.replace(/,/g,"\\b|")+"\\b)"),vi=/\s/g,mi=/\n/g,yi=/[\{,]\s*[\w\$_]+\s*:|('(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`)|new |typeof |void /g,gi=/"(\d+)"/g,bi=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/,_i=/[^\w$\.](?:[A-Za-z_$][\w$]*)/g,xi=/^(?:true|false|null|undefined|Infinity|NaN)$/,wi=[],ki=Object.freeze({parseExpression:Be,isSimplePath:Ue}),Si=[],Ci=[],Ei={},Oi={},$i=!1,Ai=0;ze.prototype.get=function(){this.beforeGet();var e,t=this.scope||this.vm;try{e=this.getter.call(t,t)}catch(n){}return this.deep&&qe(e),this.preProcess&&(e=this.preProcess(e)),this.filters&&(e=t._applyFilters(e,null,this.filters,!1)),this.postProcess&&(e=this.postProcess(e)),this.afterGet(),e},ze.prototype.set=function(e){var t=this.scope||this.vm;this.filters&&(e=t._applyFilters(e,this.value,this.filters,!0));try{this.setter.call(t,t,e)}catch(n){}var r=t.$forContext;if(r&&r.alias===this.expression){if(r.filters)return;r._withLock(function(){t.$key?r.rawValue[t.$key]=e:r.rawValue.$set(t.$index,e)})}},ze.prototype.beforeGet=function(){ge.target=this},ze.prototype.addDep=function(e){var t=e.id;this.newDepIds.has(t)||(this.newDepIds.add(t),this.newDeps.push(e),this.depIds.has(t)||e.addSub(this))},ze.prototype.afterGet=function(){ge.target=null;for(var e=this.deps.length;e--;){var t=this.deps[e];this.newDepIds.has(t.id)||t.removeSub(this)}var n=this.depIds;this.depIds=this.newDepIds,this.newDepIds=n,this.newDepIds.clear(),n=this.deps,this.deps=this.newDeps,this.newDeps=n,this.newDeps.length=0},ze.prototype.update=function(e){this.lazy?this.dirty=!0:this.sync||!Er.async?this.run():(this.shallow=this.queued?e?this.shallow:!1:!!e,this.queued=!0,We(this))},ze.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||(m(e)||this.deep)&&!this.shallow){var t=this.value;this.value=e;this.prevError;this.cb.call(this.vm,e,t)}this.queued=this.shallow=!1}},ze.prototype.evaluate=function(){var e=ge.target;this.value=this.get(),this.dirty=!1,ge.target=e},ze.prototype.depend=function(){for(var e=this.deps.length;e--;)this.deps[e].depend()},ze.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||this.vm._vForRemoving||this.vm._watchers.$remove(this);for(var e=this.deps.length;e--;)this.deps[e].removeSub(this);this.active=!1,this.vm=this.cb=this.value=null}};var Ni=new er,Li={bind:function(){this.attr=3===this.el.nodeType?"data":"textContent"},update:function(e){this.el[this.attr]=a(e)}},Ii=new k(1e3),Pi=new k(1e3),ji={efault:[0,"",""],legend:[1,"<fieldset>","</fieldset>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]};ji.td=ji.th=[3,"<table><tbody><tr>","</tr></tbody></table>"],ji.option=ji.optgroup=[1,'<select multiple="multiple">',"</select>"],ji.thead=ji.tbody=ji.colgroup=ji.caption=ji.tfoot=[1,"<table>","</table>"],ji.g=ji.defs=ji.symbol=ji.use=ji.image=ji.text=ji.circle=ji.ellipse=ji.line=ji.path=ji.polygon=ji.polyline=ji.rect=[1,'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"version="1.1">',"</svg>"];var Ti=/<([\w:-]+)/,Fi=/&#?\w+?;/,Di=/<!--/,Ri=function(){if(Dn){var e=document.createElement("div");return e.innerHTML="<template>1</template>",!e.cloneNode(!0).firstChild.innerHTML}return!1}(),Bi=function(){if(Dn){var e=document.createElement("textarea");return e.placeholder="t","t"===e.cloneNode(!0).value}return!1}(),Ui=Object.freeze({cloneNode:Qe,parseTemplate:Xe}),Mi={bind:function(){8===this.el.nodeType&&(this.nodes=[],this.anchor=re("v-html"),q(this.el,this.anchor))},update:function(e){e=a(e),this.nodes?this.swap(e):this.el.innerHTML=e},swap:function(e){for(var t=this.nodes.length;t--;)W(this.nodes[t]);var n=Xe(e,!0,!0);this.nodes=d(n.childNodes),V(n,this.anchor)}};Ze.prototype.callHook=function(e){var t,n;for(t=0,n=this.childFrags.length;n>t;t++)this.childFrags[t].callHook(e);for(t=0,n=this.children.length;n>t;t++)e(this.children[t])},Ze.prototype.beforeRemove=function(){var e,t;for(e=0,t=this.childFrags.length;t>e;e++)this.childFrags[e].beforeRemove(!1);for(e=0,t=this.children.length;t>e;e++)this.children[e].$destroy(!1,!0);var n=this.unlink.dirs;for(e=0,t=n.length;t>e;e++)n[e]._watcher&&n[e]._watcher.teardown()},Ze.prototype.destroy=function(){this.parentFrag&&this.parentFrag.childFrags.$remove(this),this.node.__v_frag=null,this.unlink()};var Vi=new k(5e3);at.prototype.create=function(e,t,n){var r=Qe(this.template);return new Ze(this.linker,this.vm,r,e,t,n)};var Hi=700,Wi=800,zi=850,qi=1100,Gi=1500,Ji=1500,Ki=1750,Qi=2100,Xi=2200,Zi=2300,Yi=0,ea={priority:Xi,terminal:!0,params:["track-by","stagger","enter-stagger","leave-stagger"],bind:function(){var e=this.expression.match(/(.*) (?:in|of) (.*)/);if(e){var t=e[1].match(/\((.*),(.*)\)/);t?(this.iterator=t[1].trim(),this.alias=t[2].trim()):this.alias=e[1].trim(),this.expression=e[2]}if(this.alias){this.id="__v-for__"+ ++Yi;var n=this.el.tagName;this.isOption=("OPTION"===n||"OPTGROUP"===n)&&"SELECT"===this.el.parentNode.tagName,this.start=re("v-for-start"),this.end=re("v-for-end"),q(this.el,this.end),V(this.start,this.end),this.cache=Object.create(null),this.factory=new at(this.vm,this.el)}},update:function(e){this.diff(e),this.updateRef(),this.updateModel()},diff:function(e){var t,r,i,a,o,s,l=e[0],u=this.fromObject=m(l)&&n(l,"$key")&&n(l,"$value"),c=this.params.trackBy,p=this.frags,h=this.frags=new Array(e.length),f=this.alias,d=this.iterator,v=this.start,y=this.end,g=R(v),b=!p;for(t=0,r=e.length;r>t;t++)l=e[t],a=u?l.$key:null,o=u?l.$value:l,s=!m(o),i=!b&&this.getCachedFrag(o,t,a),i?(i.reused=!0,i.scope.$index=t,a&&(i.scope.$key=a),d&&(i.scope[d]=null!==a?a:t),(c||u||s)&&be(function(){i.scope[f]=o})):(i=this.create(o,f,t,a),i.fresh=!b),h[t]=i,b&&i.before(y);if(!b){var _=0,x=p.length-h.length;for(this.vm._vForRemoving=!0,t=0,r=p.length;r>t;t++)i=p[t],i.reused||(this.deleteCachedFrag(i),this.remove(i,_++,x,g));this.vm._vForRemoving=!1,_&&(this.vm._watchers=this.vm._watchers.filter(function(e){return e.active}));var w,k,S,C=0;for(t=0,r=h.length;r>t;t++)i=h[t],w=h[t-1],k=w?w.staggerCb?w.staggerAnchor:w.end||w.node:v,i.reused&&!i.staggerCb?(S=ot(i,v,this.id),S===w||S&&ot(S,v,this.id)===w||this.move(i,k)):this.insert(i,C++,k,g),i.reused=i.fresh=!1}},create:function(e,t,n,r){var i=this._host,a=this._scope||this.vm,o=Object.create(a);o.$refs=Object.create(a.$refs),o.$els=Object.create(a.$els),o.$parent=a,o.$forContext=this,be(function(){Se(o,t,e)}),Se(o,"$index",n),r?Se(o,"$key",r):o.$key&&g(o,"$key",null),this.iterator&&Se(o,this.iterator,null!==r?r:n);var s=this.factory.create(i,o,this._frag);return s.forId=this.id,this.cacheFrag(e,s,n,r),s},updateRef:function(){var e=this.descriptor.ref;if(e){var t,n=(this._scope||this.vm).$refs;this.fromObject?(t={},this.frags.forEach(function(e){t[e.scope.$key]=st(e)})):t=this.frags.map(st),n[e]=t}},updateModel:function(){if(this.isOption){var e=this.start.parentNode,t=e&&e.__v_model;t&&t.forceUpdate()}},insert:function(e,t,n,r){e.staggerCb&&(e.staggerCb.cancel(),e.staggerCb=null);var i=this.getStagger(e,t,null,"enter");if(r&&i){var a=e.staggerAnchor;a||(a=e.staggerAnchor=re("stagger-anchor"),a.__v_frag=e),H(a,n);var o=e.staggerCb=x(function(){e.staggerCb=null,e.before(a),W(a)});setTimeout(o,i)}else{var s=n.nextSibling;s||(H(this.end,n),s=this.end),e.before(s)}},remove:function(e,t,n,r){if(e.staggerCb)return e.staggerCb.cancel(),void(e.staggerCb=null);var i=this.getStagger(e,t,n,"leave");if(r&&i){var a=e.staggerCb=x(function(){e.staggerCb=null,e.remove()});setTimeout(a,i)}else e.remove()},move:function(e,t){t.nextSibling||this.end.parentNode.appendChild(this.end),e.before(t.nextSibling,!1)},cacheFrag:function(e,t,r,i){var a,o=this.params.trackBy,s=this.cache,l=!m(e);i||o||l?(a=ut(r,i,e,o),s[a]||(s[a]=t)):(a=this.id,n(e,a)?null===e[a]&&(e[a]=t):Object.isExtensible(e)&&g(e,a,t)),t.raw=e},getCachedFrag:function(e,t,n){var r,i=this.params.trackBy,a=!m(e);if(n||i||a){var o=ut(t,n,e,i);r=this.cache[o]}else r=e[this.id];return r&&(r.reused||r.fresh),r},deleteCachedFrag:function(e){var t=e.raw,r=this.params.trackBy,i=e.scope,a=i.$index,o=n(i,"$key")&&i.$key,s=!m(t);if(r||o||s){var l=ut(a,o,t,r);this.cache[l]=null}else t[this.id]=null,e.raw=null},getStagger:function(e,t,n,r){r+="Stagger";var i=e.node.__v_trans,a=i&&i.hooks,o=a&&(a[r]||a.stagger);return o?o.call(e,t,n):t*parseInt(this.params[r]||this.params.stagger,10)},_preProcess:function(e){return this.rawValue=e,e},_postProcess:function(e){if(Tn(e))return e;if(y(e)){for(var t,n=Object.keys(e),r=n.length,i=new Array(r);r--;)t=n[r],i[r]={$key:t,$value:e[t]};return i}return"number"!=typeof e||isNaN(e)||(e=lt(e)),e||[]},unbind:function(){if(this.descriptor.ref&&((this._scope||this.vm).$refs[this.descriptor.ref]=null),this.frags)for(var e,t=this.frags.length;t--;)e=this.frags[t],this.deleteCachedFrag(e),e.destroy()}},ta={priority:Qi,terminal:!0,bind:function(){var e=this.el;if(e.__vue__)this.invalid=!0;else{var t=e.nextElementSibling;t&&null!==B(t,"v-else")&&(W(t),this.elseEl=t),this.anchor=re("v-if"),q(e,this.anchor)}},update:function(e){this.invalid||(e?this.frag||this.insert():this.remove())},insert:function(){this.elseFrag&&(this.elseFrag.remove(),this.elseFrag=null),this.factory||(this.factory=new at(this.vm,this.el)),this.frag=this.factory.create(this._host,this._scope,this._frag),this.frag.before(this.anchor)},remove:function(){this.frag&&(this.frag.remove(),this.frag=null),this.elseEl&&!this.elseFrag&&(this.elseFactory||(this.elseFactory=new at(this.elseEl._context||this.vm,this.elseEl)),this.elseFrag=this.elseFactory.create(this._host,this._scope,this._frag),this.elseFrag.before(this.anchor))},unbind:function(){this.frag&&this.frag.destroy(),this.elseFrag&&this.elseFrag.destroy()}},na={bind:function(){var e=this.el.nextElementSibling;e&&null!==B(e,"v-else")&&(this.elseEl=e)},update:function(e){this.apply(this.el,e),this.elseEl&&this.apply(this.elseEl,!e)},apply:function(e,t){function n(){e.style.display=t?"":"none"}R(e)?F(e,t?1:-1,n,this.vm):n()}},ra={bind:function(){var e=this,t=this.el,n="range"===t.type,r=this.params.lazy,i=this.params.number,a=this.params.debounce,s=!1;if(Vn||n||(this.on("compositionstart",function(){s=!0}),this.on("compositionend",function(){s=!1,r||e.listener()})),this.focused=!1,n||r||(this.on("focus",function(){e.focused=!0}),this.on("blur",function(){e.focused=!1,e._frag&&!e._frag.inserted||e.rawListener()})),this.listener=this.rawListener=function(){if(!s&&e._bound){var r=i||n?o(t.value):t.value;e.set(r),Yn(function(){e._bound&&!e.focused&&e.update(e._watcher.value)})}},a&&(this.listener=b(this.listener,a)),this.hasjQuery="function"==typeof jQuery,this.hasjQuery){var l=jQuery.fn.on?"on":"bind";jQuery(t)[l]("change",this.rawListener),r||jQuery(t)[l]("input",this.listener)}else this.on("change",this.rawListener),r||this.on("input",this.listener);!r&&Mn&&(this.on("cut",function(){Yn(e.listener)}),this.on("keyup",function(t){46!==t.keyCode&&8!==t.keyCode||e.listener()})),(t.hasAttribute("value")||"TEXTAREA"===t.tagName&&t.value.trim())&&(this.afterBind=this.listener)},update:function(e){e=a(e),e!==this.el.value&&(this.el.value=e)},unbind:function(){var e=this.el;if(this.hasjQuery){var t=jQuery.fn.off?"off":"unbind";jQuery(e)[t]("change",this.listener),jQuery(e)[t]("input",this.listener)}}},ia={bind:function(){var e=this,t=this.el;this.getValue=function(){if(t.hasOwnProperty("_value"))return t._value;var n=t.value;return e.params.number&&(n=o(n)),n},this.listener=function(){e.set(e.getValue())},this.on("change",this.listener),t.hasAttribute("checked")&&(this.afterBind=this.listener)},update:function(e){this.el.checked=w(e,this.getValue())}},aa={bind:function(){var e=this,t=this,n=this.el;this.forceUpdate=function(){t._watcher&&t.update(t._watcher.get())};var r=this.multiple=n.hasAttribute("multiple");this.listener=function(){var e=ct(n,r);e=t.params.number?Tn(e)?e.map(o):o(e):e,t.set(e)},this.on("change",this.listener);var i=ct(n,r,!0);(r&&i.length||!r&&null!==i)&&(this.afterBind=this.listener),this.vm.$on("hook:attached",function(){Yn(e.forceUpdate)}),R(n)||Yn(this.forceUpdate)},update:function(e){var t=this.el;t.selectedIndex=-1;for(var n,r,i=this.multiple&&Tn(e),a=t.options,o=a.length;o--;)n=a[o],r=n.hasOwnProperty("_value")?n._value:n.value,n.selected=i?pt(e,r)>-1:w(e,r)},unbind:function(){this.vm.$off("hook:attached",this.forceUpdate)}},oa={bind:function(){function e(){var e=n.checked;return e&&n.hasOwnProperty("_trueValue")?n._trueValue:!e&&n.hasOwnProperty("_falseValue")?n._falseValue:e}var t=this,n=this.el;this.getValue=function(){return n.hasOwnProperty("_value")?n._value:t.params.number?o(n.value):n.value},this.listener=function(){var r=t._watcher.value;if(Tn(r)){var i=t.getValue();n.checked?_(r,i)<0&&r.push(i):r.$remove(i)}else t.set(e())},this.on("change",this.listener),n.hasAttribute("checked")&&(this.afterBind=this.listener)},update:function(e){var t=this.el;Tn(e)?t.checked=_(e,this.getValue())>-1:t.hasOwnProperty("_trueValue")?t.checked=w(e,t._trueValue):t.checked=!!e}},sa={text:ra,radio:ia,select:aa,checkbox:oa},la={priority:Wi,twoWay:!0,handlers:sa,params:["lazy","number","debounce"],bind:function(){this.checkFilters(),this.hasRead&&!this.hasWrite;var e,t=this.el,n=t.tagName;if("INPUT"===n)e=sa[t.type]||sa.text;else if("SELECT"===n)e=sa.select;else{if("TEXTAREA"!==n)return;e=sa.text}t.__v_model=this,e.bind.call(this),this.update=e.update,this._unbind=e.unbind},checkFilters:function(){var e=this.filters;if(e)for(var t=e.length;t--;){var n=ye(this.vm.$options,"filters",e[t].name);("function"==typeof n||n.read)&&(this.hasRead=!0),n.write&&(this.hasWrite=!0)}},unbind:function(){this.el.__v_model=null,this._unbind&&this._unbind()}},ua={esc:27,tab:9,enter:13,space:32,"delete":[8,46],up:38,left:37,right:39,down:40},ca={priority:Hi,acceptStatement:!0,keyCodes:ua,bind:function(){if("IFRAME"===this.el.tagName&&"load"!==this.arg){var e=this;this.iframeBind=function(){G(e.el.contentWindow,e.arg,e.handler,e.modifiers.capture)},this.on("load",this.iframeBind)}},update:function(e){if(this.descriptor.raw||(e=function(){}),"function"==typeof e){this.modifiers.stop&&(e=ft(e)),this.modifiers.prevent&&(e=dt(e)),this.modifiers.self&&(e=vt(e));var t=Object.keys(this.modifiers).filter(function(e){return"stop"!==e&&"prevent"!==e&&"self"!==e&&"capture"!==e});t.length&&(e=ht(e,t)),this.reset(),this.handler=e,this.iframeBind?this.iframeBind():G(this.el,this.arg,this.handler,this.modifiers.capture)}},reset:function(){var e=this.iframeBind?this.el.contentWindow:this.el;this.handler&&J(e,this.arg,this.handler)},unbind:function(){this.reset()}},pa=["-webkit-","-moz-","-ms-"],ha=["Webkit","Moz","ms"],fa=/!important;?$/,da=Object.create(null),va=null,ma={deep:!0,update:function(e){"string"==typeof e?this.el.style.cssText=e:Tn(e)?this.handleObject(e.reduce(v,{})):this.handleObject(e||{})},handleObject:function(e){var t,n,r=this.cache||(this.cache={});for(t in r)t in e||(this.handleSingle(t,null),delete r[t]);for(t in e)n=e[t],n!==r[t]&&(r[t]=n,this.handleSingle(t,n))},handleSingle:function(e,t){if(e=mt(e))if(null!=t&&(t+=""),t){var n=fa.test(t)?"important":"";n?(t=t.replace(fa,"").trim(),this.el.style.setProperty(e.kebab,t,n)):this.el.style[e.camel]=t}else this.el.style[e.camel]=""}},ya="http://www.w3.org/1999/xlink",ga=/^xlink:/,ba=/^v-|^:|^@|^(?:is|transition|transition-mode|debounce|track-by|stagger|enter-stagger|leave-stagger)$/,_a=/^(?:value|checked|selected|muted)$/,xa=/^(?:draggable|contenteditable|spellcheck)$/,wa={value:"_value","true-value":"_trueValue","false-value":"_falseValue"},ka={priority:zi,bind:function(){var e=this.arg,t=this.el.tagName;e||(this.deep=!0);var n=this.descriptor,r=n.interp;r&&(n.hasOneTime&&(this.expression=N(r,this._scope||this.vm)),(ba.test(e)||"name"===e&&("PARTIAL"===t||"SLOT"===t))&&(this.el.removeAttribute(e),this.invalid=!0))},update:function(e){if(!this.invalid){var t=this.arg;this.arg?this.handleSingle(t,e):this.handleObject(e||{})}},handleObject:ma.handleObject,handleSingle:function(e,t){var n=this.el,r=this.descriptor.interp;if(this.modifiers.camel&&(e=u(e)),!r&&_a.test(e)&&e in n){var i="value"===e&&null==t?"":t;n[e]!==i&&(n[e]=i)}var a=wa[e];if(!r&&a){n[a]=t;var o=n.__v_model;o&&o.listener()}return"value"===e&&"TEXTAREA"===n.tagName?void n.removeAttribute(e):void(xa.test(e)?n.setAttribute(e,t?"true":"false"):null!=t&&t!==!1?"class"===e?(n.__v_trans&&(t+=" "+n.__v_trans.id+"-transition"),Q(n,t)):ga.test(e)?n.setAttributeNS(ya,e,t===!0?"":t):n.setAttribute(e,t===!0?"":t):n.removeAttribute(e))}},Sa={priority:Gi,bind:function(){if(this.arg){var e=this.id=u(this.arg),t=(this._scope||this.vm).$els;n(t,e)?t[e]=this.el:Se(t,e,this.el)}},unbind:function(){var e=(this._scope||this.vm).$els;e[this.id]===this.el&&(e[this.id]=null)}},Ca={bind:function(){}},Ea={bind:function(){var e=this.el;this.vm.$once("pre-hook:compiled",function(){e.removeAttribute("v-cloak")})}},Oa={text:Li,html:Mi,"for":ea,"if":ta,show:na,model:la,on:ca,bind:ka,el:Sa,ref:Ca,cloak:Ea},$a={deep:!0,update:function(e){e?"string"==typeof e?this.setClass(e.trim().split(/\s+/)):this.setClass(gt(e)):this.cleanup()},setClass:function(e){this.cleanup(e);for(var t=0,n=e.length;n>t;t++){var r=e[t];r&&bt(this.el,r,X)}this.prevKeys=e},cleanup:function(e){var t=this.prevKeys;if(t)for(var n=t.length;n--;){var r=t[n];(!e||e.indexOf(r)<0)&&bt(this.el,r,Z)}}},Aa={priority:Ji,params:["keep-alive","transition-mode","inline-template"],bind:function(){this.el.__vue__||(this.keepAlive=this.params.keepAlive,this.keepAlive&&(this.cache={}),this.params.inlineTemplate&&(this.inlineTemplate=Y(this.el,!0)),this.pendingComponentCb=this.Component=null,this.pendingRemovals=0,this.pendingRemovalCb=null,this.anchor=re("v-component"),q(this.el,this.anchor),this.el.removeAttribute("is"),this.el.removeAttribute(":is"),this.descriptor.ref&&this.el.removeAttribute("v-ref:"+p(this.descriptor.ref)),this.literal&&this.setComponent(this.expression))},update:function(e){this.literal||this.setComponent(e)},setComponent:function(e,t){if(this.invalidatePending(),e){var n=this;this.resolveComponent(e,function(){n.mountComponent(t)})}else this.unbuild(!0),this.remove(this.childVM,t),this.childVM=null},resolveComponent:function(e,t){var n=this;this.pendingComponentCb=x(function(r){n.ComponentName=r.options.name||("string"==typeof e?e:null),n.Component=r,t()}),this.vm._resolveComponent(e,this.pendingComponentCb)},mountComponent:function(e){this.unbuild(!0);var t=this,n=this.Component.options.activate,r=this.getCached(),i=this.build();n&&!r?(this.waitingFor=i,_t(n,i,function(){t.waitingFor===i&&(t.waitingFor=null,t.transition(i,e))})):(r&&i._updateRef(),this.transition(i,e))},invalidatePending:function(){this.pendingComponentCb&&(this.pendingComponentCb.cancel(),this.pendingComponentCb=null)},build:function(e){var t=this.getCached();if(t)return t;if(this.Component){var n={name:this.ComponentName,el:Qe(this.el),template:this.inlineTemplate,parent:this._host||this.vm,_linkerCachable:!this.inlineTemplate,_ref:this.descriptor.ref,_asComponent:!0,_isRouterView:this._isRouterView,_context:this.vm,_scope:this._scope,_frag:this._frag};e&&v(n,e);var r=new this.Component(n);return this.keepAlive&&(this.cache[this.Component.cid]=r),r}},getCached:function(){return this.keepAlive&&this.cache[this.Component.cid]},unbuild:function(e){this.waitingFor&&(this.keepAlive||this.waitingFor.$destroy(),this.waitingFor=null);var t=this.childVM;return!t||this.keepAlive?void(t&&(t._inactive=!0,t._updateRef(!0))):void t.$destroy(!1,e)},remove:function(e,t){var n=this.keepAlive;if(e){this.pendingRemovals++,this.pendingRemovalCb=t;var r=this;e.$remove(function(){r.pendingRemovals--,n||e._cleanup(),!r.pendingRemovals&&r.pendingRemovalCb&&(r.pendingRemovalCb(),r.pendingRemovalCb=null)})}else t&&t()},transition:function(e,t){var n=this,r=this.childVM;switch(r&&(r._inactive=!0),e._inactive=!1,this.childVM=e,n.params.transitionMode){case"in-out":e.$before(n.anchor,function(){n.remove(r,t)});break;case"out-in":n.remove(r,function(){e.$before(n.anchor,t)});break;default:n.remove(r),e.$before(n.anchor,t)}},unbind:function(){if(this.invalidatePending(),this.unbuild(),this.cache){for(var e in this.cache)this.cache[e].$destroy();this.cache=null}}},Na=Er._propBindingModes,La={},Ia=/^[$_a-zA-Z]+[\w$]*$/,Pa=Er._propBindingModes,ja={bind:function(){var e=this.vm,t=e._context,n=this.descriptor.prop,r=n.path,i=n.parentPath,a=n.mode===Pa.TWO_WAY,o=this.parentWatcher=new ze(t,i,function(t){Ct(e,n,t)},{twoWay:a,filters:n.filters,scope:this._scope});if(St(e,n,o.value),a){var s=this;e.$once("pre-hook:created",function(){s.childWatcher=new ze(e,r,function(e){o.set(e)},{sync:!0})})}},unbind:function(){this.parentWatcher.teardown(),this.childWatcher&&this.childWatcher.teardown()}},Ta=[],Fa=!1,Da="transition",Ra="animation",Ba=Gn+"Duration",Ua=Kn+"Duration",Ma=Dn&&window.requestAnimationFrame,Va=Ma?function(e){Ma(function(){Ma(e)})}:function(e){setTimeout(e,50)},Ha=It.prototype;Ha.enter=function(e,t){this.cancelPending(),this.callHook("beforeEnter"),this.cb=t,X(this.el,this.enterClass),e(),this.entered=!1,this.callHookWithCb("enter"),this.entered||(this.cancel=this.hooks&&this.hooks.enterCancelled,Nt(this.enterNextTick))},Ha.enterNextTick=function(){var e=this;this.justEntered=!0,Va(function(){e.justEntered=!1});var t=this.enterDone,n=this.getCssTransitionType(this.enterClass);this.pendingJsCb?n===Da&&Z(this.el,this.enterClass):n===Da?(Z(this.el,this.enterClass),this.setupCssCb(Jn,t)):n===Ra?this.setupCssCb(Qn,t):t()},Ha.enterDone=function(){this.entered=!0,this.cancel=this.pendingJsCb=null,Z(this.el,this.enterClass),this.callHook("afterEnter"),this.cb&&this.cb()},Ha.leave=function(e,t){this.cancelPending(),this.callHook("beforeLeave"),this.op=e,this.cb=t,X(this.el,this.leaveClass),this.left=!1,this.callHookWithCb("leave"),this.left||(this.cancel=this.hooks&&this.hooks.leaveCancelled,this.op&&!this.pendingJsCb&&(this.justEntered?this.leaveDone():Nt(this.leaveNextTick)))},Ha.leaveNextTick=function(){var e=this.getCssTransitionType(this.leaveClass);if(e){var t=e===Da?Jn:Qn;this.setupCssCb(t,this.leaveDone)}else this.leaveDone()},Ha.leaveDone=function(){this.left=!0,this.cancel=this.pendingJsCb=null,this.op(),Z(this.el,this.leaveClass),this.callHook("afterLeave"),this.cb&&this.cb(),this.op=null},Ha.cancelPending=function(){this.op=this.cb=null;var e=!1;this.pendingCssCb&&(e=!0,J(this.el,this.pendingCssEvent,this.pendingCssCb),this.pendingCssEvent=this.pendingCssCb=null),this.pendingJsCb&&(e=!0,this.pendingJsCb.cancel(),this.pendingJsCb=null),e&&(Z(this.el,this.enterClass),Z(this.el,this.leaveClass)),this.cancel&&(this.cancel.call(this.vm,this.el),this.cancel=null)},Ha.callHook=function(e){this.hooks&&this.hooks[e]&&this.hooks[e].call(this.vm,this.el)},Ha.callHookWithCb=function(e){var t=this.hooks&&this.hooks[e];t&&(t.length>1&&(this.pendingJsCb=x(this[e+"Done"])),t.call(this.vm,this.el,this.pendingJsCb))},Ha.getCssTransitionType=function(e){if(!(!Jn||document.hidden||this.hooks&&this.hooks.css===!1||Pt(this.el))){var t=this.type||this.typeCache[e];if(t)return t;var n=this.el.style,r=window.getComputedStyle(this.el),i=n[Ba]||r[Ba];if(i&&"0s"!==i)t=Da;else{var a=n[Ua]||r[Ua];a&&"0s"!==a&&(t=Ra)}return t&&(this.typeCache[e]=t),t}},Ha.setupCssCb=function(e,t){this.pendingCssEvent=e;var n=this,r=this.el,i=this.pendingCssCb=function(a){a.target===r&&(J(r,e,i),n.pendingCssEvent=n.pendingCssCb=null,!n.pendingJsCb&&t&&t())};G(r,e,i)};var Wa={priority:qi,update:function(e,t){var n=this.el,r=ye(this.vm.$options,"transitions",e);e=e||"v",t=t||"v",n.__v_trans=new It(n,e,r,this.vm),Z(n,t+"-transition"),X(n,e+"-transition")}},za={style:ma,"class":$a,component:Aa,prop:ja,transition:Wa},qa=/^v-bind:|^:/,Ga=/^v-on:|^@/,Ja=/^v-([^:]+)(?:$|:(.*)$)/,Ka=/\.[^\.]+/g,Qa=/^(v-bind:|:)?transition$/,Xa=1e3,Za=2e3;Zt.terminal=!0;var Ya=/[^\w\-:\.]/,eo=Object.freeze({compile:jt,compileAndLinkProps:Bt,compileRoot:Ut,transclude:on,resolveSlots:cn}),to=/^v-on:|^@/;vn.prototype._bind=function(){var e=this.name,t=this.descriptor;if(("cloak"!==e||this.vm._isCompiled)&&this.el&&this.el.removeAttribute){var n=t.attr||"v-"+e;this.el.removeAttribute(n)}var r=t.def;if("function"==typeof r?this.update=r:v(this,r),this._setupParams(),this.bind&&this.bind(),this._bound=!0,this.literal)this.update&&this.update(t.raw);else if((this.expression||this.modifiers)&&(this.update||this.twoWay)&&!this._checkStatement()){var i=this;this.update?this._update=function(e,t){i._locked||i.update(e,t)}:this._update=dn;var a=this._preProcess?f(this._preProcess,this):null,o=this._postProcess?f(this._postProcess,this):null,s=this._watcher=new ze(this.vm,this.expression,this._update,{filters:this.filters,twoWay:this.twoWay,deep:this.deep,preProcess:a,postProcess:o,scope:this._scope});this.afterBind?this.afterBind():this.update&&this.update(s.value)}},vn.prototype._setupParams=function(){if(this.params){var e=this.params;this.params=Object.create(null);for(var t,n,r,i=e.length;i--;)t=p(e[i]),r=u(t),n=U(this.el,t),null!=n?this._setupParamWatcher(r,n):(n=B(this.el,t),null!=n&&(this.params[r]=""===n?!0:n))}},vn.prototype._setupParamWatcher=function(e,t){var n=this,r=!1,i=(this._scope||this.vm).$watch(t,function(t,i){if(n.params[e]=t,r){var a=n.paramWatchers&&n.paramWatchers[e];a&&a.call(n,t,i)}else r=!0},{immediate:!0,user:!1});(this._paramUnwatchFns||(this._paramUnwatchFns=[])).push(i)},vn.prototype._checkStatement=function(){var e=this.expression;if(e&&this.acceptStatement&&!Ue(e)){var t=Be(e).get,n=this._scope||this.vm,r=function(e){n.$event=e,t.call(n,n),n.$event=null};return this.filters&&(r=n._applyFilters(r,null,this.filters)), -this.update(r),!0}},vn.prototype.set=function(e){this.twoWay&&this._withLock(function(){this._watcher.set(e)})},vn.prototype._withLock=function(e){var t=this;t._locked=!0,e.call(t),Yn(function(){t._locked=!1})},vn.prototype.on=function(e,t,n){G(this.el,e,t,n),(this._listeners||(this._listeners=[])).push([e,t])},vn.prototype._teardown=function(){if(this._bound){this._bound=!1,this.unbind&&this.unbind(),this._watcher&&this._watcher.teardown();var e,t=this._listeners;if(t)for(e=t.length;e--;)J(this.el,t[e][0],t[e][1]);var n=this._paramUnwatchFns;if(n)for(e=n.length;e--;)n[e]();this.vm=this.el=this._watcher=this._listeners=null}};var no=/[^|]\|[^|]/;Ce(wn),hn(wn),fn(wn),mn(wn),yn(wn),gn(wn),bn(wn),_n(wn),xn(wn);var ro={priority:Zi,params:["name"],bind:function(){var e=this.params.name||"default",t=this.vm._slotContents&&this.vm._slotContents[e];t&&t.hasChildNodes()?this.compile(t.cloneNode(!0),this.vm._context,this.vm):this.fallback()},compile:function(e,t,n){if(e&&t){if(this.el.hasChildNodes()&&1===e.childNodes.length&&1===e.childNodes[0].nodeType&&e.childNodes[0].hasAttribute("v-if")){var r=document.createElement("template");r.setAttribute("v-else",""),r.innerHTML=this.el.innerHTML,r._context=this.vm,e.appendChild(r)}var i=n?n._scope:this._scope;this.unlink=t.$compile(e,n,i,this._frag)}e?q(this.el,e):W(this.el)},fallback:function(){this.compile(Y(this.el,!0),this.vm)},unbind:function(){this.unlink&&this.unlink()}},io={priority:Ki,params:["name"],paramWatchers:{name:function(e){ta.remove.call(this),e&&this.insert(e)}},bind:function(){this.anchor=re("v-partial"),q(this.el,this.anchor),this.insert(this.params.name)},insert:function(e){var t=ye(this.vm.$options,"partials",e,!0);t&&(this.factory=new at(this.vm,t),ta.insert.call(this))},unbind:function(){this.frag&&this.frag.destroy()}},ao={slot:ro,partial:io},oo=ea._postProcess,so=/(\d{3})(?=\d)/g,lo={orderBy:Cn,filterBy:Sn,limitBy:kn,json:{read:function(e,t){return"string"==typeof e?e:JSON.stringify(e,null,arguments.length>1?t:2)},write:function(e){try{return JSON.parse(e)}catch(t){return e}}},capitalize:function(e){return e||0===e?(e=e.toString(),e.charAt(0).toUpperCase()+e.slice(1)):""},uppercase:function(e){return e||0===e?e.toString().toUpperCase():""},lowercase:function(e){return e||0===e?e.toString().toLowerCase():""},currency:function(e,t,n){if(e=parseFloat(e),!isFinite(e)||!e&&0!==e)return"";t=null!=t?t:"$",n=null!=n?n:2;var r=Math.abs(e).toFixed(n),i=n?r.slice(0,-1-n):r,a=i.length%3,o=a>0?i.slice(0,a)+(i.length>3?",":""):"",s=n?r.slice(-1-n):"",l=0>e?"-":"";return l+t+o+i.slice(a).replace(so,"$1,")+s},pluralize:function(e){var t=d(arguments,1),n=t.length;if(n>1){var r=e%10-1;return r in t?t[r]:t[n-1]}return t[0]+(1===e?"":"s")},debounce:function(e,t){return e?(t||(t=300),b(e,t)):void 0}};return On(wn),wn.version="1.0.26-csp",setTimeout(function(){Er.devtools&&Rn&&Rn.emit("init",wn)},0),wn}); +(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]||""});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].split(/ *\| */)}this.tokens.push(item);continue}if(cap=this.rules.lheading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[2]==="="?1:2,text:cap[1]});continue}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull.length>1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&(cap[1]==="pre"||cap[1]==="script"||cap[1]==="style"),text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(item);continue}if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:"paragraph",text:cap[1].charAt(cap[1].length-1)==="\n"?cap[1].slice(0,-1):cap[1]});continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"text",text:cap[0]});continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return this.tokens};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^<a /i.test(cap[0])){this.inLink=true}else if(this.inLink&&/^<\/a>/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(cap[0]):escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.text(escape(this.smartypants(cap[0])));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"â€").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){if(!this.options.mangle)return text;var out="",l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"<pre><code>"+(escaped?code:escape(code,true))+"\n</code></pre>"}return'<pre><code class="'+this.options.langPrefix+escape(lang,true)+'">'+(escaped?code:escape(code,true))+"\n</code></pre>\n"};Renderer.prototype.blockquote=function(quote){return"<blockquote>\n"+quote+"</blockquote>\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"<h"+level+' id="'+this.options.headerPrefix+raw.toLowerCase().replace(/[^\w]+/g,"-")+'">'+text+"</h"+level+">\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"</"+type+">\n"};Renderer.prototype.listitem=function(text){return"<li>"+text+"</li>\n"};Renderer.prototype.paragraph=function(text){return"<p>"+text+"</p>\n"};Renderer.prototype.table=function(header,body){return"<table>\n"+"<thead>\n"+header+"</thead>\n"+"<tbody>\n"+body+"</tbody>\n"+"</table>\n"};Renderer.prototype.tablerow=function(content){return"<tr>\n"+content+"</tr>\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"</"+type+">\n"};Renderer.prototype.strong=function(text){return"<strong>"+text+"</strong>"};Renderer.prototype.em=function(text){return"<em>"+text+"</em>"};Renderer.prototype.codespan=function(text){return"<code>"+text+"</code>"};Renderer.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"};Renderer.prototype.del=function(text){return"<del>"+text+"</del>"};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='<a href="'+href+'"';if(title){out+=' title="'+title+'"'}out+=">"+text+"</a>";return out};Renderer.prototype.image=function(href,title,text){var out='<img src="'+href+'" alt="'+text+'"';if(title){out+=' title="'+title+'"'}out+=this.options.xhtml?"/>":">";return out};Renderer.prototype.text=function(text){return text};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i<this.token.header.length;i++){flags={header:true,align:this.token.align[i]};cell+=this.renderer.tablecell(this.inline.output(this.token.header[i]),{header:true,align:this.token.align[i]})}header+=this.renderer.tablerow(cell);for(i=0;i<this.token.cells.length;i++){row=this.token.cells[i];cell="";for(j=0;j<row.length;j++){cell+=this.renderer.tablecell(this.inline.output(row[j]),{header:false,align:this.token.align[j]})}body+=this.renderer.tablerow(cell)}return this.renderer.table(header,body)}case"blockquote_start":{var body="";while(this.next().type!=="blockquote_end"){body+=this.tok()}return this.renderer.blockquote(body)}case"list_start":{var body="",ordered=this.token.ordered;while(this.next().type!=="list_end"){body+=this.tok()}return this.renderer.list(body,ordered)}case"list_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.token.type==="text"?this.parseText():this.tok()}return this.renderer.listitem(body)}case"loose_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.tok()}return this.renderer.listitem(body)}case"html":{var html=!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;return this.renderer.html(html)}case"paragraph":{return this.renderer.paragraph(this.inline.output(this.token.text))}case"text":{return this.renderer.paragraph(this.parseText())}}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target){if(Object.prototype.hasOwnProperty.call(target,key)){obj[key]=target[key]}}}return obj}function marked(src,opt,callback){if(callback||typeof opt==="function"){if(!callback){callback=opt;opt=null}opt=merge({},marked.defaults,opt||{});var highlight=opt.highlight,tokens,pending,i=0;try{tokens=Lexer.lex(src,opt)}catch(e){return callback(e)}pending=tokens.length;var done=function(err){if(err){opt.highlight=highlight;return callback(err)}var out;try{out=Parser.parse(tokens,opt)}catch(e){err=e}opt.highlight=highlight;return err?callback(err):callback(null,out)};if(!highlight||highlight.length<3){return done()}delete opt.highlight;if(!pending)return done();for(;i<tokens.length;i++){(function(token){if(token.type!=="code"){return--pending||done()}return highlight(token.text,token.lang,function(err,code){if(err)return done(err);if(code==null||code===token.text){return--pending||done()}token.text=code;token.escaped=true;--pending||done()})})(tokens[i])}return}try{if(opt)opt=merge({},marked.defaults,opt);return Parser.parse(Lexer.lex(src,opt),opt)}catch(e){e.message+="\nPlease report this to https://github.com/chjj/marked.";if((opt||marked.defaults).silent){return"<p>An error occured:</p><pre>"+escape(e.message+"",true)+"</pre>"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}());
\ No newline at end of file diff --git a/assets/sass/_alert.sass b/assets/sass/_alert.sass index 5a90c825..6de1c2f6 100644 --- a/assets/sass/_alert.sass +++ b/assets/sass/_alert.sass @@ -48,3 +48,11 @@ border-width: 1px 0 0 border-radius: 4px 4px 0 0 z-index: 9999 + opacity: 1 + animation: fadeout 5s linear forwards + +@keyframes fadeout + 0% + opacity: 1 + 100% + opacity: 0 diff --git a/assets/sass/_suggest_menu.sass b/assets/sass/_suggest_menu.sass new file mode 100644 index 00000000..76580d56 --- /dev/null +++ b/assets/sass/_suggest_menu.sass @@ -0,0 +1,28 @@ +@import variables + +#suggest-menu + position: absolute + display: block + z-index: 1000 + min-width: 160px + padding: 5px 0 + background: #fff + list-style: none + border: 1px solid #ccc + border-radius: 3px + box-shadow: 0 6px 12px rgba(0, 0, 0, .175) + +.suggest-menu-item + white-space: nowrap + padding: 3px 10px + color: color('primary') + font-weight: bold + cursor: pointer + &.active + color: #fff + background: #428bca + small + color: #fff + small + color: color('light') + font-weight: normal diff --git a/assets/sass/app.sass b/assets/sass/app.sass index 9a93e4ab..45f9ef59 100644 --- a/assets/sass/app.sass +++ b/assets/sass/app.sass @@ -11,6 +11,7 @@ @import tooltip @import dropdown @import accordion +@import suggest_menu @import dialog_box @import popover @import pagination @@ -3,6 +3,11 @@ use Symfony\Component\EventDispatcher\Event; +if (php_sapi_name() !== 'cli') { + echo 'This script run only from the command line'.PHP_EOL; + exit(255); +} + try { require __DIR__.'/app/common.php'; $container['dispatcher']->dispatch('app.bootstrap', new Event); diff --git a/config.default.php b/config.default.php index b9dc8d77..09774689 100644 --- a/config.default.php +++ b/config.default.php @@ -19,6 +19,12 @@ define('LOG_FILE', DATA_DIR.DIRECTORY_SEPARATOR.'debug.log'); // Plugins directory define('PLUGINS_DIR', 'plugins'); +// Plugins directory URL +define('PLUGIN_API_URL', 'https://kanboard.net/plugins.json'); + +// Enable/Disable plugin installer +define('PLUGIN_INSTALLER', true); + // Available cache drivers are "file" and "memory" define('CACHE_DRIVER', 'memory'); @@ -44,6 +50,11 @@ define('MAIL_SMTP_ENCRYPTION', null); // Valid values are "null", "ssl" or "tls" // Sendmail command to use when the transport is "sendmail" define('MAIL_SENDMAIL_COMMAND', '/usr/sbin/sendmail -bs'); +// Run automatically database migrations +// If set to false, you will have to run manually the SQL migrations from the CLI during the next Kanboard upgrade +// Do not run the migrations from multiple processes at the same time (example: web page + background worker) +define('DB_RUN_MIGRATIONS', true); + // Database driver: sqlite, mysql or postgres (sqlite by default) define('DB_DRIVER', 'sqlite'); @@ -196,7 +207,7 @@ define('ENABLE_URL_REWRITE', false); // Hide login form, useful if all your users use Google/Github/ReverseProxy authentication define('HIDE_LOGIN_FORM', false); -// Disabling logout (for external SSO authentication) +// Disabling logout (useful for external SSO authentication) define('DISABLE_LOGOUT', false); // Enable captcha after 3 authentication failure @@ -220,3 +231,6 @@ define('HTTP_PROXY_PASSWORD', ''); // Set to false to allow self-signed certificates define('HTTP_VERIFY_SSL_CERTIFICATE', true); + +// TOTP (2FA) issuer name +define('TOTP_ISSUER', 'Kanboard'); diff --git a/doc/api-authentication.markdown b/doc/api-authentication.markdown index 3ba1e8f5..be536be3 100644 --- a/doc/api-authentication.markdown +++ b/doc/api-authentication.markdown @@ -17,7 +17,8 @@ Default method (HTTP Basic) ### User credentials -- Use the real username and password +- Username: username +- Password: user password or personal access token The API use the [HTTP Basic Authentication Scheme described in the RFC2617](http://www.ietf.org/rfc/rfc2617.txt). diff --git a/doc/api-json-rpc.markdown b/doc/api-json-rpc.markdown index ab1056f0..fc612682 100644 --- a/doc/api-json-rpc.markdown +++ b/doc/api-json-rpc.markdown @@ -18,6 +18,7 @@ There are two types of API access: ### User API - Access to the API with the user credentials (username and password) +- You can also generate a personal access token instead of your password - Application role and project permissions are checked for each procedure - A user session is created on the server - Example of possible clients: native mobile/desktop application, command line utility, etc... diff --git a/doc/cli.markdown b/doc/cli.markdown index 37cc7ee8..8bd5bde5 100644 --- a/doc/cli.markdown +++ b/doc/cli.markdown @@ -10,7 +10,7 @@ Usage ----- - Open a terminal and go to your Kanboard directory (example: `cd /var/www/kanboard`) -- Run the command `./kanboard` +- Run the command `./cli` or `php cli` ```bash Kanboard version master @@ -32,6 +32,9 @@ Available commands: help Displays help for a command list Lists commands worker Execute queue worker + db + db:migrate Execute SQL migrations + db:version Show database schema version export export:daily-project-column-stats Daily project column stats CSV export (number of tasks per column and per day) export:subtasks Subtasks CSV export @@ -63,13 +66,13 @@ Available commands Usage: ```bash -./kanboard export:tasks <project_id> <start_date> <end_date> +./cli export:tasks <project_id> <start_date> <end_date> ``` Example: ```bash -./kanboard export:tasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +./cli export:tasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ``` CSV data are sent to `stdout`. @@ -79,13 +82,13 @@ CSV data are sent to `stdout`. Usage: ```bash -./kanboard export:subtasks <project_id> <start_date> <end_date> +./cli export:subtasks <project_id> <start_date> <end_date> ``` Example: ```bash -./kanboard export:subtasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +./cli export:subtasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ``` ### Task transitions CSV export @@ -93,13 +96,13 @@ Example: Usage: ```bash -./kanboard export:transitions <project_id> <start_date> <end_date> +./cli export:transitions <project_id> <start_date> <end_date> ``` Example: ```bash -./kanboard export:transitions 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +./cli export:transitions 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ``` ### Export daily summaries data in CSV @@ -107,13 +110,13 @@ Example: The exported data will be printed on the standard output: ```bash -./kanboard export:daily-project-column-stats <project_id> <start_date> <end_date> +./cli export:daily-project-column-stats <project_id> <start_date> <end_date> ``` Example: ```bash -./kanboard export:daily-project-column-stats 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +./cli export:daily-project-column-stats 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ``` ### Send notifications for overdue tasks @@ -121,7 +124,7 @@ Example: Emails will be sent to all users with notifications enabled. ```bash -./kanboard notification:overdue-tasks +./cli notification:overdue-tasks ``` Optional parameters: @@ -147,7 +150,7 @@ You can also display the overdue tasks with the flag `--show`: This command calculate the statistics of each project: ```bash -./kanboard projects:daily-stats +./cli projects:daily-stats Run calculation for Project #0 Run calculation for Project #1 Run calculation for Project #10 @@ -158,14 +161,14 @@ Run calculation for Project #10 This command send a "daily cronjob event" to all open tasks of each project. ```bash -./kanboard trigger:tasks +./cli trigger:tasks Trigger task event: project_id=2, nb_tasks=1 ``` ### Reset user password ```bash -./kanboard user:reset-password my_user +./cli user:reset-password my_user ``` You will be prompted for a password and confirmation. Characters are not printed to the screen. @@ -173,13 +176,13 @@ You will be prompted for a password and confirmation. Characters are not printed ### Remove two-factor authentication for a user ```bash -./kanboard user:reset-2fa my_user +./cli user:reset-2fa my_user ``` ### Install a plugin ```bash -./kanboard plugin:install https://github.com/kanboard/plugin-github-auth/releases/download/v1.0.1/GithubAuth-1.0.1.zip +./cli plugin:install https://github.com/kanboard/plugin-github-auth/releases/download/v1.0.1/GithubAuth-1.0.1.zip ``` Note: Installed files will have the same permissions as the current user @@ -187,13 +190,13 @@ Note: Installed files will have the same permissions as the current user ### Remove a plugin ```bash -./kanboard plugin:uninstall Budget +./cli plugin:uninstall Budget ``` ### Upgrade all plugins ```bash -./kanboard plugin:upgrade +./cli plugin:upgrade * Updating plugin: Budget Planning * Plugin up to date: Github Authentication ``` @@ -201,5 +204,21 @@ Note: Installed files will have the same permissions as the current user ### Run Background worker ```bash -./kanboard worker +./cli worker +``` + +### Execute database migrations + +If the parameter `DB_RUN_MIGRATIONS` is set to `false`, you have run the database migrations manually: + +```bash +./cli db:migrate +``` + +### Check database schema version + +```bash +./cli db:version +Current version: 95 +Last version: 96 ``` diff --git a/doc/config.markdown b/doc/config.markdown index 853fa6f2..a2046989 100644 --- a/doc/config.markdown +++ b/doc/config.markdown @@ -30,6 +30,12 @@ Enable/disable plugin installation from the user interface: define('PLUGIN_INSTALLER', true); // Default is true ``` +Change default plugin directory URL: + +```php +define('PLUGIN_API_URL', 'https://kanboard.net/plugins.json'); +``` + Folder for uploaded files ------------------------- @@ -80,6 +86,11 @@ Database settings ----------------- ```php +// Run automatically database migrations +// If set to false, you will have to run manually the SQL migrations from the CLI during the next Kanboard upgrade +// Do not run the migrations from multiple processes at the same time (example: web page + background worker) +define('DB_RUN_MIGRATIONS', true); + // Database driver: sqlite, mysql or postgres (sqlite by default) define('DB_DRIVER', 'sqlite'); @@ -315,4 +326,7 @@ define('DISABLE_LOGOUT', false); // Override API token stored in the database, useful for automated tests define('API_AUTHENTICATION_TOKEN', 'My unique API Token'); + +// TOTP (2FA) issuer name +define('TOTP_ISSUER', 'Kanboard'); ``` diff --git a/doc/cronjob.markdown b/doc/cronjob.markdown index 780f0025..743aac95 100644 --- a/doc/cronjob.markdown +++ b/doc/cronjob.markdown @@ -25,7 +25,7 @@ sudo crontab -u www-data -e Example to execute the daily cronjob at 8am: ```bash -0 8 * * * cd /path/to/kanboard && ./kanboard cronjob >/dev/null 2>&1 +0 8 * * * cd /path/to/kanboard && ./cli cronjob >/dev/null 2>&1 ``` Note: the cronjob process must have write access to the database in case you are using Sqlite. diff --git a/doc/es_ES/cli.markdown b/doc/es_ES/cli.markdown index 3f19b39d..ec46bdd6 100755 --- a/doc/es_ES/cli.markdown +++ b/doc/es_ES/cli.markdown @@ -10,7 +10,7 @@ Uso ----- - Abre una terminal y ve a tu directorio de kanboard (ejemplo : `cd /var/www/kanboard`) -- Corre el comando `./kanboard` +- Corre el comando `./cli` / `php cli` ```bash Kanboard version master @@ -33,10 +33,10 @@ Available commands: list Lista de comandos worker Execute queue worker export - export:daily-project-column-stats Diariamente estadísticas de exportación de CSV (número de tareas por columna y por día ) + export:daily-project-column-stats Diariamente estad�sticas de exportaci�n de CSV (n�mero de tareas por columna y por d�a ) export:subtasks Exportar a CSV las subtareas export:tasks Exportar a CSV las tareas - export:transitions Exportar a CSV tareas de transición + export:transitions Exportar a CSV tareas de transici�n locale locale:compare Comparar aplicacion de traducciones con el locale fr_FR locale:sync Sincronizar todas las traducciones basadas en el locale fr_FR @@ -51,7 +51,7 @@ Available commands: trigger trigger:tasks Disparadores de eventos calendarizados para todas las tareas user - user:reset-2fa Eliminar la autenticación two-factor para un usuario + user:reset-2fa Eliminar la autenticaci�n two-factor para un usuario user:reset-password Cambiar el passwor del usuario ``` @@ -63,13 +63,13 @@ Comandos disponibles Uso: ```bash -./kanboard export:tasks <project_id> <start_date> <end_date> +./cli export:tasks <project_id> <start_date> <end_date> ``` Ejemplo: ```bash -./kanboard export:tasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +./cli export:tasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ``` CSV los datos son enviados a `stdout`. @@ -79,41 +79,41 @@ CSV los datos son enviados a `stdout`. Uso: ```bash -./kanboard export:subtasks <project_id> <start_date> <end_date> +./cli export:subtasks <project_id> <start_date> <end_date> ``` Ejemplo: ```bash -./kanboard export:subtasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +./cli export:subtasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ``` -### Exportación a CSV de tareas de transición +### Exportaci�n a CSV de tareas de transici�n Uso: ```bash -./kanboard export:transitions <project_id> <start_date> <end_date> +./cli export:transitions <project_id> <start_date> <end_date> ``` Ejemplo: ```bash -./kanboard export:transitions 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +./cli export:transitions 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ``` ### Exportar diariamente resumenes de datos en CSV -Los datos exportados se pueden imprimir en la salida estándar: +Los datos exportados se pueden imprimir en la salida est�ndar: ```bash -./kanboard export:daily-project-column-stats <project_id> <start_date> <end_date> +./cli export:daily-project-column-stats <project_id> <start_date> <end_date> ``` Ejemplo: ```bash -./kanboard export:daily-project-column-stats 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv +./cli export:daily-project-column-stats 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ``` ### Envio de notificaciones para tareas atrasadas @@ -121,7 +121,7 @@ Ejemplo: Los Emails se enviaran a todos los usuarios con las notificaciones habilitadas. ```bash -./kanboard notification:overdue-tasks +./cli notification:overdue-tasks ``` Parametros opcionales: @@ -130,10 +130,10 @@ Parametros opcionales: - `--group`: Grupo tareas atrasadas todo para un usuario (desde todos los proyectos) en un email - `--manager`: Enviar todas las tareas atrasadas a un project manager(s) en un email -También puede mostrar las tareas atrasadas con la bandera `--show`: +Tambi�n puede mostrar las tareas atrasadas con la bandera `--show`: ```bash -./kanboard notification:overdue-tasks --show +./cli notification:overdue-tasks --show +-----+---------+------------+------------+--------------+----------+ | Id | Title | Due date | Project Id | Project name | Assignee | +-----+---------+------------+------------+--------------+----------+ @@ -147,7 +147,7 @@ También puede mostrar las tareas atrasadas con la bandera `--show`: Este comando calcula las estadisticas por cada proyecto: ```bash -./kanboard projects:daily-stats +./cli projects:daily-stats Run calculation for Project #0 Run calculation for Project #1 Run calculation for Project #10 @@ -158,42 +158,42 @@ Run calculation for Project #10 Este comando envia a "daily cronjob event" a todas las tareas abiertas de cada proyecto. ```bash -./kanboard trigger:tasks +./cli trigger:tasks Trigger task event: project_id=2, nb_tasks=1 ``` ### Resetear el password del usuario ```bash -./kanboard user:reset-password my_user +./cli user:reset-password my_user ``` -Se le pedirá una contraseña y la confirmación. Los caracteres no se imprimen en la pantalla. +Se le pedir� una contrase�a y la confirmaci�n. Los caracteres no se imprimen en la pantalla. -### Eliminar la autenticación two-factor para un usuario +### Eliminar la autenticaci�n two-factor para un usuario ```bash -./kanboard user:reset-2fa my_user +./cli user:reset-2fa my_user ``` ### Instalar un plugin ```bash -./kanboard plugin:install https://github.com/kanboard/plugin-github-auth/releases/download/v1.0.1/GithubAuth-1.0.1.zip +./cli plugin:install https://github.com/kanboard/plugin-github-auth/releases/download/v1.0.1/GithubAuth-1.0.1.zip ``` -Nota: Los archivos instalados tendrán los mismos permisos que el usuario actual +Nota: Los archivos instalados tendr�n los mismos permisos que el usuario actual ### Eliminar un usuario ```bash -./kanboard plugin:uninstall Budget +./cli plugin:uninstall Budget ``` ### Upgrade todos los plugins ```bash -./kanboard plugin:upgrade +./cli plugin:upgrade * Updating plugin: Budget Planning * Plugin up to date: Github Authentication ``` @@ -201,5 +201,5 @@ Nota: Los archivos instalados tendrán los mismos permisos que el usuario actual ### Run Background worker ```bash -./kanboard worker +./cli worker ``` diff --git a/doc/es_ES/cronjob.markdown b/doc/es_ES/cronjob.markdown index f8f9ebc8..b7dc5cee 100755 --- a/doc/es_ES/cronjob.markdown +++ b/doc/es_ES/cronjob.markdown @@ -1,4 +1,4 @@ -Programación de Jobs en background +Programaci�n de Jobs en background ================================== Para trabajar correctamente,Kanboard requiere que se corra un job en background diariamente. @@ -10,7 +10,7 @@ Este job es necesario para estas caracteristicas: - Enviar notificaciones de tareas atrasadas. - Ejecutar automaticamente acciones conectadas a el evento "Daily background job for tasks" -Configuración de plataformas Unix y Linux +Configuraci�n de plataformas Unix y Linux ----------------------------------------- Hay varias maneras de definir una tarea programada en sistemas operativos Unix/Linux , este ejemplo es para Ubuntu 14.04 . @@ -25,7 +25,7 @@ sudo crontab -u www-data -e Ejemplo para ejecutar diariamente cronjob a las 8am: ```bash -0 8 * * * cd /path/to/kanboard && ./kanboard cronjob >/dev/null 2>&1 +0 8 * * * cd /path/to/kanboard && ./cli cronjob >/dev/null 2>&1 ``` Nota : El proceso del cronjob debe tener acceso a escritura de la base de datos en caso de usar Sqlite. diff --git a/doc/es_ES/installation.markdown b/doc/es_ES/installation.markdown index 9491d591..f3dfc495 100644 --- a/doc/es_ES/installation.markdown +++ b/doc/es_ES/installation.markdown @@ -44,6 +44,7 @@ Si desea instalar Kanboard fuera de la raÃz de documentos del servidor web, es ```bash . ├── assets -> ../kanboard/assets +├── cli -> ../kanboard/cli ├── doc -> ../kanboard/doc ├── favicon.ico -> ../kanboard/favicon.ico ├── index.php -> ../kanboard/index.php diff --git a/doc/es_ES/translations.markdown b/doc/es_ES/translations.markdown index 074d9ae3..66fd2a4c 100644 --- a/doc/es_ES/translations.markdown +++ b/doc/es_ES/translations.markdown @@ -50,7 +50,7 @@ How to find missing translations in the applications? From a terminal, run the following command: ```bash -./kanboard locale:compare +./cli locale:compare ``` All missing and unused translations are displayed on the screen. @@ -62,7 +62,7 @@ How to synchronize translation files? From a Unix shell run this command: ```bash -./kanboard locale:sync +./cli locale:sync ``` The French translation is used a reference to other locales. diff --git a/doc/fr_FR/index.markdown b/doc/fr_FR/index.markdown index d48c94ca..b33baf85 100644 --- a/doc/fr_FR/index.markdown +++ b/doc/fr_FR/index.markdown @@ -46,6 +46,7 @@ Utiliser Kanboard - [Créer des tâches par email](create-tasks-by-email.markdown) - [Sous-tâches](subtasks.markdown) - [Analytique des tâches](analytics-tasks.markdown) +- [Mentionner les utilisateurs](user-mentions.markdown) ### Travailler avec les utilisateurs diff --git a/doc/fr_FR/installation.markdown b/doc/fr_FR/installation.markdown index 4f7569ab..9e4cb47a 100644 --- a/doc/fr_FR/installation.markdown +++ b/doc/fr_FR/installation.markdown @@ -42,6 +42,7 @@ Si vous souhaitez installer Kanboard en dehors du document root de votre serveur ```bash . ├── assets -> ../kanboard/assets +├── cli -> ../kanboard/cli ├── doc -> ../kanboard/doc ├── favicon.ico -> ../kanboard/favicon.ico ├── index.php -> ../kanboard/index.php diff --git a/doc/fr_FR/update.markdown b/doc/fr_FR/update.markdown index 508f729d..68468e50 100644 --- a/doc/fr_FR/update.markdown +++ b/doc/fr_FR/update.markdown @@ -12,7 +12,8 @@ Choses importantes à faire avant la mise à jour - **Vérifiez que votre sauvegarde est valide !** - Vérifiez encore - Toujours lire la [liste des changements](https://github.com/kanboard/kanboard/blob/master/ChangeLog) pour vérifier sil y a des opérations manuelles à faire -- Toujours fermer les sessions des utilisateurs sur le serveur +- Stoppez le _worker_ +- Mettez le serveur web en mode maintenance pour éviter que les gens utilisent l'application pendant la mise à jour Depuis l'archive (version stable) --------------------------------- @@ -33,3 +34,21 @@ Depuis le dépôt git (version de développement) 3. Testez que tout fonctionne correctement Cette méthode va installer **la version en cours de développement**, utilisez là à vos risques. + +Appliquer les migrations SQL manuellement +----------------------------------------- + +Par défaut, les migrations SQL sont exécutées automatiquement. +La version du schéma est vérifiée à chaque requête. +De cette manière, les changements de base de données sont appliqués automatiquement. + +Vous pouvez désactiver ce comportement si vous le souhaitez en fonction de votre configuration. +Par exemple, si plusieurs processus essaient de mettre à jour le schéma en même temps, il se peut que vous ayez des problèmes même si chaque opération se fait dans une transaction. + +Pour désactiver cette fonctionnalité, mettez le paramètre `DB_RUN_MIGRATIONS` à `false` dans votre fichier de [configuration](config.markdown). + +Lorsque vous allez mettre à jour Kanboard, exécutez cette commande : + +```bash +./cli db:migrate +``` diff --git a/doc/fr_FR/user-mentions.markdown b/doc/fr_FR/user-mentions.markdown new file mode 100644 index 00000000..af322bb8 --- /dev/null +++ b/doc/fr_FR/user-mentions.markdown @@ -0,0 +1,13 @@ +Mentionner les utilisateurs +=========================== + +Kanboard offre la possibilité d'envoyer des notifications lorsque quelqu'un est mentionné. + +Si vous avez besoin d'obtenir l'attention de quelqu'un dans un commentaire ou une tâche, utilisez le symbole @ suivi de l'identifiant de l'utilisateur. +Kanboard va automatiquement suggérer une liste d'utilisateurs : + +![Mentions](screenshots/user-mentions.png) + +- Pour le moment, cette fonctionnalité est activée uniquement pour la description des tâches et les commentaires +- Cela fonctionne seulement lors de la création des tâches ou commentaires +- Pour être mentionné, les utilisateurs doivent être membres du projet diff --git a/doc/index.markdown b/doc/index.markdown index 54010d0c..09b39d9f 100644 --- a/doc/index.markdown +++ b/doc/index.markdown @@ -89,6 +89,7 @@ Using Kanboard - [Solving database migration issues](solving-database-migration-issues.markdown) - [Blank page after upgrading](solving-blank-page-issue.markdown) +- [Unable to open a session on Windows IIS and Internet Explorer](solving-session-issue-windows-iis-ie.markdown) - [Performances](performances.markdown) Technical details @@ -110,7 +111,6 @@ Technical details - [Run Kanboard with Docker](docker.markdown) - [Run Kanboard with Vagrant](vagrant.markdown) - [Run Kanboard on Cloudron](cloudron.markdown) -- [Run Kanboard on Nitrous](nitrous.markdown) ### Configuration diff --git a/doc/installation.markdown b/doc/installation.markdown index 67b010a9..518282be 100644 --- a/doc/installation.markdown +++ b/doc/installation.markdown @@ -21,7 +21,7 @@ The `data` folder is used to store: - Uploaded files: `files/*` - Image thumbnails: `files/thumbnails/*` -People who are using a remote database (Mysql/Postgresql) and a remote file storage (Aws S3 or similar) don't necessarily need to have a persistent local data folder or to change the permission. +People who are using a remote database (Mysql/Postgresql) and a remote object storage (Aws S3 or similar) don't necessarily need to have a persistent local data folder or to change the permission. From the git repository (development version) --------------------------------------------- @@ -42,6 +42,7 @@ If you would like to install Kanboard outside of the web server document root, y ```bash . ├── assets -> ../kanboard/assets +├── cli -> ../kanboard/cli ├── doc -> ../kanboard/doc ├── favicon.ico -> ../kanboard/favicon.ico ├── index.php -> ../kanboard/index.php @@ -53,7 +54,16 @@ The `.htaccess` is optional because its content can be included directly in the You can also define a custom location for the plugins and files folders by changing the [config file](config.markdown). -Optional installation + +Other Database Types +-------------------- + +Kanboard supports Mysql and Postgres as alternative to Sqlite. + +- [Mysql configuration](mysql-configuration.markdown] +- [Postgres configuration](postgresql-configuration.markdown) + +Optional Installation --------------------- - Some features of Kanboard require that you run [a daily background job](cronjob.markdown) (Reports and analytics) diff --git a/doc/nitrous.markdown b/doc/nitrous.markdown deleted file mode 100644 index daaedcef..00000000 --- a/doc/nitrous.markdown +++ /dev/null @@ -1,10 +0,0 @@ -Nitrous Quickstart -================== - -Create a free development environment for this Kanboard project in the cloud on [Nitrous.io](https://www.nitrous.io) by clicking the button below. - -<a href="https://www.nitrous.io/quickstart"> - <img src="https://nitrous-image-icons.s3.amazonaws.com/quickstart.png" alt="Nitrous Quickstart" width=142 height=34> -</a> - -Simply access your site via the `Preview > 3000` link in the IDE. diff --git a/doc/plugin-registration.markdown b/doc/plugin-registration.markdown index a9273e1d..2c80aab3 100644 --- a/doc/plugin-registration.markdown +++ b/doc/plugin-registration.markdown @@ -1,6 +1,28 @@ Plugin Registration =================== +Project skeleton generator +-------------------------- + +You can use `cookiecutter` to create the project structure of your plugin automatically. + +Install Cookiecutter: + +```bash +pip install -U cookiecutter +``` + +Run Kanboard cookiecutter: + +```bash +cookiecutter gh:kanboard/cookiecutter-plugin +plugin_name [My Plugin]: Some Plugin +plugin_namespace [MyPlugin]: SomePlugin +plugin_author [Plugin Author]: Me +plugin_description [My plugin is awesome]: +plugin_homepage [https://github.com/kanboard/plugin-myplugin]: +``` + Directory structure ------------------- diff --git a/doc/postgresql-configuration.markdown b/doc/postgresql-configuration.markdown index 627e2ded..bab15313 100644 --- a/doc/postgresql-configuration.markdown +++ b/doc/postgresql-configuration.markdown @@ -6,11 +6,9 @@ By default, Kanboard use Sqlite to store its data but it's also possible to use Requirements ------------ -- Postgresql server already installed and configured +- Postgresql >= 9.3 - The PHP extension `pdo_pgsql` installed (Debian/Ubuntu: `apt-get install php5-pgsql`) -Note: Kanboard is tested with **Postgresql 9.3 and 9.4** - Configuration ------------- @@ -43,10 +41,10 @@ Note: You can also rename the template file `config.default.php` to `config.php` For the first time, Kanboard will run one by one each database migration and this process can take some time according to your configuration. -To avoid any issues or potential timeouts you can initialize the database directly by importing the SQL schema: +To avoid any issues or potential timeouts, you can initialize the database directly by importing the SQL schema: ```bash psql -U postgres my_database < app/Schema/Sql/postgres.sql ``` -The file `app/Schema/Sql/postgres.sql` is a sql dump that represents the last version of the database. +The file `app/Schema/Sql/postgres.sql` is a SQL dump that represents the last version of the database. diff --git a/doc/ru_RU/cli.markdown b/doc/ru_RU/cli.markdown index 9c7b56a7..5ac2b4ec 100644 --- a/doc/ru_RU/cli.markdown +++ b/doc/ru_RU/cli.markdown @@ -1,236 +1,125 @@ Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¾Ð¹ Ñтроки ========================== - - Канборд обеÑпечивает проÑтой Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¾Ð¹ Ñтроки, которым можно воÑпользоватьÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ из Unix терминала. Ðта возможноÑÑ‚ÑŒ доÑтупна только Ñ Ð»Ð¾ÐºÐ°Ð»ÑŒÐ½Ð¾Ð¹ машины. - - Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¾Ð¹ Ñтроки полезен Ð´Ð»Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´ вне процеÑÑов веб Ñервера. - - ИÑпользование[¶](#usage "СÑылка на Ñтот заголовок") --------------------------------------------------- - - - Откройте терминал и перейдите в директорию Канборд (например: `cd /var/www/kanboard`) +- Выполните команду `./cli` - -- Выполните команду `./kanboard` - - - -<!-- --> - - - - Kanboard version master - - - - Usage: - - command [options] [arguments] - - - - Options: - - -h, --help Display this help message - - -q, --quiet Do not output any message - - -V, --version Display this application version - - --ansi Force ANSI output - - --no-ansi Disable ANSI output - - -n, --no-interaction Do not ask any interactive question - - -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug - - - - Available commands: - - cronjob Execute daily cronjob - - help Displays help for a command - - list Lists commands - - export - - export:daily-project-column-stats Daily project column stats CSV export (number of tasks per column and per day) - - export:subtasks Subtasks CSV export - - export:tasks Tasks CSV export - - export:transitions Task transitions CSV export - - locale - - locale:compare Compare application translations with the fr_FR locale - - locale:sync Synchronize all translations based on the fr_FR locale - - notification - - notification:overdue-tasks Send notifications for overdue tasks - - plugin - - plugin:install Install a plugin from a remote Zip archive - - plugin:uninstall Remove a plugin - - plugin:upgrade Update all installed plugins - - projects - - projects:daily-stats Calculate daily statistics for all projects - - trigger - - trigger:tasks Trigger scheduler event for all tasks - - user - - user:reset-2fa Remove two-factor authentication for a user - - user:reset-password Change user password - +```bash +Kanboard version master + +Usage: + command [options] [arguments] + +Options: + -h, --help Display this help message + -q, --quiet Do not output any message + -V, --version Display this application version + --ansi Force ANSI output + --no-ansi Disable ANSI output + -n, --no-interaction Do not ask any interactive question + -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug + +Available commands: + cronjob Execute daily cronjob + help Displays help for a command + list Lists commands + worker Execute queue worker + db + db:migrate Execute SQL migrations + db:version Show database schema version + export + export:daily-project-column-stats Daily project column stats CSV export (number of tasks per column and per day) + export:subtasks Subtasks CSV export + export:tasks Tasks CSV export + export:transitions Task transitions CSV export + locale + locale:compare Compare application translations with the fr_FR locale + locale:sync Synchronize all translations based on the fr_FR locale + notification + notification:overdue-tasks Send notifications for overdue tasks + plugin + plugin:install Install a plugin from a remote Zip archive + plugin:uninstall Remove a plugin + plugin:upgrade Update all installed plugins + projects + projects:daily-stats Calculate daily statistics for all projects + trigger + trigger:tasks Trigger scheduler event for all tasks + user + user:reset-2fa Remove two-factor authentication for a user + user:reset-password Change user password +``` ДоÑтупные команды[¶](#available-commands "СÑылка на Ñтот заголовок") -------------------------------------------------------------------- - - ### ÐкÑпорт задач в формате CSV[¶](#tasks-csv-export "СÑылка на Ñтот заголовок") - - Применение: - - - ./kanboard export:tasks <project_id> <start_date> <end_date> - - + ./cli export:tasks <project_id> <start_date> <end_date> Пример: - - - ./kanboard export:tasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv - - + ./cli export:tasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv Данные CSV передаютÑÑ Ð² `stdout`. - - ### ÐкÑпорт подзадач в формате CSV[¶](#subtasks-csv-export "СÑылка на Ñтот заголовок") - - Применение: - - - ./kanboard export:subtasks <project_id> <start_date> <end_date> - - + ./cli export:subtasks <project_id> <start_date> <end_date> Пример: - - - ./kanboard export:subtasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv - - + ./cli export:subtasks 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ### ÐкÑпорт Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð·Ð°Ð´Ð°Ñ‡ в формате CSV[¶](#task-transitions-csv-export "СÑылка на Ñтот заголовок") - - Применение: - - - ./kanboard export:transitions <project_id> <start_date> <end_date> - - + ./cli export:transitions <project_id> <start_date> <end_date> Пример: - - - ./kanboard export:transitions 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv - - + ./cli export:transitions 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ### ÐкÑпорт ежедневных Ñведений в формате CSV[¶](#export-daily-summaries-data-in-csv "СÑылка на Ñтот заголовок") - - ÐкÑпортированные данные будут выведены в Ñтандартный вывод: - - - ./kanboard export:daily-project-column-stats <project_id> <start_date> <end_date> - - + ./cli export:daily-project-column-stats <project_id> <start_date> <end_date> Пример: - - - ./kanboard export:daily-project-column-stats 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv - - + ./cli export:daily-project-column-stats 1 2014-10-01 2014-11-30 > /tmp/my_custom_export.csv ### Отправка уведомлений Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñроченных задач[¶](#send-notifications-for-overdue-tasks "СÑылка на Ñтот заголовок") - - Email ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ отправлены вÑем пользователÑм, у которых включено оповещение. - - - ./kanboard notification:overdue-tasks - - + ./cli notification:overdue-tasks ÐеобÑзательные параметры: - - - `--show`: Показывать отправку уведомлений - - - - `--group`: Группировать вÑе проÑроченные задачи Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ (Ñо вÑех проектов) на один email - - - - `--manager`: ПоÑылать вÑе проÑроченные задачи менеджеру (менеджерам) проекта в одном email Ñообщении - - Ð’Ñ‹ можете проÑмотреть проÑроченные задачи Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ параметра `--show`: - - ```bash -./kanboard notification:overdue-tasks --show +./cli notification:overdue-tasks --show +-----+---------+------------+------------+--------------+----------+ | Id | Title | Due date | Project Id | Project name | Assignee | +-----+---------+------------+------------+--------------+----------+ @@ -239,93 +128,46 @@ Email ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ отправлены вÑем пользов +-----+---------+------------+------------+--------------+----------+ ``` - ### ЗапуÑк ежедневной калькулÑции ÑтатиÑтики[¶](#run-daily-project-stats-calculation "СÑылка на Ñтот заголовок") - - Ðта команда Ñчитает ÑтатиÑтику Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ проекта: - - - ./kanboard projects:daily-stats - + ./cli projects:daily-stats Run calculation for Project #0 - Run calculation for Project #1 - Run calculation for Project #10 - - ### Триггеры Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ñ‡[¶](#trigger-for-tasks) - - Ðта команда поÑылает “Ñобытие Ð´Ð»Ñ ÐµÐ¶ÐµÐ´Ð½ÐµÐ²Ð½Ñ‹Ñ… фоновых Ð·Ð°Ð´Ð°Ð½Ð¸Ð¹â€ Ð´Ð»Ñ Ð²Ñех открытых задач в каждом проекте. - - - ./kanboard trigger:tasks - + ./cli trigger:tasks Trigger task event: project_id=2, nb_tasks=1 - - ### Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ[¶](#reset-user-password "СÑылка на Ñтот заголовок") - - - ./kanboard user:reset-password my_user - - + ./cli user:reset-password my_user Будет запрошен пароль и подтверждение. Символы не отображаютÑÑ Ð½Ð° Ñкране. - - ### Удаление двухуровневой аутентификации Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ[¶](#remove-two-factor-authentication-for-a-user "СÑылка на Ñтот заголовок") - - - ./kanboard user:reset-2fa my_user - - + ./cli user:reset-2fa my_user ### УÑтановка плагина[¶](#install-a-plugin "СÑылка на Ñтот заголовок") - - - ./kanboard plugin:install https://github.com/kanboard/plugin-github-auth/releases/download/v1.0.1/GithubAuth-1.0.1.zip - - + ./cli plugin:install https://github.com/kanboard/plugin-github-auth/releases/download/v1.0.1/GithubAuth-1.0.1.zip Заметка: УÑтановленные файлы будут иметь теже права, что и у текущего Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ - - ### Удаление плагина[¶](#remove-a-plugin "СÑылка на Ñтот заголовок") - - - ./kanboard plugin:uninstall Budget - - + ./cli plugin:uninstall Budget ### Обновление вÑех плагинов[¶](#upgrade-all-plugins "СÑылка на Ñтот заголовок") - - - ./kanboard plugin:upgrade - + ./cli plugin:upgrade * Updating plugin: Budget Planning - * Plugin up to date: Github Authentication - - - - - [РуÑÑÐºÐ°Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Kanboard](http://kanboard.ru/doc/) - diff --git a/doc/ru_RU/cronjob.markdown b/doc/ru_RU/cronjob.markdown index 62f8e886..f6d3a2af 100644 --- a/doc/ru_RU/cronjob.markdown +++ b/doc/ru_RU/cronjob.markdown @@ -1,7 +1,6 @@ Ежедневные фоновые задачи ========================= - Ð”Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ð¹ работы, Канборд должен запуÑкать ежедневные фоновые задачи. Ðа Unix платформах Ñтот процеÑÑ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÑÑ‚ÑÑ Ð² `cron`. Фоновые задачи необходимы Ð´Ð»Ñ Ñледующих возможноÑтей: @@ -16,26 +15,14 @@ Ð”Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ„Ð¾Ð½Ð¾Ð²Ñ‹Ñ… задач под операционной ÑиÑтемой Unix/Linux иÑпользуютÑÑ Ñ€Ð°Ð·Ð½Ñ‹Ðµ решениÑ. ЗдеÑÑŒ приведен пример Ð´Ð»Ñ Ubuntu 14.04. Ð”Ð»Ñ Ð´Ñ€ÑƒÐ³Ð¸Ñ… ÑиÑтем процедура похожа. - Отредактируйте crontab под пользователем вашего веб Ñервера: - sudo crontab -u www-data -e - Пример запуÑка ежедневной фоновой задачи в 8 утра: - - 0 8 * * * cd /path/to/kanboard && ./kanboard cronjob >/dev/null 2>&1 - + 0 8 * * * cd /path/to/kanboard && ./cli cronjob >/dev/null 2>&1 Примечание: Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñ„Ð¾Ð½Ð¾Ð²Ñ‹Ñ… задач должен иметь права доÑтупа к вашей базе данных в Ñлучае еÑли вы иÑпользуете Sqlite. Обычно, доÑтаточно запуÑкать фоновую задачу под пользователем веб Ñервера. - - - - - - [РуÑÑÐºÐ°Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Kanboard](http://kanboard.ru/doc/) - diff --git a/doc/ru_RU/index.markdown b/doc/ru_RU/index.markdown index c4a12d52..88467206 100644 --- a/doc/ru_RU/index.markdown +++ b/doc/ru_RU/index.markdown @@ -178,7 +178,6 @@ - [ЗапуÑк Kanboard на Cloudron](cloudron.markdown) -- [ЗапуÑк Kanboard на Nitrous](nitrous.markdown) ### ÐаÑтройка[¶](#configuration "СÑылка на Ñтот заголовок") diff --git a/doc/ru_RU/installation.markdown b/doc/ru_RU/installation.markdown index e59e43d2..ff989b19 100644 --- a/doc/ru_RU/installation.markdown +++ b/doc/ru_RU/installation.markdown @@ -75,6 +75,7 @@ ├── assets -> ../kanboard/assets ├── doc -> ../kanboard/doc + ├── cli -> ../kanboard/cli ├── favicon.ico -> ../kanboard/favicon.ico ├── index.php -> ../kanboard/index.php ├── jsonrpc.php -> ../kanboard/jsonrpc.php diff --git a/doc/ru_RU/translations.markdown b/doc/ru_RU/translations.markdown index f4bcafc0..0b9c6752 100644 --- a/doc/ru_RU/translations.markdown +++ b/doc/ru_RU/translations.markdown @@ -1,61 +1,25 @@ Переводы на другие Ñзыки (локализациÑ) ====================================== - - Как перевеÑти Канборд на новый Ñзык?[¶](#how-to-translate-kanboard-to-a-new-language "СÑылка на Ñтот заголовок") ---------------------------------------------------------------------------------------------------------------- - - - Переводы хранÑÑ‚ÑÑ Ð² директории `app/Locale` - - - - Ð’ Ñтой директории еÑÑ‚ÑŒ поддиректории Ð´Ð»Ñ Ñ€Ð°Ð·Ð½Ñ‹Ñ… Ñзыков, например, Ð´Ð»Ñ Ñ€ÑƒÑÑкого имеетÑÑ `ru_RU`, Ð´Ð»Ñ Ñ„Ñ€Ð°Ð½Ñ†ÑƒÐ·Ñкого - `fr_FR` и Ñ‚.д. - - - - Переводы находÑÑ‚ÑÑ Ð² PHP файле, который возвращает маÑÑив Ñ Ð¿Ð°Ñ€Ð¾Ð¹ ключ-значение - - - - Ключ - оригинальный текÑÑ‚ на английÑком и значение - перевод на ÑоответÑвующем Ñзыке - - - - **ФранцузÑкие переводы вÑегда в актуальном ÑоÑтоÑнии** - - - - Ð’Ñегда иÑпользуйте поÑледнюю верÑию (branch master) - - ### Создание нового перевода[¶](#create-a-new-translation "СÑылка на Ñтот заголовок") 1. Создайте новую директорию: `app/Locale/xx_XX`, например `app/Locale/fr_CA` Ð´Ð»Ñ ÐºÐ°Ð½Ð°Ð´Ñкого фрацузÑкого - - - 2. Создайте новый файл Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ð¾Ð´Ð°: `app/Locale/xx_XX/translations.php` - - - 3. ИÑпользуйте как образец Ñодержимое французÑкого перевода (локализации) и замените Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ - - - 4. ВнеÑите Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² файл `app/Model/Language.php` - - - 5. Проверьте добавленный Ñзык на локальной верÑии Канборда - - - 6. Пошлите [pull-request на Github](https://help.github.com/articles/using-pull-requests/) @@ -63,93 +27,46 @@ Как обновить имеющийÑÑ Ð¿ÐµÑ€ÐµÐ²Ð¾Ð´?[¶](#how-to-update-an-existing-translation "СÑылка на Ñтот заголовок") ----------------------------------------------------------------------------------------------------- - - 1. Откройте файл перевода `app/Locale/xx_XX/translations.php` - - - 2. ОтÑутÑвующие переводы закоментированы - `//` и Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿ÑƒÑтые, нужно заполнить Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸ удалить коментарий - - - 3. Проверьте внеÑенные Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ð° локальной верÑии Канборда и пошлите [pull-request](https://help.github.com/articles/using-pull-requests/) - Как добавить новый текÑÑ‚ перевода в приложение?[¶](#how-to-add-new-translated-text-in-the-application "СÑылка на Ñтот заголовок") --------------------------------------------------------------------------------------------------------------------------------- - - Переводы отображаютÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ функций в иÑходном коде: - - `t()`: показывает текÑÑ‚ Ñ HTML escaping - - - - `e()`: показывает текÑÑ‚ без HTML escaping - Ð’Ñегда иÑпользуйте английÑкую верÑию иÑходного кода. - - - ТекÑтовые Ñтроки иÑпользуют функцию `sprintf()` Ð´Ð»Ñ Ð·Ð°Ð¼ÐµÐ½Ñ‹ Ñлементов: - - - `%s` иÑпользуетÑÑ Ð´Ð»Ñ Ð·Ð°Ð¼ÐµÐ½Ñ‹ Ñтроки - - - - `%d` иÑпользуетÑÑ Ð´Ð»Ñ Ð·Ð°Ð¼ÐµÐ½Ñ‹ цифры - ОзнакомитÑÑ Ñ Ð´Ð¾Ñтупными форматами вы можете в [документации PHP](http://php.net/sprintf). - - Как найти отÑутÑтвующие переводы в приложении?[¶](#how-to-find-missing-translations-in-the-applications "СÑылка на Ñтот заголовок") ----------------------------------------------------------------------------------------------------------------------------------- - - Из терминала запуÑтите Ñледующую команду: - - - ./kanboard locale:compare - - + ./cli locale:compare Ð’Ñе отÑутÑтвующие и неиÑпользуемые переводы будут показаны на Ñкране. Добавьте их во французÑкую локализацию и Ñинхронизируйте Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ локализациÑми (Ñмотрите ниже) - - Как Ñинхронизировать файлы переводов?[¶](#how-to-synchronize-translation-files "СÑылка на Ñтот заголовок") ---------------------------------------------------------------------------------------------------------- - - Ð’ оболочке Unix запуÑтите Ñледующую команду: - - - ./kanboard locale:sync - - + ./cli locale:sync ФранцузÑкий перевод иÑпользуетÑÑ Ð´Ð»Ñ ÑÑылки на другие локализации. - - - - - [РуÑÑÐºÐ°Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Kanboard](http://kanboard.ru/doc/) - diff --git a/doc/screenshots/mention-autocomplete.png b/doc/screenshots/mention-autocomplete.png Binary files differdeleted file mode 100644 index f23fb6d1..00000000 --- a/doc/screenshots/mention-autocomplete.png +++ /dev/null diff --git a/doc/screenshots/user-mentions.png b/doc/screenshots/user-mentions.png Binary files differnew file mode 100644 index 00000000..d5f7bcc6 --- /dev/null +++ b/doc/screenshots/user-mentions.png diff --git a/doc/solving-session-issue-windows-iis-ie.markdown b/doc/solving-session-issue-windows-iis-ie.markdown new file mode 100644 index 00000000..1ad3124b --- /dev/null +++ b/doc/solving-session-issue-windows-iis-ie.markdown @@ -0,0 +1,19 @@ +I'm not able to login with Internet Explorer and Microsoft IIS +============================================================== + +If you are not able to login and always get the error **"Username or password required"** even if you have entered the right credentials, +that means there is a problem with the session. + +For example, this is a known issue if you meet these criteria: + +- You are using a domain name with an underscore: `kanboard_something.mycompany.tld` +- You are using Microsoft Windows Server and IIS +- Your browser is Internet Explorer + +Solution: **Do not use underscore in the domain name because this is not a valid domain name**. + +Explanation: Internet Explorer doesn't accept cookies with a domain name with underscores because it's not valid. + +Reference: + +- https://support.microsoft.com/en-us/kb/316112 diff --git a/doc/translations.markdown b/doc/translations.markdown index 074d9ae3..66fd2a4c 100644 --- a/doc/translations.markdown +++ b/doc/translations.markdown @@ -50,7 +50,7 @@ How to find missing translations in the applications? From a terminal, run the following command: ```bash -./kanboard locale:compare +./cli locale:compare ``` All missing and unused translations are displayed on the screen. @@ -62,7 +62,7 @@ How to synchronize translation files? From a Unix shell run this command: ```bash -./kanboard locale:sync +./cli locale:sync ``` The French translation is used a reference to other locales. diff --git a/doc/update.markdown b/doc/update.markdown index fca0d7d4..76cac27a 100644 --- a/doc/update.markdown +++ b/doc/update.markdown @@ -11,8 +11,9 @@ Important things to do before updating - **Always make a backup of your data before upgrading** - **Check that your backup is valid!** - Check again -- Always read the [change log](https://github.com/kanboard/kanboard/blob/master/ChangeLog) to check for breaking changes -- Always close all user sessions (flush all sessions on the server) +- Always read the [change history](https://github.com/kanboard/kanboard/blob/master/ChangeLog) to check for breaking changes +- Stop the worker if you use it +- Put the web server in maintenance mode to avoid people use the software while upgrading From the archive (stable version) --------------------------------- @@ -33,3 +34,20 @@ From the repository (development version) 3. Login and check if everything is ok Note: This method will install the **current development version**, use at your own risk. + +Running SQL migrations manually +------------------------------- + +By default, SQL migrations are executed automatically. The schema version is checked at each request. +In this way, when you upgrade Kanboard to another version, the database schema is updated for you. + +You may want to disable this behaviour is case you have a specific configuration. +For example, if multiple processes try to apply the migrations in the same time you might have some concurrency problems even if each operation is executed inside a transaction. + +To disable this feature, set the parameter `DB_RUN_MIGRATIONS` at `false` in your [config file](config.markdown). + +When you will have to upgrade Kanboard, run this command: + +```bash +./cli db:migrate +``` diff --git a/doc/user-mentions.markdown b/doc/user-mentions.markdown index 156456d6..4ce47054 100644 --- a/doc/user-mentions.markdown +++ b/doc/user-mentions.markdown @@ -6,7 +6,7 @@ Kanboard offers the possibility to send notifications when someone is mentioned. If you need to get the attention of someone in a comment or in a task, use the @ symbol followed by their username. Kanboard will automatically suggest a list of users: -![User Mention](screenshots/mention-autocomplete.png) +![User Mention](screenshots/user-mentions.png) - At the moment, only the task description and the comment text area have this feature enabled. - The user mentions works only during tasks and comments creation. diff --git a/doc/worker.markdown b/doc/worker.markdown index 8516068b..89becacd 100644 --- a/doc/worker.markdown +++ b/doc/worker.markdown @@ -19,7 +19,7 @@ This feature is optional and require the installation of a queue daemon on your - To install Beanstalk, you can simply use the package manager of your Linux distribution - Install the [Kanboard plugin for Beanstalk](https://kanboard.net/plugin/beanstalk) -- Start the worker with the Kanboard command line tool: `./kanboard worker` +- Start the worker with the Kanboard command line tool: `./cli worker` ### RabbitMQ @@ -27,7 +27,7 @@ This feature is optional and require the installation of a queue daemon on your - Follow the official documentation of RabbitMQ for the installation and the configuration - Install the [Kanboard plugin for RabbitMQ](https://kanboard.net/plugin/rabbitmq) -- Start the worker with the Kanboard command line tool: `./kanboard worker` +- Start the worker with the Kanboard command line tool: `./cli worker` ### Notes diff --git a/docker/crontab/cronjob.alpine b/docker/crontab/cronjob.alpine index d051ff28..e92aa0e3 100644 --- a/docker/crontab/cronjob.alpine +++ b/docker/crontab/cronjob.alpine @@ -1 +1 @@ -1 0 * * * cd /var/www/app && ./kanboard cronjob +1 0 * * * cd /var/www/app && ./cli cronjob diff --git a/gulpfile.js b/gulpfile.js index 0ff5b651..c9076ffa 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -7,10 +7,15 @@ var strip = require('gulp-strip-comments'); var src = { js: [ + 'node_modules/textarea-caret/index.js', + 'assets/js/polyfills/*.js', + 'assets/js/core/base.js', + 'assets/js/core/!(base|bootstrap)*.js', + 'assets/js/components/*.js', + 'assets/js/core/bootstrap.js', 'assets/js/src/Namespace.js', 'assets/js/src/!(Namespace|Bootstrap|BoardDragAndDrop)*.js', 'assets/js/src/BoardDragAndDrop.js', - 'assets/js/components/*.js', 'assets/js/src/Bootstrap.js' ] }; @@ -66,13 +71,6 @@ gulp.task('bower', function() { }); gulp.task('vendor', function() { - gulp.src('node_modules/vue/dist/vue.min.js') - .pipe(strip({trim: true})) - .pipe(gulp.dest('node_modules/vue/dist/')) - ; - - vendor.js.push('node_modules/vue/dist/vue.min.js'); - gulp.src(vendor.js) .pipe(concat('vendor.min.js')) .pipe(gulp.dest(dist.js)) diff --git a/nitrous-post-create.sh b/nitrous-post-create.sh deleted file mode 100755 index 558cc753..00000000 --- a/nitrous-post-create.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -rm -rf ~/code/public_html - -sudo apt-get update -sudo apt-get install -y php5-sqlite -sudo apt-get clean - -cd ~/code -mv kanboard public_html -cd public_html -composer install -cd ~/code -sudo chown -R nitrous:www-data public_html -sudo service apache2 reload diff --git a/nitrous.json b/nitrous.json deleted file mode 100644 index 1cf4ab67..00000000 --- a/nitrous.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "template": "php-apache", - "ports": [3000], - "name": "Kanboard", - "description": "Kanban project management software" -} diff --git a/package.json b/package.json index ac74f034..d2a47830 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kanboard", - "dependencies": { + "devDependencies": { "bower": "^1.7.9", "gulp": "^3.9.1", "gulp-bower": "0.0.13", @@ -9,6 +9,9 @@ "gulp-sass": "^2.3.2", "gulp-strip-comments": "^2.4.3", "gulp-uglify": "^1.5.3", - "vue": "1.0.26-csp" + "jshint": "^2.9.4" + }, + "dependencies": { + "textarea-caret": "^3.0.2" } } diff --git a/tests/units/Auth/ApiAccessTokenAuthTest.php b/tests/units/Auth/ApiAccessTokenAuthTest.php new file mode 100644 index 00000000..22852805 --- /dev/null +++ b/tests/units/Auth/ApiAccessTokenAuthTest.php @@ -0,0 +1,71 @@ +<?php + +use Kanboard\Auth\ApiAccessTokenAuth; +use Kanboard\Model\UserModel; + +require_once __DIR__.'/../Base.php'; + +class ApiAccessTokenAuthTest extends Base +{ + public function testGetName() + { + $provider = new ApiAccessTokenAuth($this->container); + $this->assertEquals('API Access Token', $provider->getName()); + } + + public function testAuthenticateWithoutToken() + { + $provider = new ApiAccessTokenAuth($this->container); + + $provider->setUsername('admin'); + $provider->setPassword('admin'); + $this->assertFalse($provider->authenticate()); + $this->assertNull($provider->getUser()); + } + + public function testAuthenticateWithEmptyPassword() + { + $provider = new ApiAccessTokenAuth($this->container); + + $provider->setUsername('admin'); + $provider->setPassword(''); + $this->assertFalse($provider->authenticate()); + } + + public function testAuthenticateWithTokenAndNoScope() + { + $provider = new ApiAccessTokenAuth($this->container); + $userModel = new UserModel($this->container); + + $userModel->update(array( + 'id' => 1, + 'api_access_token' => 'test', + )); + + $provider->setUsername('admin'); + $provider->setPassword('test'); + $this->assertFalse($provider->authenticate()); + } + + public function testAuthenticateWithToken() + { + $this->container['sessionStorage']->scope = 'API'; + + $provider = new ApiAccessTokenAuth($this->container); + $userModel = new UserModel($this->container); + + $userModel->update(array( + 'id' => 1, + 'api_access_token' => 'test', + )); + + $provider->setUsername('admin'); + $provider->setPassword('test'); + $this->assertTrue($provider->authenticate()); + $this->assertInstanceOf('Kanboard\User\DatabaseUserProvider', $provider->getUser()); + + $provider->setUsername('admin'); + $provider->setPassword('something else'); + $this->assertFalse($provider->authenticate()); + } +} diff --git a/tests/units/Base.php b/tests/units/Base.php index 722a1335..1b986fcb 100644 --- a/tests/units/Base.php +++ b/tests/units/Base.php @@ -49,6 +49,7 @@ abstract class Base extends PHPUnit_Framework_TestCase $this->container->register(new Kanboard\ServiceProvider\FilterProvider()); $this->container->register(new Kanboard\ServiceProvider\JobProvider()); $this->container->register(new Kanboard\ServiceProvider\QueueProvider()); + $this->container->register(new Kanboard\ServiceProvider\ExternalTaskProvider()); $this->container['dispatcher'] = new TraceableEventDispatcher( new EventDispatcher, diff --git a/tests/units/EventBuilder/CommentEventBuilderTest.php b/tests/units/EventBuilder/CommentEventBuilderTest.php index 2f6a90b5..ff1c630e 100644 --- a/tests/units/EventBuilder/CommentEventBuilderTest.php +++ b/tests/units/EventBuilder/CommentEventBuilderTest.php @@ -33,5 +33,7 @@ class CommentEventBuilderTest extends Base $this->assertInstanceOf('Kanboard\Event\CommentEvent', $event); $this->assertNotEmpty($event['comment']); $this->assertNotEmpty($event['task']); + $this->assertEquals(1, $event->getTaskId()); + $this->assertEquals(1, $event->getProjectId()); } } diff --git a/tests/units/EventBuilder/ProjectFileEventBuilderTest.php b/tests/units/EventBuilder/ProjectFileEventBuilderTest.php index 8f5eb87e..c3595029 100644 --- a/tests/units/EventBuilder/ProjectFileEventBuilderTest.php +++ b/tests/units/EventBuilder/ProjectFileEventBuilderTest.php @@ -29,5 +29,7 @@ class ProjectFileEventBuilderTest extends Base $this->assertInstanceOf('Kanboard\Event\ProjectFileEvent', $event); $this->assertNotEmpty($event['file']); $this->assertNotEmpty($event['project']); + $this->assertNull($event->getTaskId()); + $this->assertEquals(1, $event->getProjectId()); } } diff --git a/tests/units/EventBuilder/SubtaskEventBuilderTest.php b/tests/units/EventBuilder/SubtaskEventBuilderTest.php index fe425cb8..215b1ed2 100644 --- a/tests/units/EventBuilder/SubtaskEventBuilderTest.php +++ b/tests/units/EventBuilder/SubtaskEventBuilderTest.php @@ -58,5 +58,7 @@ class SubtaskEventBuilderTest extends Base $this->assertCount(2, $event['changes']); $this->assertEquals('new title', $event['changes']['title']); $this->assertEquals(1, $event['changes']['user_id']); + $this->assertEquals(1, $event->getTaskId()); + $this->assertEquals(1, $event->getProjectId()); } } diff --git a/tests/units/EventBuilder/TaskEventBuilderTest.php b/tests/units/EventBuilder/TaskEventBuilderTest.php index c89dcd85..446b862b 100644 --- a/tests/units/EventBuilder/TaskEventBuilderTest.php +++ b/tests/units/EventBuilder/TaskEventBuilderTest.php @@ -33,6 +33,8 @@ class TaskEventBuilderTest extends Base $this->assertInstanceOf('Kanboard\Event\TaskEvent', $event); $this->assertNotEmpty($event['task']); $this->assertEquals(1, $event['task_id']); + $this->assertEquals(1, $event->getTaskId()); + $this->assertEquals(1, $event->getProjectId()); $this->assertEquals(array('title' => 'after'), $event['changes']); } diff --git a/tests/units/EventBuilder/TaskFileEventBuilderTest.php b/tests/units/EventBuilder/TaskFileEventBuilderTest.php index c90e18d3..1e88b6fb 100644 --- a/tests/units/EventBuilder/TaskFileEventBuilderTest.php +++ b/tests/units/EventBuilder/TaskFileEventBuilderTest.php @@ -32,5 +32,7 @@ class TaskFileEventBuilderTest extends Base $this->assertInstanceOf('Kanboard\Event\TaskFileEvent', $event); $this->assertNotEmpty($event['file']); $this->assertNotEmpty($event['task']); + $this->assertEquals(1, $event->getTaskId()); + $this->assertEquals(1, $event->getProjectId()); } } diff --git a/tests/units/EventBuilder/TaskLinkEventBuilderTest.php b/tests/units/EventBuilder/TaskLinkEventBuilderTest.php index 18508146..4e38eeb6 100644 --- a/tests/units/EventBuilder/TaskLinkEventBuilderTest.php +++ b/tests/units/EventBuilder/TaskLinkEventBuilderTest.php @@ -33,6 +33,8 @@ class TaskLinkEventBuilderTest extends Base $this->assertInstanceOf('Kanboard\Event\TaskLinkEvent', $event); $this->assertNotEmpty($event['task_link']); $this->assertNotEmpty($event['task']); + $this->assertEquals(1, $event->getTaskId()); + $this->assertEquals(1, $event->getProjectId()); } public function testBuildTitle() diff --git a/tests/units/Filter/TaskStartsWithIdFilterTest.php b/tests/units/Filter/TaskStartsWithIdFilterTest.php new file mode 100644 index 00000000..e911a6a1 --- /dev/null +++ b/tests/units/Filter/TaskStartsWithIdFilterTest.php @@ -0,0 +1,103 @@ +<?php + +use Kanboard\Filter\TaskStartsWithIdFilter; +use Kanboard\Model\ProjectModel; +use Kanboard\Model\TaskCreationModel; +use Kanboard\Model\TaskFinderModel; + +require_once __DIR__.'/../Base.php'; + +class TaskStartsWithIdFilterTest extends Base +{ + public function testManyResults() + { + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $query = $taskFinderModel->getExtendedQuery(); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Test'))); + + for ($i = 1; $i <= 20; $i++) { + $this->assertNotFalse($taskCreationModel->create(array('project_id' => 1, 'title' => 'Task #'.$i))); + } + + $filter = new TaskStartsWithIdFilter(); + $filter->withQuery($query); + $filter->withValue(1); + $filter->apply(); + + $tasks = $query->findAll(); + $this->assertCount(11, $tasks); + $this->assertEquals('Task #1', $tasks[0]['title']); + $this->assertEquals('Task #19', $tasks[10]['title']); + } + + public function testOneResult() + { + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $query = $taskFinderModel->getExtendedQuery(); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Test'))); + + for ($i = 1; $i <= 20; $i++) { + $this->assertNotFalse($taskCreationModel->create(array('project_id' => 1, 'title' => 'Task #'.$i))); + } + + $filter = new TaskStartsWithIdFilter(); + $filter->withQuery($query); + $filter->withValue(3); + $filter->apply(); + + $tasks = $query->findAll(); + $this->assertCount(1, $tasks); + $this->assertEquals('Task #3', $tasks[0]['title']); + } + + public function testEmptyResult() + { + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $query = $taskFinderModel->getExtendedQuery(); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Test'))); + + for ($i = 1; $i <= 20; $i++) { + $this->assertNotFalse($taskCreationModel->create(array('project_id' => 1, 'title' => 'Task #'.$i))); + } + + $filter = new TaskStartsWithIdFilter(); + $filter->withQuery($query); + $filter->withValue(30); + $filter->apply(); + + $tasks = $query->findAll(); + $this->assertCount(0, $tasks); + } + + public function testWithTwoDigits() + { + $taskFinderModel = new TaskFinderModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $query = $taskFinderModel->getExtendedQuery(); + + $this->assertEquals(1, $projectModel->create(array('name' => 'Test'))); + + for ($i = 1; $i <= 20; $i++) { + $this->assertNotFalse($taskCreationModel->create(array('project_id' => 1, 'title' => 'Task #'.$i))); + } + + $filter = new TaskStartsWithIdFilter(); + $filter->withQuery($query); + $filter->withValue(11); + $filter->apply(); + + $tasks = $query->findAll(); + $this->assertCount(1, $tasks); + $this->assertEquals('Task #11', $tasks[0]['title']); + } +} diff --git a/tests/units/Formatter/TaskSuggestMenuFormatterTest.php b/tests/units/Formatter/TaskSuggestMenuFormatterTest.php new file mode 100644 index 00000000..d247d670 --- /dev/null +++ b/tests/units/Formatter/TaskSuggestMenuFormatterTest.php @@ -0,0 +1,39 @@ +<?php + +use Kanboard\Formatter\TaskSuggestMenuFormatter; +use Kanboard\Model\ProjectModel; +use Kanboard\Model\TaskCreationModel; + +require_once __DIR__.'/../Base.php'; + +class TaskSuggestMenuFormatterTest extends Base +{ + public function testFormat() + { + $projectModel = new ProjectModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $taskSuggestMenuFormatter = new TaskSuggestMenuFormatter($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'My Project'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'Task 1', 'project_id' => 1))); + $this->assertEquals(2, $taskCreationModel->create(array('title' => 'Task 2', 'project_id' => 1))); + + $result = $taskSuggestMenuFormatter + ->withQuery($this->container['taskFinderModel']->getExtendedQuery()) + ->format() + ; + + $expected = array( + array( + 'value' => '1', + 'html' => '#1 Task 1 <small>My Project</small>', + ), + array( + 'value' => '2', + 'html' => '#2 Task 2 <small>My Project</small>', + ), + ); + + $this->assertSame($expected, $result); + } +} diff --git a/tests/units/Formatter/UserMentionFormatterTest.php b/tests/units/Formatter/UserMentionFormatterTest.php new file mode 100644 index 00000000..6338e80f --- /dev/null +++ b/tests/units/Formatter/UserMentionFormatterTest.php @@ -0,0 +1,42 @@ +<?php + +use Kanboard\Formatter\UserMentionFormatter; + +require_once __DIR__.'/../Base.php'; + +class UserMentionFormatterTest extends Base +{ + public function testFormat() + { + $userMentionFormatter = new UserMentionFormatter($this->container); + $users = array( + array( + 'id' => 1, + 'username' => 'someone', + 'name' => 'Someone', + 'email' => 'test@localhost', + 'avatar_path' => 'avatar_image', + ), + array( + 'id' => 2, + 'username' => 'somebody', + 'name' => '', + 'email' => '', + 'avatar_path' => '', + ) + ); + + $expected = array( + array( + 'value' => 'someone', + 'html' => '<div class="avatar avatar-20 avatar-inline"><img src="?controller=AvatarFileController&action=image&user_id=1&size=20" alt="Someone" title="Someone"></div> someone <small>Someone</small>', + ), + array( + 'value' => 'somebody', + 'html' => '<div class="avatar avatar-20 avatar-inline"><div class="avatar-letter" style="background-color: rgb(191, 210, 121)" title="somebody">S</div></div> somebody', + ), + ); + + $this->assertSame($expected, $userMentionFormatter->withUsers($users)->format()); + } +} diff --git a/tests/units/FunctionTest.php b/tests/units/FunctionTest.php index 1c5f971d..0709f1fb 100644 --- a/tests/units/FunctionTest.php +++ b/tests/units/FunctionTest.php @@ -59,6 +59,38 @@ class FunctionTest extends Base $this->assertSame($expected, array_column_index($input, 'k1')); } + public function testArrayColumnIndexUnique() + { + $input = array( + array( + 'k1' => 11, + 'k2' => 22, + ), + array( + 'k1' => 11, + 'k2' => 55, + ), + array( + 'k1' => 33, + 'k2' => 44, + ), + array() + ); + + $expected = array( + 11 => array( + 'k1' => 11, + 'k2' => 22, + ), + 33 => array( + 'k1' => 33, + 'k2' => 44, + ) + ); + + $this->assertSame($expected, array_column_index_unique($input, 'k1')); + } + public function testArrayMergeRelation() { $relations = array( diff --git a/tests/units/Helper/TextHelperTest.php b/tests/units/Helper/TextHelperTest.php index c9447abb..a54c5780 100644 --- a/tests/units/Helper/TextHelperTest.php +++ b/tests/units/Helper/TextHelperTest.php @@ -32,7 +32,7 @@ class TextHelperTest extends Base ); $this->assertEquals( - '<p>Task <a href="?controller=TaskViewController&action=readonly&token='.$project['token'].'&task_id=1">#1</a></p>', + '<p>Task <a href="http://localhost/?controller=TaskViewController&action=readonly&token='.$project['token'].'&task_id=1">#1</a></p>', $helper->markdown('Task #1', true) ); @@ -48,6 +48,11 @@ class TextHelperTest extends Base { $h = new TextHelper($this->container); $this->assertEquals('<p>Text <a href="?controller=UserViewController&action=profile&user_id=1" class="user-mention-link">@admin</a> @notfound</p>', $h->markdown('Text @admin @notfound')); + $this->assertEquals('<p>Text <a href="?controller=UserViewController&action=profile&user_id=1" class="user-mention-link">@admin</a>,</p>', $h->markdown('Text @admin,')); + $this->assertEquals('<p>Text <a href="?controller=UserViewController&action=profile&user_id=1" class="user-mention-link">@admin</a>!</p>', $h->markdown('Text @admin!')); + $this->assertEquals('<p>Text <a href="?controller=UserViewController&action=profile&user_id=1" class="user-mention-link">@admin</a>? </p>', $h->markdown('Text @admin? ')); + $this->assertEquals('<p>Text <a href="?controller=UserViewController&action=profile&user_id=1" class="user-mention-link">@admin</a>.</p>', $h->markdown('Text @admin.')); + $this->assertEquals('<p>Text <a href="?controller=UserViewController&action=profile&user_id=1" class="user-mention-link">@admin</a>: test</p>', $h->markdown('Text @admin: test')); $this->assertEquals('<p>Text @admin @notfound</p>', $h->markdown('Text @admin @notfound', true)); } diff --git a/tests/units/Job/CommentEventJobTest.php b/tests/units/Job/CommentEventJobTest.php index 8571af8e..b830b2b8 100644 --- a/tests/units/Job/CommentEventJobTest.php +++ b/tests/units/Job/CommentEventJobTest.php @@ -49,4 +49,46 @@ class CommentEventJobTest extends Base $this->assertArrayHasKey(CommentModel::EVENT_UPDATE.'.closure', $called); $this->assertArrayHasKey(CommentModel::EVENT_DELETE.'.closure', $called); } + + public function testThatUserMentionJobIsCalled() + { + $comment = 'some comment'; + + $this->container['queueManager'] = $this + ->getMockBuilder('\Kanboard\Core\Queue\QueueManager') + ->setConstructorArgs(array($this->container)) + ->setMethods(array( + 'push', + )) + ->getMock(); + + $this->container['userMentionJob'] = $this + ->getMockBuilder('\Kanboard\Job\UserMentionJob') + ->setConstructorArgs(array($this->container)) + ->setMethods(array( + 'withParams', + )) + ->getMock(); + + $this->container['queueManager'] + ->expects($this->any()) + ->method('push'); + + $this->container['userMentionJob'] + ->expects($this->once()) + ->method('withParams') + ->with($comment, CommentModel::EVENT_USER_MENTION, $this->anything()) + ->will($this->returnValue($this->container['userMentionJob'])); + + $commentModel = new CommentModel($this->container); + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $commentEventJob = new CommentEventJob($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => $comment, 'user_id' => 1))); + + $commentEventJob->execute(1, CommentModel::EVENT_CREATE); + } } diff --git a/tests/units/Job/TaskEventJobTest.php b/tests/units/Job/TaskEventJobTest.php index c399faad..bfd7bc55 100644 --- a/tests/units/Job/TaskEventJobTest.php +++ b/tests/units/Job/TaskEventJobTest.php @@ -186,4 +186,44 @@ class TaskEventJobTest extends Base $called = $this->container['dispatcher']->getCalledListeners(); $this->assertArrayHasKey(TaskModel::EVENT_MOVE_PROJECT.'.closure', $called); } + + public function testThatUserMentionJobIsCalled() + { + $description = 'something'; + + $this->container['queueManager'] = $this + ->getMockBuilder('\Kanboard\Core\Queue\QueueManager') + ->setConstructorArgs(array($this->container)) + ->setMethods(array( + 'push', + )) + ->getMock(); + + $this->container['userMentionJob'] = $this + ->getMockBuilder('\Kanboard\Job\UserMentionJob') + ->setConstructorArgs(array($this->container)) + ->setMethods(array( + 'withParams', + )) + ->getMock(); + + $this->container['queueManager'] + ->expects($this->any()) + ->method('push'); + + $this->container['userMentionJob'] + ->expects($this->once()) + ->method('withParams') + ->with($description, TaskModel::EVENT_USER_MENTION, $this->anything()) + ->will($this->returnValue($this->container['userMentionJob'])); + + $taskCreationModel = new TaskCreationModel($this->container); + $projectModel = new ProjectModel($this->container); + $taskEventJob = new TaskEventJob($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); + $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'description' => $description, 'project_id' => 1))); + + $taskEventJob->execute(1, array(TaskModel::EVENT_CREATE)); + } } diff --git a/tests/units/Model/UserMentionTest.php b/tests/units/Job/UserMentionJobTest.php index b41c92cd..4cd4ac9b 100644 --- a/tests/units/Model/UserMentionTest.php +++ b/tests/units/Job/UserMentionJobTest.php @@ -1,45 +1,44 @@ <?php -require_once __DIR__.'/../Base.php'; - use Kanboard\Core\Security\Role; -use Kanboard\Event\GenericEvent; -use Kanboard\Model\UserModel; -use Kanboard\Model\TaskModel; -use Kanboard\Model\TaskCreationModel; +use Kanboard\Event\TaskEvent; +use Kanboard\Job\UserMentionJob; use Kanboard\Model\ProjectModel; use Kanboard\Model\ProjectUserRoleModel; -use Kanboard\Model\UserMentionModel; +use Kanboard\Model\TaskModel; +use Kanboard\Model\UserModel; + +require_once __DIR__.'/../Base.php'; -class UserMentionTest extends Base +class UserMentionJobTest extends Base { public function testGetMentionedUsersWithNoMentions() { $userModel = new UserModel($this->container); - $userMentionModel = new UserMentionModel($this->container); + $userMentionJob = new UserMentionJob($this->container); $this->assertNotFalse($userModel->create(array('username' => 'user1'))); - $this->assertEmpty($userMentionModel->getMentionedUsers('test')); + $this->assertEmpty($userMentionJob->getMentionedUsers('test')); } public function testGetMentionedUsersWithNotficationDisabled() { $userModel = new UserModel($this->container); - $userMentionModel = new UserMentionModel($this->container); + $userMentionJob = new UserMentionJob($this->container); $this->assertNotFalse($userModel->create(array('username' => 'user1'))); - $this->assertEmpty($userMentionModel->getMentionedUsers('test @user1')); + $this->assertEmpty($userMentionJob->getMentionedUsers('test @user1')); } public function testGetMentionedUsersWithNotficationEnabled() { $userModel = new UserModel($this->container); - $userMentionModel = new UserMentionModel($this->container); + $userMentionJob = new UserMentionJob($this->container); $this->assertNotFalse($userModel->create(array('username' => 'user1'))); $this->assertNotFalse($userModel->create(array('username' => 'user2', 'name' => 'Foobar', 'notifications_enabled' => 1))); - $users = $userMentionModel->getMentionedUsers('test @user2'); + $users = $userMentionJob->getMentionedUsers('test @user2'); $this->assertCount(1, $users); $this->assertEquals('user2', $users[0]['username']); $this->assertEquals('Foobar', $users[0]['name']); @@ -47,48 +46,41 @@ class UserMentionTest extends Base $this->assertEquals('', $users[0]['language']); } - public function testGetMentionedUsersWithNotficationEnabledAndUserLoggedIn() + public function testGetMentionedUsersWithNotficationEnabledAndPunctuationMarks() { - $this->container['sessionStorage']->user = array('id' => 3); $userModel = new UserModel($this->container); - $userMentionModel = new UserMentionModel($this->container); + $userMentionJob = new UserMentionJob($this->container); $this->assertNotFalse($userModel->create(array('username' => 'user1'))); $this->assertNotFalse($userModel->create(array('username' => 'user2', 'name' => 'Foobar', 'notifications_enabled' => 1))); - $this->assertEmpty($userMentionModel->getMentionedUsers('test @user2')); + $users = $userMentionJob->getMentionedUsers('test @user2, test'); + $this->assertCount(1, $users); + $this->assertEquals('user2', $users[0]['username']); + $this->assertEquals('Foobar', $users[0]['name']); + $this->assertEquals('', $users[0]['email']); + $this->assertEquals('', $users[0]['language']); } - public function testFireEventsWithMultipleMentions() + public function testGetMentionedUsersWithNotficationEnabledAndUserLoggedIn() { - $projectUserRoleModel = new ProjectUserRoleModel($this->container); - $projectModel = new ProjectModel($this->container); + $this->container['sessionStorage']->user = array('id' => 3); $userModel = new UserModel($this->container); - $userMentionModel = new UserMentionModel($this->container); - $event = new GenericEvent(array('project_id' => 1)); - - $this->assertEquals(2, $userModel->create(array('username' => 'user1', 'name' => 'User 1', 'notifications_enabled' => 1))); - $this->assertEquals(3, $userModel->create(array('username' => 'user2', 'name' => 'User 2', 'notifications_enabled' => 1))); - - $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); - $this->assertTrue($projectUserRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); - - $this->container['dispatcher']->addListener(TaskModel::EVENT_USER_MENTION, array($this, 'onUserMention')); + $userMentionJob = new UserMentionJob($this->container); - $userMentionModel->fireEvents('test @user1 @user2', TaskModel::EVENT_USER_MENTION, $event); + $this->assertNotFalse($userModel->create(array('username' => 'user1'))); + $this->assertNotFalse($userModel->create(array('username' => 'user2', 'name' => 'Foobar', 'notifications_enabled' => 1))); - $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_USER_MENTION.'.UserMentionTest::onUserMention', $called); + $this->assertEmpty($userMentionJob->getMentionedUsers('test @user2')); } - public function testFireEventsWithNoProjectId() + public function testFireEventsWithMultipleMentions() { $projectUserRoleModel = new ProjectUserRoleModel($this->container); $projectModel = new ProjectModel($this->container); - $taskCreationModel = new TaskCreationModel($this->container); $userModel = new UserModel($this->container); - $userMentionModel = new UserMentionModel($this->container); - $event = new GenericEvent(array('task_id' => 1)); + $userMentionJob = new UserMentionJob($this->container); + $event = new TaskEvent(array('task' => array('project_id' => 1))); $this->assertEquals(2, $userModel->create(array('username' => 'user1', 'name' => 'User 1', 'notifications_enabled' => 1))); $this->assertEquals(3, $userModel->create(array('username' => 'user2', 'name' => 'User 2', 'notifications_enabled' => 1))); @@ -96,14 +88,12 @@ class UserMentionTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'P1'))); $this->assertTrue($projectUserRoleModel->addUser(1, 3, Role::PROJECT_MEMBER)); - $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'Task 1'))); - $this->container['dispatcher']->addListener(TaskModel::EVENT_USER_MENTION, array($this, 'onUserMention')); - $userMentionModel->fireEvents('test @user1 @user2', TaskModel::EVENT_USER_MENTION, $event); + $userMentionJob->execute('test @user1 @user2', TaskModel::EVENT_USER_MENTION, $event->getAll()); $called = $this->container['dispatcher']->getCalledListeners(); - $this->assertArrayHasKey(TaskModel::EVENT_USER_MENTION.'.UserMentionTest::onUserMention', $called); + $this->assertArrayHasKey(TaskModel::EVENT_USER_MENTION.'.UserMentionJobTest::onUserMention', $called); } public function onUserMention($event) diff --git a/tests/units/Model/ConfigModelTest.php b/tests/units/Model/ConfigModelTest.php new file mode 100644 index 00000000..bbc792e3 --- /dev/null +++ b/tests/units/Model/ConfigModelTest.php @@ -0,0 +1,125 @@ +<?php + +require_once __DIR__.'/../Base.php'; + +use Kanboard\Model\ConfigModel; + +class ConfigModelTest extends Base +{ + public function testRegenerateToken() + { + $configModel = new ConfigModel($this->container); + $token = $configModel->getOption('api_token'); + $this->assertTrue($configModel->regenerateToken('api_token')); + $this->assertNotEquals($token, $configModel->getOption('api_token')); + } + + public function testCRUDOperations() + { + $configModel = new ConfigModel($this->container); + + $this->assertTrue($configModel->save(array('key1' => 'value1'))); + $this->assertTrue($configModel->save(array('key1' => 'value2'))); + $this->assertTrue($configModel->save(array('key2' => 'value2'))); + + $this->assertEquals('value2', $configModel->getOption('key1')); + $this->assertEquals('value2', $configModel->getOption('key2')); + $this->assertEquals('', $configModel->getOption('key3')); + $this->assertEquals('default', $configModel->getOption('key3', 'default')); + + $this->assertTrue($configModel->exists('key1')); + $this->assertFalse($configModel->exists('key3')); + + $this->assertTrue($configModel->save(array('key1' => 'value1'))); + + $this->assertArrayHasKey('key1', $configModel->getAll()); + $this->assertArrayHasKey('key2', $configModel->getAll()); + + $this->assertContains('value1', $configModel->getAll()); + $this->assertContains('value2', $configModel->getAll()); + } + + public function testSaveApplicationUrl() + { + $configModel = new ConfigModel($this->container); + + $this->assertTrue($configModel->save(array('application_url' => 'http://localhost/'))); + $this->assertEquals('http://localhost/', $configModel->getOption('application_url')); + + $this->assertTrue($configModel->save(array('application_url' => 'http://localhost'))); + $this->assertEquals('http://localhost/', $configModel->getOption('application_url')); + + $this->assertTrue($configModel->save(array('application_url' => ''))); + $this->assertEquals('', $configModel->getOption('application_url')); + } + + public function testDefaultValues() + { + $configModel = new ConfigModel($this->container); + + $this->assertEquals(172800, $configModel->getOption('board_highlight_period')); + $this->assertEquals(60, $configModel->getOption('board_public_refresh_interval')); + $this->assertEquals(10, $configModel->getOption('board_private_refresh_interval')); + $this->assertEmpty($configModel->getOption('board_columns')); + + $this->assertEquals('yellow', $configModel->getOption('default_color')); + $this->assertEquals('en_US', $configModel->getOption('application_language')); + $this->assertEquals('UTC', $configModel->getOption('application_timezone')); + $this->assertEquals('m/d/Y', $configModel->getOption('application_date_format')); + $this->assertEmpty($configModel->getOption('application_url')); + $this->assertEmpty($configModel->getOption('application_stylesheet')); + $this->assertEquals('USD', $configModel->getOption('application_currency')); + + $this->assertEquals(0, $configModel->getOption('calendar_user_subtasks_time_tracking')); + $this->assertEquals('date_started', $configModel->getOption('calendar_user_tasks')); + $this->assertEquals('date_started', $configModel->getOption('calendar_user_tasks')); + + $this->assertEquals(0, $configModel->getOption('integration_gravatar')); + $this->assertEquals(1, $configModel->getOption('cfd_include_closed_tasks')); + $this->assertEquals(1, $configModel->getOption('password_reset')); + + $this->assertEquals(1, $configModel->getOption('subtask_time_tracking')); + $this->assertEquals(0, $configModel->getOption('subtask_restriction')); + $this->assertEmpty($configModel->getOption('project_categories')); + + $this->assertEmpty($configModel->getOption('webhook_url_task_modification')); + $this->assertEmpty($configModel->getOption('webhook_url_task_creation')); + $this->assertNotEmpty($configModel->getOption('webhook_token')); + $this->assertEmpty($configModel->getOption('webhook_url')); + + $this->assertNotEmpty($configModel->getOption('api_token')); + } + + public function testGetOption() + { + $configModel = new ConfigModel($this->container); + + $this->assertEquals('', $configModel->getOption('board_columns')); + $this->assertEquals('test', $configModel->getOption('board_columns', 'test')); + $this->assertEquals(0, $configModel->getOption('board_columns', 0)); + } + + public function testGetWithCaching() + { + $configModel = new ConfigModel($this->container); + + $this->assertEquals('UTC', $configModel->get('application_timezone')); + $this->assertTrue($configModel->save(array('application_timezone' => 'Europe/Paris'))); + + $this->assertEquals('UTC', $configModel->get('application_timezone')); // cached value + $this->assertEquals('Europe/Paris', $configModel->getOption('application_timezone')); + + $this->assertEquals('', $configModel->get('board_columns')); + $this->assertEquals('test', $configModel->get('board_columns', 'test')); + $this->assertEquals('test', $configModel->get('empty_value', 'test')); + } + + public function testValueLength() + { + $configModel = new ConfigModel($this->container); + $string = str_repeat('a', 65535); + + $this->assertTrue($configModel->save(array('application_stylesheet' => $string))); + $this->assertSame($string, $configModel->getOption('application_stylesheet')); + } +} diff --git a/tests/units/Model/ConfigTest.php b/tests/units/Model/ConfigTest.php deleted file mode 100644 index 3345ee3e..00000000 --- a/tests/units/Model/ConfigTest.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php - -require_once __DIR__.'/../Base.php'; - -use Kanboard\Model\ConfigModel; - -class ConfigTest extends Base -{ - public function testRegenerateToken() - { - $configModel = new ConfigModel($this->container); - $token = $configModel->getOption('api_token'); - $this->assertTrue($configModel->regenerateToken('api_token')); - $this->assertNotEquals($token, $configModel->getOption('api_token')); - } - - public function testCRUDOperations() - { - $c = new ConfigModel($this->container); - - $this->assertTrue($c->save(array('key1' => 'value1'))); - $this->assertTrue($c->save(array('key1' => 'value2'))); - $this->assertTrue($c->save(array('key2' => 'value2'))); - - $this->assertEquals('value2', $c->getOption('key1')); - $this->assertEquals('value2', $c->getOption('key2')); - $this->assertEquals('', $c->getOption('key3')); - $this->assertEquals('default', $c->getOption('key3', 'default')); - - $this->assertTrue($c->exists('key1')); - $this->assertFalse($c->exists('key3')); - - $this->assertTrue($c->save(array('key1' => 'value1'))); - - $this->assertArrayHasKey('key1', $c->getAll()); - $this->assertArrayHasKey('key2', $c->getAll()); - - $this->assertContains('value1', $c->getAll()); - $this->assertContains('value2', $c->getAll()); - } - - public function testSaveApplicationUrl() - { - $c = new ConfigModel($this->container); - - $this->assertTrue($c->save(array('application_url' => 'http://localhost/'))); - $this->assertEquals('http://localhost/', $c->getOption('application_url')); - - $this->assertTrue($c->save(array('application_url' => 'http://localhost'))); - $this->assertEquals('http://localhost/', $c->getOption('application_url')); - - $this->assertTrue($c->save(array('application_url' => ''))); - $this->assertEquals('', $c->getOption('application_url')); - } - - public function testDefaultValues() - { - $c = new ConfigModel($this->container); - - $this->assertEquals(172800, $c->getOption('board_highlight_period')); - $this->assertEquals(60, $c->getOption('board_public_refresh_interval')); - $this->assertEquals(10, $c->getOption('board_private_refresh_interval')); - $this->assertEmpty($c->getOption('board_columns')); - - $this->assertEquals('yellow', $c->getOption('default_color')); - $this->assertEquals('en_US', $c->getOption('application_language')); - $this->assertEquals('UTC', $c->getOption('application_timezone')); - $this->assertEquals('m/d/Y', $c->getOption('application_date_format')); - $this->assertEmpty($c->getOption('application_url')); - $this->assertEmpty($c->getOption('application_stylesheet')); - $this->assertEquals('USD', $c->getOption('application_currency')); - - $this->assertEquals(0, $c->getOption('calendar_user_subtasks_time_tracking')); - $this->assertEquals('date_started', $c->getOption('calendar_user_tasks')); - $this->assertEquals('date_started', $c->getOption('calendar_user_tasks')); - - $this->assertEquals(0, $c->getOption('integration_gravatar')); - $this->assertEquals(1, $c->getOption('cfd_include_closed_tasks')); - $this->assertEquals(1, $c->getOption('password_reset')); - - $this->assertEquals(1, $c->getOption('subtask_time_tracking')); - $this->assertEquals(0, $c->getOption('subtask_restriction')); - $this->assertEmpty($c->getOption('project_categories')); - - $this->assertEmpty($c->getOption('webhook_url_task_modification')); - $this->assertEmpty($c->getOption('webhook_url_task_creation')); - $this->assertNotEmpty($c->getOption('webhook_token')); - $this->assertEmpty($c->getOption('webhook_url')); - - $this->assertNotEmpty($c->getOption('api_token')); - } - - public function testGetOption() - { - $c = new ConfigModel($this->container); - - $this->assertEquals('', $c->getOption('board_columns')); - $this->assertEquals('test', $c->getOption('board_columns', 'test')); - $this->assertEquals(0, $c->getOption('board_columns', 0)); - } - - public function testGetWithCaching() - { - $c = new ConfigModel($this->container); - - $this->assertEquals('UTC', $c->get('application_timezone')); - $this->assertTrue($c->save(array('application_timezone' => 'Europe/Paris'))); - - $this->assertEquals('UTC', $c->get('application_timezone')); // cached value - $this->assertEquals('Europe/Paris', $c->getOption('application_timezone')); - - $this->assertEquals('', $c->get('board_columns')); - $this->assertEquals('test', $c->get('board_columns', 'test')); - $this->assertEquals('test', $c->get('empty_value', 'test')); - } -} diff --git a/tests/units/Model/ProjectPermissionModelTest.php b/tests/units/Model/ProjectPermissionModelTest.php index 3313cf2d..7f604374 100644 --- a/tests/units/Model/ProjectPermissionModelTest.php +++ b/tests/units/Model/ProjectPermissionModelTest.php @@ -26,7 +26,7 @@ class ProjectPermissionModelTest extends Base $this->assertEquals(1, $projectModel->create(array('name' => 'Project 1'))); $this->assertEquals(2, $userModel->create(array('username' => 'user1'))); - $this->assertEquals(3, $userModel->create(array('username' => 'user2'))); + $this->assertEquals(3, $userModel->create(array('username' => 'user2', 'name' => 'User 2', 'email' => 'test@here', 'avatar_path' => 'test'))); $this->assertEquals(4, $userModel->create(array('username' => 'user3'))); $this->assertEquals(1, $groupModel->create('Group A')); @@ -35,7 +35,24 @@ class ProjectPermissionModelTest extends Base $this->assertTrue($groupRoleModel->addGroup(1, 1, Role::PROJECT_MEMBER)); $this->assertTrue($userRoleModel->addUser(1, 3, Role::PROJECT_MANAGER)); - $this->assertEquals(array('user1', 'user2'), $projectPermissionModel->findUsernames(1, 'us')); + $expected = array( + 'user1' => array( + 'username' => 'user1', + 'name' => null, + 'email' => null, + 'avatar_path' => null, + 'id' => '2', + ), + 'user2' => array( + 'username' => 'user2', + 'name' => 'User 2', + 'email' => 'test@here', + 'avatar_path' => 'test', + 'id' => '3', + ) + ); + + $this->assertEquals($expected, $projectPermissionModel->findUsernames(1, 'us')); $this->assertEmpty($projectPermissionModel->findUsernames(1, 'a')); $this->assertEmpty($projectPermissionModel->findUsernames(2, 'user')); } |