From da9be4930dee9607dc661cf65bc4f451903322c6 Mon Sep 17 00:00:00 2001 From: corpsee Date: Sat, 28 Feb 2015 23:13:02 +0600 Subject: [PATCH 01/57] Added total builds count to index and project page --- PHPCI/Controller/HomeController.php | 15 ++++++++++----- PHPCI/Controller/ProjectController.php | 2 +- PHPCI/View/Project/view.phtml | 3 +-- PHPCI/View/SummaryTable.phtml | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/PHPCI/Controller/HomeController.php b/PHPCI/Controller/HomeController.php index 2455e709..8b57db58 100644 --- a/PHPCI/Controller/HomeController.php +++ b/PHPCI/Controller/HomeController.php @@ -98,12 +98,16 @@ class HomeController extends \PHPCI\Controller protected function getSummaryHtml($projects) { $summaryBuilds = array(); - $successes = array(); - $failures = array(); + $successes = array(); + $failures = array(); + $counts = array(); foreach ($projects['items'] as $project) { $summaryBuilds[$project->getId()] = $this->buildStore->getLatestBuilds($project->getId()); + $count = $this->buildStore->getWhere(array('project_id' => $project->getId()), 1, 0, array(), array('id' => 'DESC')); + $counts[$project->getId()] = $count['count']; + $success = $this->buildStore->getLastBuildByStatus($project->getId(), Build::STATUS_SUCCESS); $failure = $this->buildStore->getLastBuildByStatus($project->getId(), Build::STATUS_FAILED); @@ -112,10 +116,11 @@ class HomeController extends \PHPCI\Controller } $summaryView = new b8\View('SummaryTable'); - $summaryView->projects = $projects['items']; - $summaryView->builds = $summaryBuilds; + $summaryView->projects = $projects['items']; + $summaryView->builds = $summaryBuilds; $summaryView->successful = $successes; - $summaryView->failed = $failures; + $summaryView->failed = $failures; + $summaryView->counts = $counts; return $summaryView->render(); } diff --git a/PHPCI/Controller/ProjectController.php b/PHPCI/Controller/ProjectController.php index 285982a1..3a55f49b 100644 --- a/PHPCI/Controller/ProjectController.php +++ b/PHPCI/Controller/ProjectController.php @@ -86,7 +86,7 @@ class ProjectController extends PHPCI\Controller $this->view->builds = $builds[0]; $this->view->total = $builds[1]; $this->view->project = $project; - $this->view->branch = urldecode($branch); + $this->view->branch = urldecode($branch); $this->view->branches = $this->projectStore->getKnownBranches($projectId); $this->view->page = $page; $this->view->pages = $pages; diff --git a/PHPCI/View/Project/view.phtml b/PHPCI/View/Project/view.phtml index 0bfd5e59..900349c8 100644 --- a/PHPCI/View/Project/view.phtml +++ b/PHPCI/View/Project/view.phtml @@ -36,8 +36,7 @@
- -

+

()

diff --git a/PHPCI/View/SummaryTable.phtml b/PHPCI/View/SummaryTable.phtml index 56df6e38..9ddaabb0 100644 --- a/PHPCI/View/SummaryTable.phtml +++ b/PHPCI/View/SummaryTable.phtml @@ -123,7 +123,7 @@ foreach($projects as $project): - + (getId()]; ?>) From 9f534711866112429c84494f3d6fb5b5ebb4bc10 Mon Sep 17 00:00:00 2001 From: corpsee Date: Sat, 28 Feb 2015 23:38:56 +0600 Subject: [PATCH 02/57] Added Date column for builds table in project page. --- PHPCI/Languages/lang.da.php | 1 + PHPCI/Languages/lang.de.php | 1 + PHPCI/Languages/lang.el.php | 1 + PHPCI/Languages/lang.en.php | 1 + PHPCI/Languages/lang.fr.php | 1 + PHPCI/Languages/lang.it.php | 1 + PHPCI/Languages/lang.nl.php | 1 + PHPCI/Languages/lang.pl.php | 1 + PHPCI/Languages/lang.ru.php | 1 + PHPCI/Languages/lang.uk.php | 1 + PHPCI/View/BuildsTable.phtml | 1 + PHPCI/View/Project/view.phtml | 1 + 12 files changed, 12 insertions(+) diff --git a/PHPCI/Languages/lang.da.php b/PHPCI/Languages/lang.da.php index 5ba3d96f..fdf27bc6 100644 --- a/PHPCI/Languages/lang.da.php +++ b/PHPCI/Languages/lang.da.php @@ -126,6 +126,7 @@ i din foretrukne hosting-platform.', 'all_branches' => 'Alle branches', 'builds' => 'Builds', 'id' => 'ID', + 'date' => 'Date', 'project' => 'Projekt', 'commit' => 'Commit', 'branch' => 'Branch', diff --git a/PHPCI/Languages/lang.de.php b/PHPCI/Languages/lang.de.php index bdcc1459..a4b83580 100644 --- a/PHPCI/Languages/lang.de.php +++ b/PHPCI/Languages/lang.de.php @@ -127,6 +127,7 @@ generiert. Um es zu verwenden, fügen Sie einfach den folgenden Public Key im Ab 'all_branches' => 'Alle Branches', 'builds' => 'Builds', 'id' => 'ID', + 'date' => 'Date', 'project' => 'Projekt', 'commit' => 'Commit', 'branch' => 'Branch', diff --git a/PHPCI/Languages/lang.el.php b/PHPCI/Languages/lang.el.php index 82b3cf22..bf5649fb 100644 --- a/PHPCI/Languages/lang.el.php +++ b/PHPCI/Languages/lang.el.php @@ -127,6 +127,7 @@ PHPCI', 'all_branches' => 'Όλες οι διακλαδώσεις', 'builds' => 'Κατασκευές', 'id' => 'Αριθμός αναγνώρισης', + 'date' => 'Date', 'project' => 'Έργο', 'commit' => 'Συνεισφορά', 'branch' => 'Διακλάδωση', diff --git a/PHPCI/Languages/lang.en.php b/PHPCI/Languages/lang.en.php index 450be1ef..1e4ffa32 100644 --- a/PHPCI/Languages/lang.en.php +++ b/PHPCI/Languages/lang.en.php @@ -128,6 +128,7 @@ PHPCI', 'all_branches' => 'All Branches', 'builds' => 'Builds', 'id' => 'ID', + 'date' => 'Date', 'project' => 'Project', 'commit' => 'Commit', 'branch' => 'Branch', diff --git a/PHPCI/Languages/lang.fr.php b/PHPCI/Languages/lang.fr.php index 20410684..77e0d0ab 100644 --- a/PHPCI/Languages/lang.fr.php +++ b/PHPCI/Languages/lang.fr.php @@ -127,6 +127,7 @@ PHPCI', 'all_branches' => 'Toutes les branches', 'builds' => 'Builds', 'id' => 'ID', + 'date' => 'Date', 'project' => 'Projet', 'commit' => 'Commit', 'branch' => 'Branche', diff --git a/PHPCI/Languages/lang.it.php b/PHPCI/Languages/lang.it.php index 46ca14fd..50b59040 100644 --- a/PHPCI/Languages/lang.it.php +++ b/PHPCI/Languages/lang.it.php @@ -127,6 +127,7 @@ PHPCI', 'all_branches' => 'Tutti i Branche', 'builds' => 'Builds', 'id' => 'ID', + 'date' => 'Date', 'project' => 'Progetto', 'commit' => 'Commit', 'branch' => 'Branch', diff --git a/PHPCI/Languages/lang.nl.php b/PHPCI/Languages/lang.nl.php index 83d5e317..d62cd4e5 100644 --- a/PHPCI/Languages/lang.nl.php +++ b/PHPCI/Languages/lang.nl.php @@ -127,6 +127,7 @@ van je gekozen source code hosting platform', 'all_branches' => 'Alle brances', 'builds' => 'Builds', 'id' => 'ID', + 'date' => 'Date', 'project' => 'Project', 'commit' => 'Commit', 'branch' => 'Branch', diff --git a/PHPCI/Languages/lang.pl.php b/PHPCI/Languages/lang.pl.php index 9d6de6c8..640ac4e0 100644 --- a/PHPCI/Languages/lang.pl.php +++ b/PHPCI/Languages/lang.pl.php @@ -128,6 +128,7 @@ od wybranego kodu źródłowego platformy hostingowej.', 'all_branches' => 'Wszystkie Gałęzie', 'builds' => 'Budowania', 'id' => 'ID', + 'date' => 'Date', 'project' => 'Projekt', 'commit' => 'Commit', 'branch' => 'Gałąź', diff --git a/PHPCI/Languages/lang.ru.php b/PHPCI/Languages/lang.ru.php index 2f9ab0ee..dba0d934 100644 --- a/PHPCI/Languages/lang.ru.php +++ b/PHPCI/Languages/lang.ru.php @@ -126,6 +126,7 @@ PHPCI', 'all_branches' => 'Все ветки', 'builds' => 'Сборки', 'id' => 'ID', + 'date' => 'Дата', 'project' => 'Проект', 'commit' => 'Коммит', 'branch' => 'Ветка', diff --git a/PHPCI/Languages/lang.uk.php b/PHPCI/Languages/lang.uk.php index 7e4a2191..0fd6d66a 100644 --- a/PHPCI/Languages/lang.uk.php +++ b/PHPCI/Languages/lang.uk.php @@ -126,6 +126,7 @@ PHPCI', 'all_branches' => 'Усі гілки', 'builds' => 'Збірки', 'id' => 'ID', + 'date' => 'Дата', 'project' => 'Проект', 'commit' => 'Комміт', 'branch' => 'Гілка', diff --git a/PHPCI/View/BuildsTable.phtml b/PHPCI/View/BuildsTable.phtml index c9d44930..93ea593b 100644 --- a/PHPCI/View/BuildsTable.phtml +++ b/PHPCI/View/BuildsTable.phtml @@ -39,6 +39,7 @@ switch($build->getStatus()) ?> + + From 000aff9121c7dbeeae9cdd5f217cfd4bf5e8fcd3 Mon Sep 17 00:00:00 2001 From: corpsee Date: Sat, 28 Feb 2015 23:51:04 +0600 Subject: [PATCH 03/57] Code style fix --- PHPCI/Controller/HomeController.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/PHPCI/Controller/HomeController.php b/PHPCI/Controller/HomeController.php index 8b57db58..d0e5a14b 100644 --- a/PHPCI/Controller/HomeController.php +++ b/PHPCI/Controller/HomeController.php @@ -105,7 +105,13 @@ class HomeController extends \PHPCI\Controller foreach ($projects['items'] as $project) { $summaryBuilds[$project->getId()] = $this->buildStore->getLatestBuilds($project->getId()); - $count = $this->buildStore->getWhere(array('project_id' => $project->getId()), 1, 0, array(), array('id' => 'DESC')); + $count = $this->buildStore->getWhere( + array('project_id' => $project->getId()), + 1, + 0, + array(), + array('id' => 'DESC') + ); $counts[$project->getId()] = $count['count']; $success = $this->buildStore->getLastBuildByStatus($project->getId(), Build::STATUS_SUCCESS); From f97089529c332a83a314fefc1d9daf58407b5be4 Mon Sep 17 00:00:00 2001 From: corpsee Date: Mon, 2 Mar 2015 08:18:40 +0600 Subject: [PATCH 04/57] Fixed 'date' it lang string --- PHPCI/Languages/lang.it.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PHPCI/Languages/lang.it.php b/PHPCI/Languages/lang.it.php index 50b59040..b022068c 100644 --- a/PHPCI/Languages/lang.it.php +++ b/PHPCI/Languages/lang.it.php @@ -127,7 +127,7 @@ PHPCI', 'all_branches' => 'Tutti i Branche', 'builds' => 'Builds', 'id' => 'ID', - 'date' => 'Date', + 'date' => 'Data', 'project' => 'Progetto', 'commit' => 'Commit', 'branch' => 'Branch', From d2e6182a2ff847035b86d2e9d46184fa907563bf Mon Sep 17 00:00:00 2001 From: Mark Clements Date: Mon, 2 Mar 2015 22:31:01 +0000 Subject: [PATCH 05/57] Fixed an inconsistency in the way the prompts in the install scripts were being output. All the DB/host fields have a space after the colon, which is much better as it means the text you type is slightly separated from the prompt. However, the admin user fields didn't include this space which was inconsistent and made the install script a little less professional. I have therefore added the missing space for the prompts which didn't have it in the English language file, and have also updated all other language files to also use this format. Most of them followed the same inconsistency as the English version, though some were consistent but without a space, and some which were differently inconsistent (both internally, and between languages). --- PHPCI/Languages/lang.da.php | 16 ++++++++-------- PHPCI/Languages/lang.de.php | 6 +++--- PHPCI/Languages/lang.el.php | 12 ++++++------ PHPCI/Languages/lang.en.php | 6 +++--- PHPCI/Languages/lang.fr.php | 6 +++--- PHPCI/Languages/lang.it.php | 6 +++--- PHPCI/Languages/lang.nl.php | 16 ++++++++-------- PHPCI/Languages/lang.pl.php | 16 ++++++++-------- PHPCI/Languages/lang.ru.php | 6 +++--- PHPCI/Languages/lang.uk.php | 16 ++++++++-------- 10 files changed, 53 insertions(+), 53 deletions(-) diff --git a/PHPCI/Languages/lang.da.php b/PHPCI/Languages/lang.da.php index 5ba3d96f..3f8f2f38 100644 --- a/PHPCI/Languages/lang.da.php +++ b/PHPCI/Languages/lang.da.php @@ -296,15 +296,15 @@ du kører composer update.', Kontrollér venligst nedenstående fejl før du fortsætter.', 'must_be_valid_email' => 'Skal være en gyldig email-adresse.', 'must_be_valid_url' => 'Skal være en gyldig URL.', - 'enter_name' => 'Administrator-navn:', - 'enter_email' => 'Administrators email-adresse:', - 'enter_password' => 'Administrator-adgangskode:', - 'enter_phpci_url' => 'Din PHPCI URL (eksempelvis "http://phpci.local"):', + 'enter_name' => 'Administrator-navn: ', + 'enter_email' => 'Administrators email-adresse: ', + 'enter_password' => 'Administrator-adgangskode: ', + 'enter_phpci_url' => 'Din PHPCI URL (eksempelvis "http://phpci.local"): ', - 'enter_db_host' => 'Indtast dit MySQL-hostnavn [localhost]:', - 'enter_db_name' => 'Indtast dit MySQL database-navn [phpci]:', - 'enter_db_user' => 'Indtast dit MySQL-brugernavn [phpci]:', - 'enter_db_pass' => 'Indtast dit MySQL-password:', + 'enter_db_host' => 'Indtast dit MySQL-hostnavn [localhost]: ', + 'enter_db_name' => 'Indtast dit MySQL database-navn [phpci]: ', + 'enter_db_user' => 'Indtast dit MySQL-brugernavn [phpci]: ', + 'enter_db_pass' => 'Indtast dit MySQL-password: ', 'could_not_connect' => 'PHPCI kunne ikke forbinde til MySQL med de angivning oplysninger. Forsøg igen.', 'setting_up_db' => 'Indlæser database...', 'user_created' => 'Brugerkonto oprettet!', diff --git a/PHPCI/Languages/lang.de.php b/PHPCI/Languages/lang.de.php index bdcc1459..6a8bd5c4 100644 --- a/PHPCI/Languages/lang.de.php +++ b/PHPCI/Languages/lang.de.php @@ -294,9 +294,9 @@ generiert. Um es zu verwenden, fügen Sie einfach den folgenden Public Key im Ab Bitte überprüfen Sie die Fehler, bevor Sie fortfahren,', 'must_be_valid_email' => 'Muss eine gültige Emailadresse sein.', 'must_be_valid_url' => 'Muss eine valide URL sein.', - 'enter_name' => 'Name des Administrators:', - 'enter_email' => 'Emailadresse des Administrators:', - 'enter_password' => 'Passwort des Administrators:', + 'enter_name' => 'Name des Administrators: ', + 'enter_email' => 'Emailadresse des Administrators: ', + 'enter_password' => 'Passwort des Administrators: ', 'enter_phpci_url' => 'Ihre PHPCI-URL (z.B. "http://phpci.local"): ', 'enter_db_host' => 'Bitte geben Sie Ihren MySQL-Host ein [localhost]: ', diff --git a/PHPCI/Languages/lang.el.php b/PHPCI/Languages/lang.el.php index 82b3cf22..e3503c99 100644 --- a/PHPCI/Languages/lang.el.php +++ b/PHPCI/Languages/lang.el.php @@ -297,15 +297,15 @@ Services του Bitbucket αποθετηρίου σας.', Παρακαλούμε διαβάστε τα παραπάνω λάθη πριν συνεχίσετε.', 'must_be_valid_email' => 'Πρέπει να είναι μια έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου.', 'must_be_valid_url' => 'Πρέπει να είναι μια έγκυρη διεύθυνση URL.', - 'enter_name' => 'Όνομα διαχειριστή:', - 'enter_email' => 'Ηλ. Διεύθυνση διαχειριστή:', - 'enter_password' => 'Κωδικός πρόσβασης διαχειριστή:', + 'enter_name' => 'Όνομα διαχειριστή: ', + 'enter_email' => 'Ηλ. Διεύθυνση διαχειριστή: ', + 'enter_password' => 'Κωδικός πρόσβασης διαχειριστή: ', 'enter_phpci_url' => 'Ο URL σύνδεσμος σας για το PHPCI ("http://phpci.local" για παράδειγμα): ', - 'enter_db_host' => 'Παρακαλώ εισάγετε τον MySQL οικοδεσπότη σας [localhost]:', + 'enter_db_host' => 'Παρακαλώ εισάγετε τον MySQL οικοδεσπότη σας [localhost]: ', 'enter_db_name' => 'Παρακαλώ εισάγετε το όνομα της MySQL βάσης δεδομένων σας [phpci]: ', - 'enter_db_user' => 'Παρακαλώ εισάγετε το όνομα χρήστη της MySQL σας [phpci]:', - 'enter_db_pass' => 'Παρακαλώ εισάγετε τον κωδικό χρήστη της MySQL σας:', + 'enter_db_user' => 'Παρακαλώ εισάγετε το όνομα χρήστη της MySQL σας [phpci]: ', + 'enter_db_pass' => 'Παρακαλώ εισάγετε τον κωδικό χρήστη της MySQL σας: ', 'could_not_connect' => 'Το PHPCI δεν μπόρεσε να συνδεθεί με την MySQL με τα στοχεία που δώσατε. Παρακαλώ δοκιμάστε ξανά.', 'setting_up_db' => 'Γίνεται ρύθμιση της βάσης δεδομένων σας ...', 'user_created' => 'Λογαριασμός χρήστη δημιουργήθηκε!', diff --git a/PHPCI/Languages/lang.en.php b/PHPCI/Languages/lang.en.php index 450be1ef..2040986d 100644 --- a/PHPCI/Languages/lang.en.php +++ b/PHPCI/Languages/lang.en.php @@ -301,9 +301,9 @@ PHPCI', Please review the errors above before continuing.', 'must_be_valid_email' => 'Must be a valid email address.', 'must_be_valid_url' => 'Must be a valid URL.', - 'enter_name' => 'Admin Name:', - 'enter_email' => 'Admin Email:', - 'enter_password' => 'Admin Password:', + 'enter_name' => 'Admin Name: ', + 'enter_email' => 'Admin Email: ', + 'enter_password' => 'Admin Password: ', 'enter_phpci_url' => 'Your PHPCI URL ("http://phpci.local" for example): ', 'enter_db_host' => 'Please enter your MySQL host [localhost]: ', diff --git a/PHPCI/Languages/lang.fr.php b/PHPCI/Languages/lang.fr.php index 20410684..7d438d2f 100644 --- a/PHPCI/Languages/lang.fr.php +++ b/PHPCI/Languages/lang.fr.php @@ -298,9 +298,9 @@ PHPCI', Merci de corriger les erreurs ci-dessus avant de continuer.', 'must_be_valid_email' => 'Doit être une adresse email valide.', 'must_be_valid_url' => 'Doit être une URL valide.', - 'enter_name' => 'Nom de l\'admin :', - 'enter_email' => 'Email de l\'admin :', - 'enter_password' => 'Mot de passe de l\'admin :', + 'enter_name' => 'Nom de l\'admin: ', + 'enter_email' => 'Email de l\'admin: ', + 'enter_password' => 'Mot de passe de l\'admin: ', 'enter_phpci_url' => 'Votre URL vers PHPCI (par exemple "http://phpci.local"): ', 'enter_db_host' => 'Merci d\'entrer le nom d\'hôte MySQL [localhost]: ', diff --git a/PHPCI/Languages/lang.it.php b/PHPCI/Languages/lang.it.php index 46ca14fd..ea023454 100644 --- a/PHPCI/Languages/lang.it.php +++ b/PHPCI/Languages/lang.it.php @@ -300,9 +300,9 @@ PHPCI', Per favore controlla gli errori riportati prima di proseguire.', 'must_be_valid_email' => 'Deve essere un indirizzo email valido.', 'must_be_valid_url' => 'Deve essere un URL valido.', - 'enter_name' => 'Nome dell\'amministratore:', - 'enter_email' => 'Email dell\'amministratore:', - 'enter_password' => 'Password dell\'amministratore:', + 'enter_name' => 'Nome dell\'amministratore: ', + 'enter_email' => 'Email dell\'amministratore: ', + 'enter_password' => 'Password dell\'amministratore: ', 'enter_phpci_url' => 'L\'URL di PHPCI ("http://phpci.locale" ad esempio): ', 'enter_db_host' => 'Per favore inserisci l\'host MySQL [localhost]: ', diff --git a/PHPCI/Languages/lang.nl.php b/PHPCI/Languages/lang.nl.php index 83d5e317..f118e5b3 100644 --- a/PHPCI/Languages/lang.nl.php +++ b/PHPCI/Languages/lang.nl.php @@ -298,15 +298,15 @@ keer je composer update uitvoert.', Gelieve de fouten na te kijken vooraleer verder te gaan.', 'must_be_valid_email' => 'Moet een geldig e-mailadres zijn.', 'must_be_valid_url' => 'Moet een geldige URL zijn.', - 'enter_name' => 'Administrator naam:', - 'enter_email' => 'Administrator e-mailadres:', - 'enter_password' => 'Administrator wachtwoord:', - 'enter_phpci_url' => 'Je PHPCI URL (bijvoorbeeld "http://phpci.local")', + 'enter_name' => 'Administrator naam: ', + 'enter_email' => 'Administrator e-mailadres: ', + 'enter_password' => 'Administrator wachtwoord: ', + 'enter_phpci_url' => 'Je PHPCI URL (bijvoorbeeld "http://phpci.local"): ', - 'enter_db_host' => 'Vul je MySQL host in [localhost]:', - 'enter_db_name' => 'Vul je MySQL databasenaam in [phpci]:', - 'enter_db_user' => 'Vul je MySQL gebruikersnaam in [phpci]:', - 'enter_db_pass' => 'Vul je MySQL watchtwoord in:', + 'enter_db_host' => 'Vul je MySQL host in [localhost]: ', + 'enter_db_name' => 'Vul je MySQL databasenaam in [phpci]: ', + 'enter_db_user' => 'Vul je MySQL gebruikersnaam in [phpci]: ', + 'enter_db_pass' => 'Vul je MySQL watchtwoord in: ', 'could_not_connect' => 'PHPCI kon met deze gegevens geen verbinding maken met MySQL. Gelieve opnieuw te proberen.', 'setting_up_db' => 'Database wordt aangemaakt...', 'user_created' => 'Gebruikersprofiel aangemaakt!', diff --git a/PHPCI/Languages/lang.pl.php b/PHPCI/Languages/lang.pl.php index 9d6de6c8..c3291d1d 100644 --- a/PHPCI/Languages/lang.pl.php +++ b/PHPCI/Languages/lang.pl.php @@ -299,15 +299,15 @@ wywołaniu polecenia composer update.', Przejrzyj powyższą listę błędów przed kontynuowaniem.', 'must_be_valid_email' => 'Poprawny adres email jest wymagany.', 'must_be_valid_url' => 'Poprawny URL jest wymagany.', - 'enter_name' => 'Imię Admina:', - 'enter_email' => 'Email Admina:', - 'enter_password' => 'Hasło Admina:', - 'enter_phpci_url' => 'URL PHPCI (na przykład "http://phpci.local"):', + 'enter_name' => 'Imię Admina: ', + 'enter_email' => 'Email Admina: ', + 'enter_password' => 'Hasło Admina: ', + 'enter_phpci_url' => 'URL PHPCI (na przykład "http://phpci.local"): ', - 'enter_db_host' => 'Wpisz hosta MySQL [host lokalny]:', - 'enter_db_name' => 'Wpisz nazwę bazy danych MySQL [phpci]:', - 'enter_db_user' => 'Wpisz nazwę użytkownika MySQL [phpci]:', - 'enter_db_pass' => 'Wpisz hasło MySQL:', + 'enter_db_host' => 'Wpisz hosta MySQL [host lokalny]: ', + 'enter_db_name' => 'Wpisz nazwę bazy danych MySQL [phpci]: ', + 'enter_db_user' => 'Wpisz nazwę użytkownika MySQL [phpci]: ', + 'enter_db_pass' => 'Wpisz hasło MySQL: ', 'could_not_connect' => 'Z podanymi ustawieniami PHPCI nie udało się połączyć z MySQL. Spróbuj ponownie.', 'setting_up_db' => 'Ustawianie Twojej bazy danych...', 'user_created' => 'Utworzono konto użytkownika!', diff --git a/PHPCI/Languages/lang.ru.php b/PHPCI/Languages/lang.ru.php index 2f9ab0ee..422f17e1 100644 --- a/PHPCI/Languages/lang.ru.php +++ b/PHPCI/Languages/lang.ru.php @@ -294,9 +294,9 @@ PHPCI', Пожалуйста, просмотрите возникшие ошибки перед тем, как продолжить.', 'must_be_valid_email' => 'Должен быть корректным email-адресом.', 'must_be_valid_url' => 'Должен быть корректным URL-адресом.', - 'enter_name' => 'Имя администратора:', - 'enter_email' => 'Email администратора:', - 'enter_password' => 'Пароль администратора:', + 'enter_name' => 'Имя администратора: ', + 'enter_email' => 'Email администратора: ', + 'enter_password' => 'Пароль администратора: ', 'enter_phpci_url' => 'URL-адрес вашего PHPCI (например: "http://phpci.local"): ', 'enter_db_host' => 'Пожалуйста, введите хост MySQL [localhost]: ', diff --git a/PHPCI/Languages/lang.uk.php b/PHPCI/Languages/lang.uk.php index 7e4a2191..118fae9e 100644 --- a/PHPCI/Languages/lang.uk.php +++ b/PHPCI/Languages/lang.uk.php @@ -298,15 +298,15 @@ PHPCI', Будь ласка, продивіться наявні помилки перед тим, як продовжити.', 'must_be_valid_email' => 'Повинно бути коректною email адресою.', 'must_be_valid_url' => 'Повинно бути коректним URL.', - 'enter_name' => 'Ім’я адміністратора:', - 'enter_email' => 'Email адміністратора:', - 'enter_password' => 'Пароль адміністратора:', - 'enter_phpci_url' => 'URL адреса вашого PHPCI (наприклад, "http://phpci.local"):', + 'enter_name' => 'Ім’я адміністратора: ', + 'enter_email' => 'Email адміністратора: ', + 'enter_password' => 'Пароль адміністратора: ', + 'enter_phpci_url' => 'URL адреса вашого PHPCI (наприклад, "http://phpci.local"): ', - 'enter_db_host' => 'Будь ласка, введіть хост MySQL [localhost]:', - 'enter_db_name' => 'Будь ласка, введить ім’я бази даних MySQL [phpci]:', - 'enter_db_user' => 'Будь ласка, введить ім’я користувача MySQL [phpci]:', - 'enter_db_pass' => 'Будь ласка, введить ваш пароль MySQL:', + 'enter_db_host' => 'Будь ласка, введіть хост MySQL [localhost]: ', + 'enter_db_name' => 'Будь ласка, введить ім’я бази даних MySQL [phpci]: ', + 'enter_db_user' => 'Будь ласка, введить ім’я користувача MySQL [phpci]: ', + 'enter_db_pass' => 'Будь ласка, введить ваш пароль MySQL: ', 'could_not_connect' => 'PHPCI не може підключитися до MySQL із наданими параметрами. Будь ласка, спробуйте ще раз.', 'setting_up_db' => 'Налаштування вашої бази даних...', 'user_created' => 'Аккаунт користувача створено!', From 8a96ec85517caac25864a03306b1efb9d027a882 Mon Sep 17 00:00:00 2001 From: Mark Clements Date: Mon, 2 Mar 2015 22:49:22 +0000 Subject: [PATCH 06/57] Fixed the install script, which bails-out with an error if the PHPCI path contains spaces. This occurs commonly on Windows, but from my reading of the code it would also be a problem on other platforms if spaces were present (though this is less likely, due to different naming conventions). It has been fixed by using escapeshellarg() on both of the paths used in the command. Fixes #698, which I've just noticed has a similar solution suggested in one of the comments, but was closed without anyone actually implementing it. --- PHPCI/Command/InstallCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PHPCI/Command/InstallCommand.php b/PHPCI/Command/InstallCommand.php index 04e0f2dd..a50eefec 100644 --- a/PHPCI/Command/InstallCommand.php +++ b/PHPCI/Command/InstallCommand.php @@ -323,7 +323,9 @@ class InstallCommand extends Command { $output->write(Lang::get('setting_up_db')); - shell_exec(PHPCI_DIR . 'vendor/bin/phinx migrate -c "' . PHPCI_DIR . 'phinx.php"'); + $phinxBinary = escapeshellarg(PHPCI_DIR . 'vendor/bin/phinx'); + $phinxScript = escapeshellarg(PHPCI_DIR . 'phinx.php'); + shell_exec($phinxBinary . ' migrate -c ' . $phinxScript); $output->writeln(''.Lang::get('ok').''); } From e75ffe0b763d152438c493ee11341c3c360e45c2 Mon Sep 17 00:00:00 2001 From: corpsee Date: Tue, 10 Mar 2015 15:44:33 +0600 Subject: [PATCH 07/57] Fixed 'date' nl lang string --- PHPCI/Languages/lang.nl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PHPCI/Languages/lang.nl.php b/PHPCI/Languages/lang.nl.php index d62cd4e5..a4c95b6d 100644 --- a/PHPCI/Languages/lang.nl.php +++ b/PHPCI/Languages/lang.nl.php @@ -127,7 +127,7 @@ van je gekozen source code hosting platform', 'all_branches' => 'Alle brances', 'builds' => 'Builds', 'id' => 'ID', - 'date' => 'Date', + 'date' => 'Datum', 'project' => 'Project', 'commit' => 'Commit', 'branch' => 'Branch', From 9ad0e90fa19dc169bda65e1280c6aee41d223c8d Mon Sep 17 00:00:00 2001 From: Stephen Ball Date: Mon, 16 Mar 2015 11:05:33 +0000 Subject: [PATCH 08/57] Preventing the plugin failing due to an undefined variable --- PHPCI/Plugin/Wipe.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PHPCI/Plugin/Wipe.php b/PHPCI/Plugin/Wipe.php index 1a71e293..86e543b5 100644 --- a/PHPCI/Plugin/Wipe.php +++ b/PHPCI/Plugin/Wipe.php @@ -61,8 +61,8 @@ class Wipe implements \PHPCI\Plugin if (IS_WIN) { $cmd = 'rmdir /S /Q "%s"'; } - $success = $this->phpci->executeCommand($cmd, $this->directory); + return $this->phpci->executeCommand($cmd, $this->directory); } - return $success; + return true; } } From 1dd1af2443157e28860ab18708e2d9563960b1bb Mon Sep 17 00:00:00 2001 From: Mark Clements Date: Wed, 18 Mar 2015 09:47:47 +0000 Subject: [PATCH 09/57] Switching tabs to spaces as per style guide. No functional changes. --- PHPCI/Command/InstallCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PHPCI/Command/InstallCommand.php b/PHPCI/Command/InstallCommand.php index a50eefec..d10f34b7 100644 --- a/PHPCI/Command/InstallCommand.php +++ b/PHPCI/Command/InstallCommand.php @@ -323,8 +323,8 @@ class InstallCommand extends Command { $output->write(Lang::get('setting_up_db')); - $phinxBinary = escapeshellarg(PHPCI_DIR . 'vendor/bin/phinx'); - $phinxScript = escapeshellarg(PHPCI_DIR . 'phinx.php'); + $phinxBinary = escapeshellarg(PHPCI_DIR . 'vendor/bin/phinx'); + $phinxScript = escapeshellarg(PHPCI_DIR . 'phinx.php'); shell_exec($phinxBinary . ' migrate -c ' . $phinxScript); $output->writeln(''.Lang::get('ok').''); From 3467e77e7489112abef26c52537106b2c75b1559 Mon Sep 17 00:00:00 2001 From: Adirelle Date: Sun, 8 Mar 2015 17:57:16 +0100 Subject: [PATCH 10/57] Use a CSRF token on the login form to prevent CSRF attacks. --- PHPCI/Controller/SessionController.php | 46 +++++++++++++++++++++----- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/PHPCI/Controller/SessionController.php b/PHPCI/Controller/SessionController.php index 540b043f..8fa9d48b 100644 --- a/PHPCI/Controller/SessionController.php +++ b/PHPCI/Controller/SessionController.php @@ -43,15 +43,23 @@ class SessionController extends \PHPCI\Controller $isLoginFailure = false; if ($this->request->getMethod() == 'POST') { - $user = $this->userStore->getByEmail($this->getParam('email')); - if ($user && password_verify($this->getParam('password', ''), $user->getHash())) { - $_SESSION['phpci_user_id'] = $user->getId(); - $response = new b8\Http\Response\RedirectResponse(); - $response->setHeader('Location', $this->getLoginRedirect()); - return $response; - } else { + $token = $this->getParam('token'); + if ($token === null || $token !== $_SESSION['login_token']) { $isLoginFailure = true; + } else { + unset($_SESSION['login_token']); + + $user = $this->userStore->getByEmail($this->getParam('email')); + + if ($user && password_verify($this->getParam('password', ''), $user->getHash())) { + $_SESSION['phpci_user_id'] = $user->getId(); + $response = new b8\Http\Response\RedirectResponse(); + $response->setHeader('Location', $this->getLoginRedirect()); + return $response; + } else { + $isLoginFailure = true; + } } } @@ -78,9 +86,15 @@ class SessionController extends \PHPCI\Controller $pwd->setClass('btn-success'); $form->addField($pwd); + $tokenValue = $this->generateToken(); + $_SESSION['login_token'] = $tokenValue; + $token = new b8\Form\Element\Hidden('token'); + $token->setValue($tokenValue); + $form->addField($token); + $this->view->form = $form->render(); $this->view->failed = $isLoginFailure; - + return $this->view->render(); } @@ -180,4 +194,20 @@ class SessionController extends \PHPCI\Controller return $rtn; } + + /** Generate a random token. + * + * @return string + */ + protected function generateToken() + { + if(function_exists('openssl_random_pseudo_bytes')) { + return bin2hex(openssl_random_pseudo_bytes(16)); + } + + return sprintf("%04x", mt_rand(0, 0xFFFF)) + . sprintf("%04x", mt_rand(0, 0xFFFF)) + . sprintf("%04x", mt_rand(0, 0xFFFF)) + . sprintf("%04x", mt_rand(0, 0xFFFF)); + } } From f29ff197c62181d1d7918f7baa768d6d81f19fa4 Mon Sep 17 00:00:00 2001 From: Adirelle Date: Sun, 8 Mar 2015 17:53:27 +0100 Subject: [PATCH 11/57] Generate an new session identifier on successful login to prevent session fixation attacks. --- PHPCI/Controller/SessionController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/PHPCI/Controller/SessionController.php b/PHPCI/Controller/SessionController.php index 8fa9d48b..6ad2681e 100644 --- a/PHPCI/Controller/SessionController.php +++ b/PHPCI/Controller/SessionController.php @@ -53,6 +53,7 @@ class SessionController extends \PHPCI\Controller $user = $this->userStore->getByEmail($this->getParam('email')); if ($user && password_verify($this->getParam('password', ''), $user->getHash())) { + session_regenerate_id(true); $_SESSION['phpci_user_id'] = $user->getId(); $response = new b8\Http\Response\RedirectResponse(); $response->setHeader('Location', $this->getLoginRedirect()); From ea3b0c219afb0ba0e5bc09c4ab21d5990c593323 Mon Sep 17 00:00:00 2001 From: Adirelle Date: Tue, 10 Mar 2015 21:29:10 +0100 Subject: [PATCH 12/57] Code style fixed. --- PHPCI/Controller/SessionController.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/PHPCI/Controller/SessionController.php b/PHPCI/Controller/SessionController.php index 6ad2681e..eb7001df 100644 --- a/PHPCI/Controller/SessionController.php +++ b/PHPCI/Controller/SessionController.php @@ -43,7 +43,6 @@ class SessionController extends \PHPCI\Controller $isLoginFailure = false; if ($this->request->getMethod() == 'POST') { - $token = $this->getParam('token'); if ($token === null || $token !== $_SESSION['login_token']) { $isLoginFailure = true; @@ -202,7 +201,7 @@ class SessionController extends \PHPCI\Controller */ protected function generateToken() { - if(function_exists('openssl_random_pseudo_bytes')) { + if (function_exists('openssl_random_pseudo_bytes')) { return bin2hex(openssl_random_pseudo_bytes(16)); } From d8df6cab4a6311df1e4803364c9af0e5f73e47ff Mon Sep 17 00:00:00 2001 From: LAHAXE Arnaud Date: Tue, 17 Mar 2015 15:49:52 +0100 Subject: [PATCH 13/57] Fix french typo mistake --- PHPCI/Languages/lang.fr.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PHPCI/Languages/lang.fr.php b/PHPCI/Languages/lang.fr.php index 7d438d2f..da2e35b4 100644 --- a/PHPCI/Languages/lang.fr.php +++ b/PHPCI/Languages/lang.fr.php @@ -264,7 +264,7 @@ PHPCI', // Plugins 'cannot_update_composer' => 'PHPCI ne peut pas mettre à jour le fichier composer.json pour vous, il n\'est pas modifiable.', 'x_has_been_removed' => '%s a été supprimé.', - 'x_has_been_added' => '%s a été ajouté au fichier composer.json poru vous et il sera installé la prochaine fois + 'x_has_been_added' => '%s a été ajouté au fichier composer.json pour vous et il sera installé la prochaine fois que vous lancerez "composer update".', 'enabled_plugins' => 'Plugins activés', 'provided_by_package' => 'Fournis par le paquet', From 3a867eb9d56117ff9195cf34b60ff68621fa4893 Mon Sep 17 00:00:00 2001 From: corpsee Date: Mon, 16 Mar 2015 12:43:01 +0600 Subject: [PATCH 14/57] Fixed 'start' string for ru lang Fixed 'from' and 'to' strings for ru lang --- PHPCI/Languages/lang.ru.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PHPCI/Languages/lang.ru.php b/PHPCI/Languages/lang.ru.php index 422f17e1..ed5a8eeb 100644 --- a/PHPCI/Languages/lang.ru.php +++ b/PHPCI/Languages/lang.ru.php @@ -188,10 +188,10 @@ PHPCI', 'class' => 'Класс', 'method' => 'Метод', 'message' => 'Сообщение', - 'start' => 'Запуск', + 'start' => 'Начало', 'end' => 'Конец', - 'from' => 'От', - 'to' => 'До', + 'from' => 'Из', + 'to' => 'В', 'suite' => 'Комплект', 'test' => 'Тест', 'result' => 'Результат', From d804438a8785760987c6c8ae9811217d136fb246 Mon Sep 17 00:00:00 2001 From: Adirelle Date: Thu, 26 Feb 2015 15:57:45 +0100 Subject: [PATCH 15/57] Use sensiolabs/ansi-to-html to parse the build logs. Added an AnsiConverter helper. Use the AnsiConverter in the email and page templates that display the build log. Use a dedicated stylesheet for the ANSI converter. It can be customized. It can be inlined in the notifications. Do not use ProphecyTestCase when not needed. --- PHPCI/Controller/BuildController.php | 7 +-- PHPCI/Helper/AnsiConverter.php | 55 ++++++++++++++++++++++++ PHPCI/View/Email/success.phtml | 4 +- PHPCI/View/layout.phtml | 1 + Tests/PHPCI/Helper/AnsiConverterTest.php | 20 +++++++++ composer.json | 3 +- composer.lock | 47 +++++++++++++++++++- public/assets/css/ansi-colors.css | 32 ++++++++++++++ public/assets/js/build-plugins/log.js | 2 +- 9 files changed, 162 insertions(+), 9 deletions(-) create mode 100644 PHPCI/Helper/AnsiConverter.php create mode 100644 Tests/PHPCI/Helper/AnsiConverterTest.php create mode 100644 public/assets/css/ansi-colors.css diff --git a/PHPCI/Controller/BuildController.php b/PHPCI/Controller/BuildController.php index bf898d2d..e4660ba7 100644 --- a/PHPCI/Controller/BuildController.php +++ b/PHPCI/Controller/BuildController.php @@ -13,6 +13,7 @@ use b8; use b8\Exception\HttpException\NotFoundException; use b8\Http\Response\JsonResponse; use PHPCI\BuildFactory; +use PHPCI\Helper\AnsiConverter; use PHPCI\Helper\Lang; use PHPCI\Model\Build; use PHPCI\Model\Project; @@ -198,11 +199,7 @@ class BuildController extends \PHPCI\Controller */ protected function cleanLog($log) { - $log = str_replace('[0;32m', '', $log); - $log = str_replace('[0;31m', '', $log); - $log = str_replace('[0m', '', $log); - - return $log; + return AnsiConverter::convert($log); } /** diff --git a/PHPCI/Helper/AnsiConverter.php b/PHPCI/Helper/AnsiConverter.php new file mode 100644 index 00000000..a5e42269 --- /dev/null +++ b/PHPCI/Helper/AnsiConverter.php @@ -0,0 +1,55 @@ +convert($text); + } + + /** + * Do not instanciate this class. + */ + private function __construct() + { + } +} diff --git a/PHPCI/View/Email/success.phtml b/PHPCI/View/Email/success.phtml index a3a604c5..342e3483 100644 --- a/PHPCI/View/Email/success.phtml +++ b/PHPCI/View/Email/success.phtml @@ -1,3 +1,5 @@ + +
@@ -8,7 +10,7 @@

Your commit getCommitId(); ?> genrate a successfull build in project getTitle(); ?>.

getCommitMessage(); ?>

-
getLog(); ?>
+
getLog()); ?>

You can review your commit and the build log.

diff --git a/PHPCI/View/layout.phtml b/PHPCI/View/layout.phtml index 33290fb3..72ef27ff 100644 --- a/PHPCI/View/layout.phtml +++ b/PHPCI/View/layout.phtml @@ -13,6 +13,7 @@ + diff --git a/Tests/PHPCI/Helper/AnsiConverterTest.php b/Tests/PHPCI/Helper/AnsiConverterTest.php new file mode 100644 index 00000000..4d1e8522 --- /dev/null +++ b/Tests/PHPCI/Helper/AnsiConverterTest.php @@ -0,0 +1,20 @@ +This is red !'; + + $actualOutput = AnsiConverter::convert($input); + + $this->assertEquals($expectedOutput, $actualOutput); + } +} diff --git a/composer.json b/composer.json index 2eec5e30..6658bffd 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,8 @@ "psr/log": "~1.0", "monolog/monolog": "~1.6", "pimple/pimple": "~1.1", - "robmorgan/phinx": "~0.4" + "robmorgan/phinx": "~0.4", + "sensiolabs/ansi-to-html": "~1.1" }, "require-dev": { diff --git a/composer.lock b/composer.lock index c5abc102..56c28655 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "4ae188c6be1c1388de6271a3b0e0475d", + "hash": "5fc23800ea77b50b496d34f7aa5cf6b3", "packages": [ { "name": "block8/b8framework", @@ -315,6 +315,50 @@ ], "time": "2015-02-23 16:38:12" }, + { + "name": "sensiolabs/ansi-to-html", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/sensiolabs/ansi-to-html.git", + "reference": "92d2ef7ffba5418be060d8ba8adaf7223d741f93" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sensiolabs/ansi-to-html/zipball/92d2ef7ffba5418be060d8ba8adaf7223d741f93", + "reference": "92d2ef7ffba5418be060d8ba8adaf7223d741f93", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "suggest": { + "twig/twig": "Provides nice templating features" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-0": { + "SensioLabs\\AnsiConverter": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "A library to convert a text with ANSI codes to HTML", + "time": "2014-08-01 14:02:39" + }, { "name": "swiftmailer/swiftmailer", "version": "v5.3.1", @@ -2030,6 +2074,7 @@ "minimum-stability": "stable", "stability-flags": [], "prefer-stable": false, + "prefer-lowest": false, "platform": { "php": ">=5.3.8", "ext-pdo": "*", diff --git a/public/assets/css/ansi-colors.css b/public/assets/css/ansi-colors.css new file mode 100644 index 00000000..c3011299 --- /dev/null +++ b/public/assets/css/ansi-colors.css @@ -0,0 +1,32 @@ +.ansi_color_fg_black { color: black } +.ansi_color_bg_black { background-color: black } +.ansi_color_fg_red { color: darkred } +.ansi_color_bg_red { background-color: darkred } +.ansi_color_fg_green { color: green } +.ansi_color_bg_green { background-color: green } +.ansi_color_fg_yellow { color: yellow } +.ansi_color_bg_yellow { background-color: yellow } +.ansi_color_fg_blue { color: blue } +.ansi_color_bg_blue { background-color: blue } +.ansi_color_fg_magenta { color: darkmagenta } +.ansi_color_bg_magenta { background-color: darkmagenta } +.ansi_color_fg_cyan { color: cyan } +.ansi_color_bg_cyan { background-color: cyan } +.ansi_color_fg_white { color: white } +.ansi_color_bg_white { background-color: white } +.ansi_color_fg_brblack { color: black } +.ansi_color_bg_brblack { background-color: black } +.ansi_color_fg_brred { color: red } +.ansi_color_bg_brred { background-color: red } +.ansi_color_fg_brgreen { color: lightgreen } +.ansi_color_bg_brgreen { background-color: lightgreen } +.ansi_color_fg_bryellow { color: lightyellow } +.ansi_color_bg_bryellow { background-color: lightyellow } +.ansi_color_fg_brblue { color: lightblue } +.ansi_color_bg_brblue { background-color: lightblue } +.ansi_color_fg_brmagenta { color: magenta } +.ansi_color_bg_brmagenta { background-color: magenta } +.ansi_color_fg_brcyan { color: lightcyan } +.ansi_color_bg_brcyan { background-color: lightcyan } +.ansi_color_fg_brwhite { color: white } +.ansi_color_bg_brwhite { background-color: white } diff --git a/public/assets/js/build-plugins/log.js b/public/assets/js/build-plugins/log.js index 8798e23c..44ebab2b 100644 --- a/public/assets/js/build-plugins/log.js +++ b/public/assets/js/build-plugins/log.js @@ -8,7 +8,7 @@ var logPlugin = ActiveBuild.UiPlugin.extend({ }, render: function() { - var container = $('
');
+        var container = $('
');
         container.css({height: '300px', 'overflow-y': 'auto'});
         container.html(ActiveBuild.buildData.log);
 

From 2c43cd1cace4dbb9c25142dedc977d7507134018 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolpla=C3=A1s?= 
Date: Sun, 1 Mar 2015 19:56:16 -0200
Subject: [PATCH 16/57] Add spanish laguage support

---
 PHPCI/Languages/lang.es.php | 385 ++++++++++++++++++++++++++++++++++++
 1 file changed, 385 insertions(+)
 create mode 100644 PHPCI/Languages/lang.es.php

diff --git a/PHPCI/Languages/lang.es.php b/PHPCI/Languages/lang.es.php
new file mode 100644
index 00000000..7c9f5a62
--- /dev/null
+++ b/PHPCI/Languages/lang.es.php
@@ -0,0 +1,385 @@
+ 'Español',
+    'language' => 'Lenguaje',
+
+    // Log in:
+    'log_in_to_phpci' => 'Ingresar a PHPCI',
+    'login_error' => 'Email o contraseña incorrectos',
+    'forgotten_password_link' => '¿Olvidaste tu contraseña?',
+    'reset_emailed' => 'Te hemos enviado un email para reiniciar tu contraseña.',
+    'reset_header' => '¡No te preocupes!
Solo tienes que ingresar tu dirección de email + y te enviaremos por email un enlace para reiniciar tu contraseña.', + 'reset_email_address' => 'Ingresa tu dirección de email:', + 'reset_send_email' => 'Enviar enlace', + 'reset_enter_password' => 'Ingresa una nueva contraseña', + 'reset_new_password' => 'Nueva contraseña:', + 'reset_change_password' => 'Cambiar contraseña', + 'reset_no_user_exists' => 'No existe ningún usuario con ese email, por favor intenta nuevamente.', + 'reset_email_body' => 'Hola %s, + +Has recibido este correo porque tú, o alguien más, ha solicitado reiniciar la contraseña de PHPCI + +Si fuiste tú, por favor haz click en el siguiente enlace para reiniciar tu contraseña: %ssession/reset-password/%d/%s + +De lo contrario, por favor ignora este correo y ninguna acción será realizada. + +Gracias, + +PHPCI', + + 'reset_email_title' => 'Reiniciar contraseña de PHPCI para %s', + 'reset_invalid' => 'Pedido inválido.', + 'email_address' => 'Dirección de email', + 'password' => 'Contraseña', + 'log_in' => 'Ingresar', + + + // Top Nav + 'toggle_navigation' => 'Activar navegación', + 'n_builds_pending' => '%d builds pendientes', + 'n_builds_running' => '%d builds ejecutándose', + 'edit_profile' => 'Editar Perfil', + 'sign_out' => 'Cerrar Sesión', + 'branch_x' => 'Rama: %s', + 'created_x' => 'Creada el: %s', + 'started_x' => 'Comenzó: %s', + + // Sidebar + 'hello_name' => 'Hola, %s', + 'dashboard' => 'Escritorio', + 'admin_options' => 'Opciones de Admin.', + 'add_project' => 'Agregar Proyecto', + 'settings' => 'Configuración', + 'manage_users' => 'Administrar Usuarios', + 'plugins' => 'Plugins', + 'view' => 'Vista', + 'build_now' => 'Ejecutar Build', + 'edit_project' => 'Editar Proyecto', + 'delete_project' => 'Eliminar Proyecto', + + // Project Summary: + 'no_builds_yet' => '¡No existen builds aún!', + 'x_of_x_failed' => '%d de los últimos %d builds fallaron.', + 'x_of_x_failed_short' => '%d / %d fallaron.', + 'last_successful_build' => ' El último build exitoso fue %s.', + 'never_built_successfully' => ' Este proyecto nunca tuvo un build exitoso.', + 'all_builds_passed' => 'Todos los últimos %d builds pasaron.', + 'all_builds_passed_short' => '%d / %d pasaron.', + 'last_failed_build' => ' El último build en fallar fue %s.', + 'never_failed_build' => ' Este proyecto no tiene ningún build fallido.', + 'view_project' => 'Ver Proyecto', + + // Timeline: + 'latest_builds' => 'Últimos builds', + 'pending' => 'Pediente', + 'running' => 'Ejecutando', + 'success' => 'Éxito', + 'successful' => 'Exitoso', + 'failed' => 'Falló', + 'manual_build' => 'Build Manual', + + // Add/Edit Project: + 'new_project' => 'Nuevo Proyecto', + 'project_x_not_found' => 'El Proyecto con ID %d no existe.', + 'project_details' => 'Detalles del Proyecto', + 'public_key_help' => 'Para facilitarte, hemos generado un par de llaves SSH para que uses en este proyecto. + Para usarlo, sólo agrega la siguiente llave pública a la sección de "deploy keys" + de tu plataforma de hosting de versionado de código.', + 'select_repository_type' => 'Selecciona tipo de repositorio...', + 'github' => 'GitHub', + 'bitbucket' => 'Bitbucket', + 'gitlab' => 'GitLab', + 'remote' => 'URL Remota', + 'local' => 'Path local', + 'hg' => 'Mercurial', + 'svn' => 'Subversion', + + 'where_hosted' => '¿Dónde está alojado tu proyecto?', + 'choose_github' => 'Selecciona un repositorio de GitHub:', + + 'repo_name' => 'Nombre del repositorio / URL (Remoto) o Ruta (Local)', + 'project_title' => 'Titulo del proyecto', + 'project_private_key' => 'Clave privada a usar para acceder al repositorio + (dejar en blanco para remotos locales o anónimos)', + 'build_config' => 'Configuración PHPCI para builds del proyecto + (en caso que no puedas agregar el archivo phpci.yml al repositorio)', + 'default_branch' => 'Nombre de la rama por defecto', + 'allow_public_status' => '¿Activar página pública con el estado del proyecto?', + 'save_project' => 'Guardar Proyecto', + + 'error_mercurial' => 'La URL del repositorio de Mercurial debe comenzar con http:// or https://', + 'error_remote' => 'La URL del repositorio debe comenzar con git://, http:// or https://', + 'error_gitlab' => 'El nombre del repositorio de GitLab debe tener el formato "user@domain.tld:owner/repo.git"', + 'error_github' => 'El nombre del repositorio debe tener el formato "owner/repo"', + 'error_bitbucket' => 'El nombre del repo debe tener el formato "owner/repo"', + 'error_path' => 'La ruta especificada no existe.', + + // View Project: + 'all_branches' => 'Todas las ramas', + 'builds' => 'Builds', + 'id' => 'ID', + 'project' => 'Proyecto', + 'commit' => 'Commit', + 'branch' => 'Rama', + 'status' => 'Estado', + 'prev_link' => '« Anterior', + 'next_link' => 'Siguiente »', + 'public_key' => 'Llave pública', + 'delete_build' => 'Eliminar Build', + + 'webhooks' => 'Webhooks', + 'webhooks_help_github' => 'Para compilar automáticamente este proyecto cada vez que se realiza un commit, agreagar la siguiente URL + como un nuevo "webhook" en la sección Webhooks + and Services de tu repositorio en GitHub.', + + 'webhooks_help_gitlab' => 'Para compilar automáticamente este proyecto, cada vez que se realiza un commit, agreagar la siguiente URL + como una "WebHook URL" en la sección "web hooks" de tu repositorio en GitLab.', + + 'webhooks_help_bitbucket' => 'Para compilar automáticamente este proyecto, cada vez que se realiza un commit, agreagar la siguiente URL + como un servicio "POST" en la sección + + Services de tu repositorio en Bitbucket.', + + // View Build + 'build_x_not_found' => 'El build con ID %d no existe.', + 'build_n' => 'Build %d', + 'rebuild_now' => 'Rebuild Ahora', + + + 'committed_by_x' => 'Commit hecho por %s', + 'commit_id_x' => 'Commit: %s', + + 'chart_display' => 'Este gráfico será mostrado una vez que el build se haya completado.', + + 'build' => 'Build', + 'lines' => 'Líneas', + 'comment_lines' => 'Líneas de comentario', + 'noncomment_lines' => 'Líneas no comentario', + 'logical_lines' => 'Líneas lógicas', + 'lines_of_code' => 'Líneas de código', + 'build_log' => 'Log', + 'quality_trend' => 'Tendencia de calidad', + 'codeception_errors' => 'Errores de Codeception', + 'phpmd_warnings' => 'PHPMD Warnings', + 'phpcs_warnings' => 'PHPCS Warnings', + 'phpcs_errors' => 'PHPCS Errors', + 'phplint_errors' => 'Lint Errors', + 'phpunit_errors' => 'PHPUnit Errors', + 'phpdoccheck_warnings' => 'Docblocks faltantes', + 'issues' => 'Incidencias', + + 'codeception' => 'Codeception', + 'phpcpd' => 'PHP Copy/Paste Detector', + 'phpcs' => 'PHP Code Sniffer', + 'phpdoccheck' => 'Missing Docblocks', + 'phpmd' => 'PHP Mess Detector', + 'phpspec' => 'PHP Spec', + 'phpunit' => 'PHP Unit', + 'technical_debt' => 'Deuda Técnica', + 'behat' => 'Behat', + + 'file' => 'Archivo', + 'line' => 'Línea', + 'class' => 'Clase', + 'method' => 'Método', + 'message' => 'Mensaje', + 'start' => 'Inicio', + 'end' => 'Fin', + 'from' => 'De', + 'to' => 'Para', + 'suite' => 'Suite', + 'test' => 'Test', + 'result' => 'Resultado', + 'ok' => 'OK', + 'took_n_seconds' => 'Tomó %d segundos', + 'build_created' => 'Build Creado', + 'build_started' => 'Build Comenzado', + 'build_finished' => 'Build Terminado', + + // Users + 'name' => 'Nombre', + 'password_change' => 'Contraseña (dejar en blanco si no quiere cambiarla)', + 'save' => 'Guardar »', + 'update_your_details' => 'Actualizar los detalles', + 'your_details_updated' => 'Tus detalles han sido actualizados.', + 'add_user' => 'Agregar Usuario', + 'is_admin' => '¿Es Admin?', + 'yes' => 'Si', + 'no' => 'No', + 'edit' => 'Editar', + 'edit_user' => 'Editar Usuario', + 'delete_user' => 'Delete Usuario', + 'user_n_not_found' => 'Usuario con ID %d no existe.', + 'is_user_admin' => '¿Es un usuario administrador?', + 'save_user' => 'Guardar Usuario', + + // Settings: + 'settings_saved' => 'Tu configuración ha sido guardada.', + 'settings_check_perms' => 'Tu configuración no fue guardada, verificar los permisos del archivo config.yml.', + 'settings_cannot_write' => 'PHPCI no puede escribir en el archivo config.yml file, la configuración no será guardada correctamente + hasta no corregir esto.', + 'settings_github_linked' => 'Tu cuenta GitHub ha sido conectada.', + 'settings_github_not_linked' => 'No se pudo conectar a tu cuenta GitHub.', + 'build_settings' => 'Configuración del Build ', + 'github_application' => 'Aplicación GitHub', + 'github_sign_in' => 'Antes de comenzar a utilizar GitHub, tienes que ingresar y permitir + el acceso a tu cuenta a PHPCI.', + 'github_phpci_linked' => 'PHPCI ha sido conectado a tu cuenta GitHub.', + 'github_where_to_find' => 'Donde encontrar estos...', + 'github_where_help' => 'Si eres priopietario de la aplicaión que quieres usar, puedes encontrar esta información en + el área de configuración de aplicaciones.', + + 'email_settings' => 'Configuraciones de Email', + 'email_settings_help' => 'Para que PHPCI pueda enviar email con el status de los builds, + debes configurar las siguientes propiedades SMTP.', + + 'application_id' => 'ID de aplicación', + 'application_secret' => 'Application Secret', + + 'smtp_server' => 'Servidor SMTP', + 'smtp_port' => 'Puerto SMTP', + 'smtp_username' => 'Usuario SMTP', + 'smtp_password' => 'Contraseña SMTP', + 'from_email_address' => 'Dirección de email DE', + 'default_notification_address' => 'Dirección de correo de notificación por defecto', + 'use_smtp_encryption' => 'Usar encriptación SMTP?', + 'none' => 'None', + 'ssl' => 'SSL', + 'tls' => 'TLS', + + 'failed_after' => 'Considerar el build como fallido luego de ', + '5_mins' => '5 Minutos', + '15_mins' => '15 Minutos', + '30_mins' => '30 Minutos', + '1_hour' => '1 Hora', + '3_hours' => '3 Horas', + + // Plugins + 'cannot_update_composer' => 'PHPCI no puede actualizar composer.json porque no tiene permisos de escritura.', + 'x_has_been_removed' => '%s ha sido elimiando.', + 'x_has_been_added' => '%s ha sido agregado a composer.json y será instalado la próxima vez que ejecutes composer update.', + 'enabled_plugins' => 'Activar Plugins', + 'provided_by_package' => 'Provisto por Paquete', + 'installed_packages' => 'Paquetes Instalados', + 'suggested_packages' => 'Paquetes Sugeridos', + 'title' => 'Título', + 'description' => 'Descripción', + 'version' => 'Versión', + 'install' => 'Instalar »', + 'remove' => 'Eliminar »', + 'search_packagist_for_more' => 'Buscar más paquetes en Packagist', + 'search' => 'Buscar »', + + // Installer + 'installation_url' => 'URL de la instalación PHPCI', + 'db_host' => 'Host', + 'db_name' => 'Nombre de la base de datos', + 'db_user' => 'Usuario de la base de datos', + 'db_pass' => 'Clave de la base de datos', + 'admin_name' => 'Nombre del Admin', + 'admin_pass' => 'Clave del Admin', + 'admin_email' => 'Email de Admin', + 'config_path' => 'Ruta al archivo config', + 'install_phpci' => 'Instalar PHPCI', + 'welcome_to_phpci' => 'Bienvenido a PHPCI', + 'please_answer' => 'Por favor, responde las siguientes preguntas:', + 'phpci_php_req' => 'PHPCI requiere al menos PHP 5.3.8 para funcionar.', + 'extension_required' => 'Extensión requerida: %s', + 'function_required' => 'PHPCI debe poder invocar la función %s(). Está deshabilitada en php.ini?', + 'requirements_not_met' => 'PHPCI no pudo ser instalado, ya que no se cumplen todos los requerimientos. + Por favor, corrige los errores antes de continuar.', + 'must_be_valid_email' => 'Debe ser una dirección de correos válida.', + 'must_be_valid_url' => 'Debe ser una URL válida.', + 'enter_name' => 'Nombre del Admin:', + 'enter_email' => 'Email del Admin:', + 'enter_password' => 'Contraseña de Admin:', + 'enter_phpci_url' => 'La URL de PHPCI ("Por ejemplo: http://phpci.local"): ', + + 'enter_db_host' => 'Por favor, ingresa el servidor MySQL [localhost]: ', + 'enter_db_name' => 'Por favor, ingresa el nombre de la base de datos MySQL [phpci]: ', + 'enter_db_user' => 'Por favor, ingresa el usuario MySQL [phpci]: ', + 'enter_db_pass' => 'Por favor, ingresa la contraseña MySQL: ', + 'could_not_connect' => 'PHPCI no pudo conectarse a MySQL con los datos dados. Por favor, intenta nuevamente.', + 'setting_up_db' => 'Configurando base de datos... ', + 'user_created' => '¡Cuenta de usuario creada!', + 'failed_to_create' => 'PHPCI no pudo crear la cuenta de admin.', + 'config_exists' => 'El archivo config de PHPCI ya existe y no es vacío.', + 'update_instead' => 'Si está intentando actualizar PHPCI, por favor, utiliza phpci:update.', + + // Update + 'update_phpci' => 'Actuliza la base de datos para reflejar los modelos actualizados.', + 'updating_phpci' => 'Actualizando base de datos PHPCI: ', + 'not_installed' => 'PHPCI no está instalado.', + 'install_instead' => 'Por favor, instala PHPCI via phpci:install.', + + // Poll Command + 'poll_github' => 'Chequear en GitHub si se necesita comenzar un Build.', + 'no_token' => 'No se encontró ningún token GitHub', + 'finding_projects' => 'Buscando proyectos para chequear', + 'found_n_projects' => 'Se encontraron %d proyectos', + 'last_commit_is' => 'El último commit en GitHub para %s es %s', + 'adding_new_build' => 'Último commit es diferente a la base de datos, agregando nuevo build.', + 'finished_processing_builds' => 'Fin de procesamiento de builds.', + + // Create Admin + 'create_admin_user' => 'Crear un usuario Admin', + 'incorrect_format' => 'Formato incorrecto', + + // Run Command + 'run_all_pending' => 'Ejecutar todos los builds PHPCI pendientes.', + 'finding_builds' => 'Buscando builds a procesar', + 'found_n_builds' => 'Se encontraron %d builds', + 'skipping_build' => 'Saltando Build %d - Build del proyecto ya en ejecución.', + 'marked_as_failed' => 'Build %d falló debido a timeout.', + + // Builder + 'missing_phpci_yml' => 'Este proyecto no contiene el archivo phpci.yml o está vacío.', + 'build_success' => 'BUILD EXITOSO', + 'build_failed' => 'BUILD FALLIDO', + 'removing_build' => 'Eliminando Build.', + 'exception' => 'Excepción: ', + 'could_not_create_working' => 'Imposible crear copia de trabajo.', + 'working_copy_created' => 'Copia de trabajo creada: %s', + 'looking_for_binary' => 'Buscando binario: %s', + 'found_in_path' => 'Encontrado en %s: %s', + 'running_plugin' => 'EJECUTANDO PLUGIN: %s', + 'plugin_success' => 'PLUGIN: EXITO', + 'plugin_failed' => 'PLUGIN: FALLÓ', + 'plugin_missing' => 'No existe el plugin: %s', + 'tap_version' => 'TapParser únicamente soporta la verisón 13 de TAP', + 'tap_error' => 'Cadena de caracteres TAP inválida, el número de tests no coincide con la cuenta de tests declarada.', + + // Build Plugins: + 'no_tests_performed' => 'No se ejecutaron tests.', + 'could_not_find' => 'No se encontró %s', + 'no_campfire_settings' => 'No se especificaron parámetros de conexión para el plugin Campfire', + 'failed_to_wipe' => 'Imposible eliminar directorio existente %s antes de copiarlo', + 'passing_build' => 'Build Exitoso', + 'failing_build' => 'Build Fallido', + 'log_output' => 'Log de Salida: ', + 'n_emails_sent' => '%d emails enviados.', + 'n_emails_failed' => '%d emails no pudieron ser enviados.', + 'unable_to_set_env' => 'Imposible setear variable de entorno', + 'tag_created' => 'Tag creado por PHPCI: %s', + 'x_built_at_x' => 'Build de %PROJECT_TITLE% en %BUILD_URI%', + 'hipchat_settings' => 'Por favor, definir room y authToken para el plugin hipchat_notify', + 'irc_settings' => 'Debes configurar un servidor, room y apodo.', + 'invalid_command' => 'Comando inválido', + 'import_file_key' => 'Sentencia de importación debe contener una llave \'file\'', + 'cannot_open_import' => 'Imposible abrir archivo de importación SQL: %s', + 'unable_to_execute' => 'Imposible ejecutar archivo SQL', + 'phar_internal_error' => 'Error interno en plugin Phar', + 'build_file_missing' => 'El archivo de build especificado no existe.', + 'property_file_missing' => 'El archivo de propiedades especificado no existe.', + 'could_not_process_report' => 'Imposible procesar el reporte generado por la herramienta.', + 'shell_not_enabled' => 'El plugin shell no está habilitado. Por favor, habilitalo desde config.yml.' +); From 9d4116e3c95e782e127de4a24121af29480b1775 Mon Sep 17 00:00:00 2001 From: Adirelle Date: Tue, 3 Mar 2015 20:10:55 +0100 Subject: [PATCH 17/57] Reworked TapParser to be compliant and more robust. Added another test case from #571. Updated the output of TapParser::processTestLine. Broke TapParser::parse down in simpler methods. TapParser: ignore leading garbage and properly complain on missing TAP log. TapParser: detect and report duplicated TAP log. TapParser: got rid of the "test" and "suite" values. They are only available with PHPUnit. TapParser: append the message from yaml diagnostic to existing message. Reworked the dispaly of test results. PHPUnit plugin: pretty print test data. --- PHPCI/Languages/lang.da.php | 10 +- PHPCI/Languages/lang.de.php | 10 +- PHPCI/Languages/lang.el.php | 10 +- PHPCI/Languages/lang.en.php | 10 +- PHPCI/Languages/lang.fr.php | 10 +- PHPCI/Languages/lang.it.php | 10 +- PHPCI/Languages/lang.nl.php | 10 +- PHPCI/Languages/lang.pl.php | 10 +- PHPCI/Languages/lang.ru.php | 10 +- PHPCI/Languages/lang.uk.php | 10 +- PHPCI/Plugin/Util/TapParser.php | 249 ++++++++++++++++------ Tests/PHPCI/Plugin/Util/TapParserTest.php | 240 ++++++++++++++++++++- public/assets/css/AdminLTE-custom.css | 9 +- public/assets/js/build-plugins/phpunit.js | 94 ++++++-- 14 files changed, 587 insertions(+), 105 deletions(-) diff --git a/PHPCI/Languages/lang.da.php b/PHPCI/Languages/lang.da.php index 4e61c3db..883e52b0 100644 --- a/PHPCI/Languages/lang.da.php +++ b/PHPCI/Languages/lang.da.php @@ -194,14 +194,20 @@ Services sektionen under dit Bitbucket-repository.', 'end' => 'Slut', 'from' => 'Fra', 'to' => 'Til', - 'suite' => 'Suite', - 'test' => 'Test', 'result' => 'Resultat', 'ok' => 'OK', 'took_n_seconds' => 'Tog %d sekunder', 'build_created' => 'Build Oprettet', 'build_started' => 'Build Startet', 'build_finished' => 'Build Afsluttet', + 'test_message' => 'Message', + 'test_no_message' => 'No message', + 'test_success' => 'Succesfull: %d', + 'test_fail' => 'Failures: %d', + 'test_skipped' => 'Skipped: %d', + 'test_error' => 'Errors: %d', + 'test_todo' => 'Todos: %d', + 'test_total' => '%d test(s)', // Users 'name' => 'Navn', diff --git a/PHPCI/Languages/lang.de.php b/PHPCI/Languages/lang.de.php index a04e40e1..62504310 100644 --- a/PHPCI/Languages/lang.de.php +++ b/PHPCI/Languages/lang.de.php @@ -192,14 +192,20 @@ generiert. Um es zu verwenden, fügen Sie einfach den folgenden Public Key im Ab 'end' => 'Ende', 'from' => 'Von', 'to' => 'Bis', - 'suite' => 'Suite', - 'test' => 'Test', 'result' => 'Resultat', 'ok' => 'OK', 'took_n_seconds' => 'Benötigte %d Sekunden', 'build_created' => 'Build erstellt', 'build_started' => 'Build gestartet', 'build_finished' => 'Build abgeschlossen', + 'test_message' => 'Message', + 'test_no_message' => 'No message', + 'test_success' => 'Succesfull: %d', + 'test_fail' => 'Failures: %d', + 'test_skipped' => 'Skipped: %d', + 'test_error' => 'Errors: %d', + 'test_todo' => 'Todos: %d', + 'test_total' => '%d test(s)', // Users 'name' => 'Name', diff --git a/PHPCI/Languages/lang.el.php b/PHPCI/Languages/lang.el.php index 4b1e82ca..5afc6593 100644 --- a/PHPCI/Languages/lang.el.php +++ b/PHPCI/Languages/lang.el.php @@ -194,14 +194,20 @@ Services του Bitbucket αποθετηρίου σας.', 'end' => 'Τέλος', 'from' => 'Από', 'to' => 'Προς', - 'suite' => 'Σουίτα', - 'test' => 'Τέστ', 'result' => 'Αποτέλεσμα', 'ok' => 'ΟΚ', 'took_n_seconds' => 'Χρειάστηκαν %d δευτερόλεπτα', 'build_created' => 'Η κατασκευή δημιουργήθηκε', 'build_started' => 'Η κατασκευή άρχισε', 'build_finished' => 'Η κατασκευή ολοκληρώθηκε', + 'test_message' => 'Message', + 'test_no_message' => 'No message', + 'test_success' => 'Succesfull: %d', + 'test_fail' => 'Failures: %d', + 'test_skipped' => 'Skipped: %d', + 'test_error' => 'Errors: %d', + 'test_todo' => 'Todos: %d', + 'test_total' => '%d test(s)', // Users 'name' => 'Όνομα', diff --git a/PHPCI/Languages/lang.en.php b/PHPCI/Languages/lang.en.php index b23eff7b..393ef584 100644 --- a/PHPCI/Languages/lang.en.php +++ b/PHPCI/Languages/lang.en.php @@ -198,14 +198,20 @@ PHPCI', 'end' => 'End', 'from' => 'From', 'to' => 'To', - 'suite' => 'Suite', - 'test' => 'Test', 'result' => 'Result', 'ok' => 'OK', 'took_n_seconds' => 'Took %d seconds', 'build_created' => 'Build Created', 'build_started' => 'Build Started', 'build_finished' => 'Build Finished', + 'test_message' => 'Message', + 'test_no_message' => 'No message', + 'test_success' => 'Succesfull: %d', + 'test_fail' => 'Failures: %d', + 'test_skipped' => 'Skipped: %d', + 'test_error' => 'Errors: %d', + 'test_todo' => 'Todos: %d', + 'test_total' => '%d test(s)', // Users 'name' => 'Name', diff --git a/PHPCI/Languages/lang.fr.php b/PHPCI/Languages/lang.fr.php index 7be361fc..6965cb06 100644 --- a/PHPCI/Languages/lang.fr.php +++ b/PHPCI/Languages/lang.fr.php @@ -195,14 +195,20 @@ PHPCI', 'end' => 'Fin', 'from' => 'À partir de', 'to' => 'jusque', - 'suite' => 'Suite', - 'test' => 'Test', 'result' => 'Resultat', 'ok' => 'OK', 'took_n_seconds' => 'Exécuté en %d secondes', 'build_created' => 'Build créé', 'build_started' => 'Build démarré', 'build_finished' => 'Build terminé', + 'test_message' => 'Message', + 'test_no_message' => 'Pas de message', + 'test_success' => 'Réussi(s): %d', + 'test_fail' => 'Echec(s): %d', + 'test_skipped' => 'Passé(s): %d', + 'test_error' => 'Erreurs: %d', + 'test_todo' => 'Todos: %d', + 'test_total' => '%d test(s)', // Users 'name' => 'Nom', diff --git a/PHPCI/Languages/lang.it.php b/PHPCI/Languages/lang.it.php index a8a3e13c..db6b23fc 100644 --- a/PHPCI/Languages/lang.it.php +++ b/PHPCI/Languages/lang.it.php @@ -197,14 +197,20 @@ PHPCI', 'end' => 'Finisci', 'from' => 'Da', 'to' => 'A', - 'suite' => 'Suite', - 'test' => 'Test', 'result' => 'Risultati', 'ok' => 'OK', 'took_n_seconds' => 'Sono stati impiegati %d seconds', 'build_created' => 'Build Creata', 'build_started' => 'Build Avviata', 'build_finished' => 'Build Terminata', + 'test_message' => 'Message', + 'test_no_message' => 'No message', + 'test_success' => 'Succesfull: %d', + 'test_fail' => 'Failures: %d', + 'test_skipped' => 'Skipped: %d', + 'test_error' => 'Errors: %d', + 'test_todo' => 'Todos: %d', + 'test_total' => '%d test(s)', // Users 'name' => 'Nome', diff --git a/PHPCI/Languages/lang.nl.php b/PHPCI/Languages/lang.nl.php index 29e8b0f8..38e9466c 100644 --- a/PHPCI/Languages/lang.nl.php +++ b/PHPCI/Languages/lang.nl.php @@ -195,14 +195,20 @@ Services sectie van je Bitbucket repository toegevoegd worden.', 'end' => 'Einde', 'from' => 'Van', 'to' => 'Tot', - 'suite' => 'Suite', - 'test' => 'Test', 'result' => 'Resultaat', 'ok' => 'OK', 'took_n_seconds' => 'Duurde %d seconden', 'build_created' => 'Build aangemaakt', 'build_started' => 'Build gestart', 'build_finished' => 'Build beëindigd', + 'test_message' => 'Message', + 'test_no_message' => 'No message', + 'test_success' => 'Succesfull: %d', + 'test_fail' => 'Failures: %d', + 'test_skipped' => 'Skipped: %d', + 'test_error' => 'Errors: %d', + 'test_todo' => 'Todos: %d', + 'test_total' => '%d test(s)', // Users 'name' => 'Naam', diff --git a/PHPCI/Languages/lang.pl.php b/PHPCI/Languages/lang.pl.php index 816eb009..b4f8430c 100644 --- a/PHPCI/Languages/lang.pl.php +++ b/PHPCI/Languages/lang.pl.php @@ -198,14 +198,20 @@ Services repozytoria Bitbucket.', 'end' => 'Koniec', 'from' => 'Od', 'to' => 'Do', - 'suite' => 'Zestaw ', - 'test' => 'Test', 'result' => 'Wynik', 'ok' => 'OK', 'took_n_seconds' => 'Zajęło %d sekund', 'build_created' => 'Budowanie Stworzone', 'build_started' => 'Budowanie Rozpoczęte', 'build_finished' => 'Budowanie Zakończone', + 'test_message' => 'Message', + 'test_no_message' => 'No message', + 'test_success' => 'Succesfull: %d', + 'test_fail' => 'Failures: %d', + 'test_skipped' => 'Skipped: %d', + 'test_error' => 'Errors: %d', + 'test_todo' => 'Todos: %d', + 'test_total' => '%d test(s)', // Users 'name' => 'Nazwa', diff --git a/PHPCI/Languages/lang.ru.php b/PHPCI/Languages/lang.ru.php index 44ed1550..931c8910 100644 --- a/PHPCI/Languages/lang.ru.php +++ b/PHPCI/Languages/lang.ru.php @@ -193,14 +193,20 @@ PHPCI', 'end' => 'Конец', 'from' => 'Из', 'to' => 'В', - 'suite' => 'Комплект', - 'test' => 'Тест', 'result' => 'Результат', 'ok' => 'OK', 'took_n_seconds' => 'Заняло секунд: %d', 'build_created' => 'Сборка создана', 'build_started' => 'Сборка запущена', 'build_finished' => 'Сборка окончена', + 'test_message' => 'Message', + 'test_no_message' => 'No message', + 'test_success' => 'Succesfull: %d', + 'test_fail' => 'Failures: %d', + 'test_skipped' => 'Skipped: %d', + 'test_error' => 'Errors: %d', + 'test_todo' => 'Todos: %d', + 'test_total' => '%d test(s)', // Users 'name' => 'Имя', diff --git a/PHPCI/Languages/lang.uk.php b/PHPCI/Languages/lang.uk.php index 3e96459e..b080c65a 100644 --- a/PHPCI/Languages/lang.uk.php +++ b/PHPCI/Languages/lang.uk.php @@ -195,14 +195,20 @@ PHPCI', 'end' => 'Кінець', 'from' => 'Від', 'to' => 'До', - 'suite' => 'Комплект', - 'test' => 'Тест', 'result' => 'Результат', 'ok' => 'OK', 'took_n_seconds' => 'Зайняло %d секунд', 'build_created' => 'Збірка створена', 'build_started' => 'Збірка розпочата', 'build_finished' => 'Збірка завершена', + 'test_message' => 'Message', + 'test_no_message' => 'No message', + 'test_success' => 'Succesfull: %d', + 'test_fail' => 'Failures: %d', + 'test_skipped' => 'Skipped: %d', + 'test_error' => 'Errors: %d', + 'test_todo' => 'Todos: %d', + 'test_total' => '%d test(s)', // Users 'name' => 'Ім’я', diff --git a/PHPCI/Plugin/Util/TapParser.php b/PHPCI/Plugin/Util/TapParser.php index 57b92b55..18772a6a 100644 --- a/PHPCI/Plugin/Util/TapParser.php +++ b/PHPCI/Plugin/Util/TapParser.php @@ -2,7 +2,9 @@ namespace PHPCI\Plugin\Util; +use Exception; use PHPCI\Helper\Lang; +use Symfony\Component\Yaml\Yaml; /** * Processes TAP format strings into usable test result data. @@ -10,18 +12,41 @@ use PHPCI\Helper\Lang; */ class TapParser { - const TEST_COUNTS_PATTERN = '/([0-9]+)\.\.([0-9]+)/'; - const TEST_LINE_PATTERN = '/(ok|not ok)\s+[0-9]+\s+\-\s+([^\n]+)::([^\n]+)/'; - const TEST_MESSAGE_PATTERN = '/message\:\s+\'([^\']+)\'/'; - const TEST_COVERAGE_PATTERN = '/Generating code coverage report/'; - const TEST_SKIP_PATTERN = '/ok\s+[0-9]+\s+\-\s+#\s+SKIP/'; + const TEST_COUNTS_PATTERN = '/^\d+\.\.(\d+)/'; + const TEST_LINE_PATTERN = '/^(ok|not ok)(?:\s+\d+)?(?:\s+\-)?\s*(.*?)(?:\s*#\s*(skip|todo)\s*(.*))?\s*$/i'; + const TEST_YAML_START = '/^(\s*)---/'; + const TEST_DIAGNOSTIC = '/^#/'; /** * @var string */ protected $tapString; + + /** + * @var int + */ protected $failures = 0; + /** + * @var array + */ + protected $lines; + + /** + * @var integer + */ + protected $lineNumber; + + /** + * @var integer + */ + protected $testCount; + + /** + * @var array + */ + protected $results; + /** * Create a new TAP parser for a given string. * @param string $tapString The TAP format string to be parsed. @@ -38,81 +63,175 @@ class TapParser { // Split up the TAP string into an array of lines, then // trim all of the lines so there's no leading or trailing whitespace. - $lines = explode("\n", $this->tapString); - $lines = array_map(function ($line) { - return trim($line); - }, $lines); + $this->lines = array_map('rtrim', explode("\n", $this->tapString)); + $this->lineNumber = 0; - // Check TAP version: - $versionLine = array_shift($lines); + $this->testCount = false; + $this->results = array(); - if ($versionLine != 'TAP version 13') { - throw new \Exception(Lang::get('tap_version')); + $header = $this->findTapLog(); + + $line = $this->nextLine(); + if ($line === $header) { + throw new Exception("Duplicated TAP log, please check the configration."); } - if (isset($lines[count($lines) - 1]) && preg_match(self::TEST_COVERAGE_PATTERN, $lines[count($lines) - 1])) { - array_pop($lines); - if ($lines[count($lines) - 1] == "") { - array_pop($lines); + while ($line !== false && ($this->testCount === false || count($this->results) < $this->testCount)) { + $this->parseLine($line); + $line = $this->nextLine(); + } + + if (count($this->results) !== $this->testCount) { + throw new Exception(Lang::get('tap_error')); + } + + return $this->results; + } + + /** Looks for the start of the TAP log in the string. + * + * @return string The TAP header line. + * + * @throws Exception if no TAP log is found or versions mismatch. + */ + protected function findTapLog() + { + // Look for the beggning of the TAP output + do { + $header = $this->nextLine(); + } while ($header !== false && substr($header, 0, 12) !== 'TAP version '); + + // + if ($header === false) { + throw new Exception('No TAP log found, please check the configuration.'); + } elseif ($header !== 'TAP version 13') { + throw new Exception(Lang::get('tap_version')); + } + + return $header; + } + + /** Fetch the next line. + * + * @return string|false The next line or false if the end has been reached. + */ + protected function nextLine() + { + if ($this->lineNumber < count($this->lines)) { + return $this->lines[$this->lineNumber++]; + } + return false; + } + + /** Parse a single line. + * + * @param string $line + */ + protected function parseLine($line) + { + if (preg_match(self::TEST_COUNTS_PATTERN, $line, $matches)) { + $this->testCount = intval($matches[1]); + + } elseif (preg_match(self::TEST_DIAGNOSTIC, $line)) { + return; + + } elseif (preg_match(self::TEST_LINE_PATTERN, $line, $matches)) { + $this->results[] = $this->processTestLine( + $matches[1], + isset($matches[2]) ? $matches[2] : '', + isset($matches[3]) ? $matches[3] : null, + isset($matches[4]) ? $matches[4] : null + ); + + } elseif (preg_match(self::TEST_YAML_START, $line, $matches)) { + $diagnostic = $this->processYamlBlock($matches[1]); + $test = array_pop($this->results); + if (isset($test['message'], $diagnostic['message'])) { + $test['message'] .= PHP_EOL . $diagnostic['message']; + unset($diagnostic['message']); } + $this->results[] = array_replace($test, $diagnostic); + + } else { + throw new Exception(sprintf('Incorrect TAP data, line %d: %s', $this->lineNumber, $line)); } - - $matches = array(); - $totalTests = 0; - if (preg_match(self::TEST_COUNTS_PATTERN, $lines[0], $matches)) { - array_shift($lines); - $totalTests = (int) $matches[2]; - } - - if (isset($lines[count($lines) - 1]) && - preg_match(self::TEST_COUNTS_PATTERN, $lines[count($lines) - 1], $matches)) { - array_pop($lines); - $totalTests = (int) $matches[2]; - } - - $rtn = $this->processTestLines($lines); - - if ($totalTests != count($rtn)) { - throw new \Exception(Lang::get('tap_error')); - } - - return $rtn; } /** - * Process the individual test lines within a TAP string. - * @param $lines + * Process an individual test line. + * + * @param string $result + * @param string $message + * @param string $directive + * @param string $reason + * * @return array */ - protected function processTestLines($lines) + protected function processTestLine($result, $message, $directive, $reason) { - $rtn = array(); + $test = array( + 'pass' => true, + 'message' => $message, + 'severity' => 'success', + ); - foreach ($lines as $line) { - $matches = array(); - - if (preg_match(self::TEST_LINE_PATTERN, $line, $matches)) { - $ok = ($matches[1] == 'ok' ? true : false); - - if (!$ok) { - $this->failures++; - } - - $item = array( - 'pass' => $ok, - 'suite' => $matches[2], - 'test' => $matches[3], - ); - - $rtn[] = $item; - } elseif (preg_match(self::TEST_SKIP_PATTERN, $line, $matches)) { - $rtn[] = array('message' => 'SKIP'); - } elseif (preg_match(self::TEST_MESSAGE_PATTERN, $line, $matches)) { - $rtn[count($rtn) - 1]['message'] = $matches[1]; - } + if ($result !== 'ok') { + $test['pass'] = false; + $test['severity'] = substr($message, 0, 6) === 'Error:' ? 'error' : 'fail'; + $this->failures++; } - return $rtn; + if ($directive) { + $test = $this->processDirective($test, $directive, $reason); + } + + return $test; + } + + /** Process an indented Yaml block. + * + * @param string $indent The block indentation to ignore. + * + * @return array The processed Yaml content. + */ + protected function processYamlBlock($indent) + { + $startLine = $this->lineNumber+1; + $endLine = $indent.'...'; + $yamlLines = array(); + do { + $line = $this->nextLine(); + if ($line === false) { + throw new Exception(Lang::get('tap_error_endless_yaml', $startLine)); + } elseif ($line === $endLine) { + break; + } + $yamlLines[] = substr($line, strlen($indent)); + + } while (true); + + return Yaml::parse(join("\n", $yamlLines)); + } + + /** Process a TAP directive + * + * @param array $test + * @param string $directive + * @param string $reason + * @return array + */ + protected function processDirective($test, $directive, $reason) + { + $test['severity'] = strtolower($directive) === 'skip' ? 'skipped' : 'todo'; + + if (!empty($reason)) { + if (!empty($test['message'])) { + $test['message'] .= ', '.$test['severity'].': '; + } + $test['message'] .= $reason; + } + + return $test; } /** diff --git a/Tests/PHPCI/Plugin/Util/TapParserTest.php b/Tests/PHPCI/Plugin/Util/TapParserTest.php index c4438b79..75c04bfa 100644 --- a/Tests/PHPCI/Plugin/Util/TapParserTest.php +++ b/Tests/PHPCI/Plugin/Util/TapParserTest.php @@ -5,22 +5,254 @@ use PHPCI\Plugin\Util\TapParser; class TapParserTest extends \PHPUnit_Framework_TestCase { - public function testSkipped() + public function testSimple() + { + $content = <<parse(); + + $this->assertEquals(array( + array('pass' => true, 'severity' => 'success', 'message' => 'SomeTest::testAnother'), + array('pass' => false, 'severity' => 'fail', 'message' => ''), + ), $result); + + $this->assertEquals(1, $parser->getTotalFailures()); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessageRegExp /No TAP/ + */ + public function testNoTapData() + { + $content = <<parse(); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessageRegExp /Duplicated TAP/ + */ + public function testDuplicateOutput() + { + $content = <<parse(); + } + + public function testSuiteAndTest() { $content = <<parse(); + + $this->assertEquals(array( + array('pass' => true, 'severity' => 'success', 'message' => 'SomeTest::testAnother',), + array('pass' => false, 'severity' => 'fail', 'message' => 'Failure: SomeTest::testAnother'), + array('pass' => false, 'severity' => 'error', 'message' => 'Error: SomeTest::testAnother'), + ), $result); + + $this->assertEquals(2, $parser->getTotalFailures()); + } + + + public function testSkipped() + { + $content = <<parse(); + + $this->assertEquals(array( + array('pass' => true, 'severity' => 'skipped', 'message' => ''), + array('pass' => true, 'severity' => 'skipped', 'message' => 'foobar'), + array('pass' => true, 'severity' => 'skipped', 'message' => 'foo, skipped: bar'), + ), $result); + + $this->assertEquals(0, $parser->getTotalFailures()); + } + + public function testTodo() + { + $content = <<parse(); + + $this->assertEquals(array( + array('pass' => true, 'severity' => 'todo', 'message' => 'SomeTest::testAnother, todo: really implement this test'), + array('pass' => true, 'severity' => 'todo', 'message' => 'really implement this test'), + array('pass' => true, 'severity' => 'todo', 'message' => 'this is a message, todo: really implement this test'), + array('pass' => true, 'severity' => 'todo', 'message' => ''), + ), $result); + + $this->assertEquals(0, $parser->getTotalFailures()); + } + + public function testYamlDiagnostic() + { + // From https://phpunit.de/manual/current/en/logging.html#logging.tap + $content = <<parse(); + + $this->assertEquals(array( + array( + 'pass' => false, + 'severity' => 'fail', + 'message' => 'FOO' . PHP_EOL . 'BAR', + ), + ), $result); + + $this->assertEquals(1, $parser->getTotalFailures()); + } + + public function testFailureAndError() + { + // From https://phpunit.de/manual/current/en/logging.html#logging.tap + $content = <<parse(); $this->assertEquals(array( - array('pass' => true, 'suite' => 'SomeTest', 'test' => 'testAnother'), - array('message' => 'SKIP'), + array( + 'pass' => false, + 'severity' => 'fail', + 'message' => 'Failure: testFailure::FailureErrorTest', + ), + array( + 'pass' => false, + 'severity' => 'error', + 'message' => 'Error: testError::FailureErrorTest', + ) ), $result); + $this->assertEquals(2, $parser->getTotalFailures()); + } + + /** + * @expectedException \Exception + */ + public function testGarbage() + { + $content = "Garbage !"; + + $parser = new TapParser($content); + $parser->parse(); + } + + /** + * @expectedException \Exception + */ + public function testInvalidTestCount() + { + $content = <<parse(); + } + + /** + * @expectedException \Exception + */ + public function testEndlessYaml() + { + $content = <<parse(); + } + + public function testCodeception() + { + $content = <<< TAP +TAP version 13 +ok 1 - try to access the dashboard as a guest (Auth/GuestAccessDashboardAndRedirectCept) +ok 2 - see the login page (Auth/SeeLoginCept) +ok 3 - click forgot password and see the email form (Auth/SeeLoginForgotPasswordCept) +ok 4 - see powered by runmybusiness branding (Auth/ShouldSeePoweredByBrandingCept) +ok 5 - submit invalid credentials (Auth/SubmitLoginAndFailCept) +ok 6 - submit valid credentials and see the dashboard (Auth/SubmitLoginAndSucceedCept) +1..6 +TAP; + + $parser = new TapParser($content); + $result = $parser->parse(); + + $this->assertEquals( + array( + array('pass' => true, 'severity' => 'success', 'message' => 'try to access the dashboard as a guest (Auth/GuestAccessDashboardAndRedirectCept)'), + array('pass' => true, 'severity' => 'success', 'message' => 'see the login page (Auth/SeeLoginCept)'), + array('pass' => true, 'severity' => 'success', 'message' => 'click forgot password and see the email form (Auth/SeeLoginForgotPasswordCept)'), + array('pass' => true, 'severity' => 'success', 'message' => 'see powered by runmybusiness branding (Auth/ShouldSeePoweredByBrandingCept)'), + array('pass' => true, 'severity' => 'success', 'message' => 'submit invalid credentials (Auth/SubmitLoginAndFailCept)'), + array('pass' => true, 'severity' => 'success', 'message' => 'submit valid credentials and see the dashboard (Auth/SubmitLoginAndSucceedCept)'), + ), + $result + ); + $this->assertEquals(0, $parser->getTotalFailures()); + } } diff --git a/public/assets/css/AdminLTE-custom.css b/public/assets/css/AdminLTE-custom.css index b95f7b70..e37a0f48 100644 --- a/public/assets/css/AdminLTE-custom.css +++ b/public/assets/css/AdminLTE-custom.css @@ -84,4 +84,11 @@ padding: 0; font-size: inherit; line-height: inherit; -} \ No newline at end of file +} + +#phpunit-data th div { margin: 0 0.5em; } +#phpunit-data .success td { background: none; color: #00a65a; } +#phpunit-data .fail td { background: none; color: #f56954; } +#phpunit-data .error td { background: none; color: #f56954; } +#phpunit-data .skipped td { background: none; color: #e08e0b; } +#phpunit-data .todo td { background: none; color: #00c0ef; } diff --git a/public/assets/js/build-plugins/phpunit.js b/public/assets/js/build-plugins/phpunit.js index 4a55d905..66f010a1 100644 --- a/public/assets/js/build-plugins/phpunit.js +++ b/public/assets/js/build-plugins/phpunit.js @@ -6,6 +6,13 @@ var phpunitPlugin = ActiveBuild.UiPlugin.extend({ displayOnUpdate: false, box: true, rendered: false, + statusMap: { + success : 'ok', + fail: 'remove', + error: 'warning-sign', + todo: 'info-sign', + skipped: 'exclamation-sign' + }, register: function() { var self = this; @@ -21,6 +28,11 @@ var phpunitPlugin = ActiveBuild.UiPlugin.extend({ query(); } }); + + $(document).on('click', '#phpunit-data .test-toggle', function(ev) { + var input = $(ev.target); + $('#phpunit-data tbody ' + input.data('target')).toggle(input.prop('checked')); + }); }, render: function() { @@ -28,7 +40,7 @@ var phpunitPlugin = ActiveBuild.UiPlugin.extend({ return $('
#getId(), 6, '0', STR_PAD_LEFT); ?>getCreated()->format('Y-m-d H:i:s'); ?> getProject())) { diff --git a/PHPCI/View/Project/view.phtml b/PHPCI/View/Project/view.phtml index 900349c8..2e79c017 100644 --- a/PHPCI/View/Project/view.phtml +++ b/PHPCI/View/Project/view.phtml @@ -42,6 +42,7 @@
' + '' + '' + - ' ' + + ' ' + '' + '
'+Lang.get('test')+''+Lang.get('test_message')+'
'); }, @@ -43,7 +55,9 @@ var phpunitPlugin = ActiveBuild.UiPlugin.extend({ this.lastData = e.queryData; var tests = this.lastData[0].meta_value; + var thead = $('#phpunit-data thead tr'); var tbody = $('#phpunit-data tbody'); + thead.empty().append(''+Lang.get('test_message')+''); tbody.empty(); if (tests.length == 0) { @@ -51,24 +65,74 @@ var phpunitPlugin = ActiveBuild.UiPlugin.extend({ return; } + var counts = { success: 0, fail: 0, error: 0, skipped: 0, todo: 0 }, total = 0; + for (var i in tests) { - - var row = $('' + - ''+tests[i].suite+'' + - '::'+tests[i].test+'
' + - ''+(tests[i].message || '')+'' + - ''); - - if (!tests[i].pass) { - row.addClass('danger'); - } else { - row.addClass('success'); - } - - tbody.append(row); + var severity = tests[i].severity || 'success', + message = tests[i].message || ('' + Lang.get('test_no_message') + ''); + counts[severity]++; + total++; + tbody.append( + '' + + '' + + '
' + message + '
' + + (tests[i].data ? '
' + this.repr(tests[i].data) + '
' : '') + + '' + + '' + ); } + var checkboxes = $(''); + thead.append(checkboxes).append('' + Lang.get('test_total', total) + ''); + + for (var key in counts) { + var count = counts[key]; + if(count > 0) { + checkboxes.append( + '
 ' + + Lang.get('test_'+key, count)+ '
' + ); + } + } + + tbody.find('.success').hide(); + $('#build-phpunit-errors').show(); + }, + + repr: function(data) + { + switch(typeof(data)) { + case 'boolean': + return '' + (data ? 'true' : 'false') + ''; + case 'string': + return '"' + data + '"'; + case 'undefined': case null: + return 'null'; + case 'object': + var rows = []; + if(data instanceof Array) { + for(var i in data) { + rows.push('' + this.repr(data[i]) + ','); + } + } else { + for(var key in data) { + rows.push( + '' + + '' + this.repr(key) + '' + + '=>' + + '' + this.repr(data[key]) + ',' + + ''); + } + } + return '' + + '' + + rows.join('') + + '' + + '
array(
)
'; + } + return '???'; } }); From 01911f11aa7c2e20087aa139df25cc081eabf41c Mon Sep 17 00:00:00 2001 From: Tobias van Beek Date: Wed, 25 Mar 2015 11:10:47 +0100 Subject: [PATCH 18/57] Add the --recursive parameter to the git clone to get the submodules --- PHPCI/Model/Build/RemoteGitBuild.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PHPCI/Model/Build/RemoteGitBuild.php b/PHPCI/Model/Build/RemoteGitBuild.php index 80718011..5d0c9419 100644 --- a/PHPCI/Model/Build/RemoteGitBuild.php +++ b/PHPCI/Model/Build/RemoteGitBuild.php @@ -54,7 +54,7 @@ class RemoteGitBuild extends Build */ protected function cloneByHttp(Builder $builder, $cloneTo) { - $cmd = 'git clone '; + $cmd = 'git clone --recursive '; $depth = $builder->getConfig('clone_depth'); @@ -84,7 +84,7 @@ class RemoteGitBuild extends Build } // Do the git clone: - $cmd = 'git clone '; + $cmd = 'git clone --recursive '; $depth = $builder->getConfig('clone_depth'); From 524341a50b33c47b6d7ba1983d8446da9e57a7f5 Mon Sep 17 00:00:00 2001 From: Angel Koilov Date: Fri, 27 Mar 2015 14:09:03 +0200 Subject: [PATCH 19/57] remove unnecessary code --- PHPCI/Plugin/Behat.php | 1 - 1 file changed, 1 deletion(-) diff --git a/PHPCI/Plugin/Behat.php b/PHPCI/Plugin/Behat.php index 23686270..445d7191 100644 --- a/PHPCI/Plugin/Behat.php +++ b/PHPCI/Plugin/Behat.php @@ -98,7 +98,6 @@ class Behat implements \PHPCI\Plugin $lines = explode(PHP_EOL, $parts[1]); - $errorCount = 0; $storeFailures = false; $data = array(); From 731fd65453c7663129dc0175b208b61ce9e06d39 Mon Sep 17 00:00:00 2001 From: zviryatko Date: Sat, 28 Mar 2015 16:50:40 +0200 Subject: [PATCH 20/57] Change xmpp config and message files directory --- PHPCI/Plugin/Xmpp.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/PHPCI/Plugin/Xmpp.php b/PHPCI/Plugin/Xmpp.php index 8614e208..add778cb 100644 --- a/PHPCI/Plugin/Xmpp.php +++ b/PHPCI/Plugin/Xmpp.php @@ -132,8 +132,8 @@ class XMPP implements \PHPCI\Plugin */ public function findConfigFile() { - if (file_exists('.sendxmpprc')) { - if (md5(file_get_contents('.sendxmpprc')) !== md5($this->getConfigFormat())) { + if (file_exists($this->phpci->buildPath . '/.sendxmpprc')) { + if (md5(file_get_contents($this->phpci->buildPath . '/.sendxmpprc')) !== md5($this->getConfigFormat())) { return null; } @@ -165,9 +165,10 @@ class XMPP implements \PHPCI\Plugin /* * Try to build conf file */ + $config_file = $this->phpci->buildPath . '/.sendxmpprc'; if (is_null($this->findConfigFile())) { - file_put_contents('.sendxmpprc', $this->getConfigFormat()); - chmod('.sendxmpprc', 0600); + file_put_contents($config_file, $this->getConfigFormat()); + chmod($config_file, 0600); } /* @@ -178,7 +179,7 @@ class XMPP implements \PHPCI\Plugin $tls = ' -t'; } - $message_file = uniqid('xmppmessage'); + $message_file = $this->phpci->buildPath . '/' . uniqid('xmppmessage'); if ($this->buildMessage($message_file) === false) { return false; } @@ -186,10 +187,10 @@ class XMPP implements \PHPCI\Plugin /* * Send XMPP notification for all recipients */ - $cmd = $sendxmpp . "%s -f .sendxmpprc -m %s %s"; + $cmd = $sendxmpp . "%s -f %s -m %s %s"; $recipients = implode(' ', $this->recipients); - $success = $this->phpci->executeCommand($cmd, $tls, $message_file, $recipients); + $success = $this->phpci->executeCommand($cmd, $tls, $config_file, $message_file, $recipients); print $this->phpci->getLastOutput(); From f3c1a98cf10871eadd62bc461e4e02382384ba2f Mon Sep 17 00:00:00 2001 From: Adirelle Date: Wed, 25 Mar 2015 15:15:53 +0100 Subject: [PATCH 21/57] Detailed webhook responses. Fixed docblocks. Reworked WebhookController to enforce Json responses in ::handleAction. Check the project type match the webhook. When creating several builds, do not stop on first error. Try to create every builds and report 'ok' if at least one succeeds. CS fix. Fixed Uses. Fixed the types accepted by the git webhook. Added some really basic test. --- PHPCI/Controller/WebhookController.php | 378 ++++++++++-------- .../Controller/WebhookControllerTest.php | 41 ++ 2 files changed, 260 insertions(+), 159 deletions(-) create mode 100644 Tests/PHPCI/Controller/WebhookControllerTest.php diff --git a/PHPCI/Controller/WebhookController.php b/PHPCI/Controller/WebhookController.php index 78824ddb..e05cfbda 100644 --- a/PHPCI/Controller/WebhookController.php +++ b/PHPCI/Controller/WebhookController.php @@ -2,7 +2,7 @@ /** * PHPCI - Continuous Integration for PHP * - * @copyright Copyright 2014, Block 8 Limited. + * @copyright Copyright 2014-2015, Block 8 Limited. * @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md * @link https://www.phptesting.org/ */ @@ -11,31 +11,37 @@ namespace PHPCI\Controller; use b8; use b8\Store; +use Exception; use PHPCI\BuildFactory; +use PHPCI\Model\Project; use PHPCI\Service\BuildService; +use PHPCI\Store\BuildStore; +use PHPCI\Store\ProjectStore; /** * Webhook Controller - Processes webhook pings from BitBucket, Github, Gitlab, etc. + * * @author Dan Cryer * @author Sami Tikka * @author Alex Russell + * @author Guillaume Perréal * @package PHPCI * @subpackage Web */ -class WebhookController extends \PHPCI\Controller +class WebhookController extends \b8\Controller { /** - * @var \PHPCI\Store\BuildStore + * @var BuildStore */ protected $buildStore; /** - * @var \PHPCI\Store\ProjectStore + * @var ProjectStore */ protected $projectStore; /** - * @var \PHPCI\Service\BuildService + * @var BuildService */ protected $buildService; @@ -49,194 +55,207 @@ class WebhookController extends \PHPCI\Controller $this->buildService = new BuildService($this->buildStore); } + /** Handle the action, Ensuring to return a JsonResponse. + * + * @param string $action + * @param mixed $actionParams + * + * @return \b8\Http\Response + */ + public function handleAction($action, $actionParams) + { + $response = new b8\Http\Response\JsonResponse(); + try { + $data = parent::handleAction($action, $actionParams); + if (isset($data['responseCode'])) { + $response->setResponseCode($data['responseCode']); + unset($data['responseCode']); + } + $response->setContent($data); + } catch (Exception $ex) { + $response->setResponseCode(500); + $response->setContent(array('status' => 'failed', 'error' => $ex->getMessage())); + } + return $response; + } + /** * Called by Bitbucket POST service. */ - public function bitbucket($project) + public function bitbucket($projectId) { - $response = new b8\Http\Response\JsonResponse(); - $response->setContent(array('status' => 'ok')); - + $project = $this->fetchProject($projectId, 'bitbucket'); $payload = json_decode($this->getParam('payload'), true); + $results = array(); + $status = 'failed'; foreach ($payload['commits'] as $commit) { try { $email = $commit['raw_author']; $email = substr($email, 0, strpos($email, '>')); $email = substr($email, strpos($email, '<') + 1); - $this->createBuild($project, $commit['raw_node'], $commit['branch'], $email, $commit['message']); - } catch (\Exception $ex) { - $response->setResponseCode(500); - $response->setContent(array('status' => 'failed', 'error' => $ex->getMessage())); - break; + $results[$commit['raw_node']] = $this->createBuild( + $project, + $commit['raw_node'], + $commit['branch'], + $email, + $commit['message'] + ); + $status = 'ok'; + } catch (Exception $ex) { + $results[$commit['raw_node']] = array('status' => 'failed', 'error' => $ex->getMessage()); } } - return $response; + return array('status' => $status, 'commits' => $results); } /** * Called by POSTing to /webhook/git/?branch=&commit= * - * @param string $project + * @param string $projectId */ - public function git($project) + public function git($projectId) { - $response = new b8\Http\Response\JsonResponse(); - $response->setContent(array('status' => 'ok')); - - $branch = $this->getParam('branch'); + $project = $this->fetchProject($projectId, array('local', 'remote')); + $branch = $this->getParam('branch', $project->getBranch()); $commit = $this->getParam('commit'); $commitMessage = $this->getParam('message'); $committer = $this->getParam('committer'); - try { - if (empty($branch)) { - $branch = 'master'; - } - - if (empty($commit)) { - $commit = null; - } - - if (empty($commitMessage)) { - $commitMessage = null; - } - - if (empty($committer)) { - $committer = null; - } - - $this->createBuild($project, $commit, $branch, $committer, $commitMessage); - } catch (\Exception $ex) { - $response->setResponseCode(500); - $response->setContent(array('status' => 'failed', 'error' => $ex->getMessage())); - } - - return $response; + return $this->createBuild($project, $commit, $branch, $committer, $commitMessage); } /** * Called by Github Webhooks: */ - public function github($project) + public function github($projectId) { - $response = new b8\Http\Response\JsonResponse(); - $response->setContent(array('status' => 'ok')); + $project = $this->fetchProject($projectId, 'github'); switch ($_SERVER['CONTENT_TYPE']) { case 'application/json': $payload = json_decode(file_get_contents('php://input'), true); break; - case 'application/x-www-form-urlencoded': $payload = json_decode($this->getParam('payload'), true); break; - default: - $response->setResponseCode(401); - $response->setContent(array('status' => 'failed', 'error' => 'Content type not supported.')); - return $response; + return array('status' => 'failed', 'error' => 'Content type not supported.', 'responseCode' => 401); } // Handle Pull Request web hooks: if (array_key_exists('pull_request', $payload)) { - return $this->githubPullRequest($project, $payload, $response); + return $this->githubPullRequest($project, $payload); } // Handle Push web hooks: if (array_key_exists('commits', $payload)) { - return $this->githubCommitRequest($project, $payload, $response); + return $this->githubCommitRequest($project, $payload); } - return $response; + return array('status' => 'ignored', 'message' => 'Unusable payload.'); } /** * Handle the payload when Github sends a commit webhook. - * @param $project + * + * @param Project $project * @param array $payload * @param b8\Http\Response\JsonResponse $response + * * @return b8\Http\Response\JsonResponse */ - protected function githubCommitRequest($project, array $payload, b8\Http\Response\JsonResponse $response) + protected function githubCommitRequest(Project $project, array $payload) { // Github sends a payload when you close a pull request with a // non-existant commit. We don't want this. if (array_key_exists('after', $payload) && $payload['after'] === '0000000000000000000000000000000000000000') { - return $response; + return array('status' => 'ignored'); } - try { - if (isset($payload['commits']) && is_array($payload['commits'])) { - // If we have a list of commits, then add them all as builds to be tested: + if (isset($payload['commits']) && is_array($payload['commits'])) { + // If we have a list of commits, then add them all as builds to be tested: - foreach ($payload['commits'] as $commit) { - if (!$commit['distinct']) { - continue; - } + $results = array(); + $status = 'failed'; + foreach ($payload['commits'] as $commit) { + if (!$commit['distinct']) { + $results[$commit['id']] = array('status' => 'ignored'); + continue; + } + try { $branch = str_replace('refs/heads/', '', $payload['ref']); $committer = $commit['committer']['email']; - $this->createBuild($project, $commit['id'], $branch, $committer, $commit['message']); + $results[$commit['id']] = $this->createBuild( + $project, + $commit['id'], + $branch, + $committer, + $commit['message'] + ); + $status = 'ok'; + } catch (Exception $ex) { + $results[$commit['id']] = array('status' => 'failed', 'error' => $ex->getMessage()); } - } elseif (substr($payload['ref'], 0, 10) == 'refs/tags/') { - // If we don't, but we're dealing with a tag, add that instead: - $branch = str_replace('refs/tags/', 'Tag: ', $payload['ref']); - $committer = $payload['pusher']['email']; - $message = $payload['head_commit']['message']; - $this->createBuild($project, $payload['after'], $branch, $committer, $message); } - - } catch (\Exception $ex) { - $response->setResponseCode(500); - $response->setContent(array('status' => 'failed', 'error' => $ex->getMessage())); - + return array('status' => $status, 'commits' => $results); } - return $response; + if (substr($payload['ref'], 0, 10) == 'refs/tags/') { + // If we don't, but we're dealing with a tag, add that instead: + $branch = str_replace('refs/tags/', 'Tag: ', $payload['ref']); + $committer = $payload['pusher']['email']; + $message = $payload['head_commit']['message']; + return $this->createBuild($project, $payload['after'], $branch, $committer, $message); + } + + return array('status' => 'ignored', 'message' => 'Unusable payload.'); } /** * Handle the payload when Github sends a Pull Request webhook. - * @param $projectId + * + * @param Project $project * @param array $payload */ - protected function githubPullRequest($projectId, array $payload, b8\Http\Response\JsonResponse $response) + protected function githubPullRequest(Project $project, array $payload) { // We only want to know about open pull requests: if (!in_array($payload['action'], array('opened', 'synchronize', 'reopened'))) { - return $response; + return array('status' => 'ok'); } - try { - $headers = array(); - $token = \b8\Config::getInstance()->get('phpci.github.token'); + $headers = array(); + $token = \b8\Config::getInstance()->get('phpci.github.token'); - if (!empty($token)) { - $headers[] = 'Authorization: token ' . $token; + if (!empty($token)) { + $headers[] = 'Authorization: token ' . $token; + } + + $url = $payload['pull_request']['commits_url']; + $http = new \b8\HttpClient(); + $http->setHeaders($headers); + $response = $http->get($url); + + // Check we got a success response: + if (!$response['success']) { + throw new Exception('Could not get commits, failed API request.'); + } + + $results = array(); + $status = 'failed'; + foreach ($response['body'] as $commit) { + // Skip all but the current HEAD commit ID: + $id = $commit['sha']; + if ($id != $payload['pull_request']['head']['sha']) { + $results[$id] = array('status' => 'ignored', 'message' => 'not branch head'); + continue; } - $url = $payload['pull_request']['commits_url']; - $http = new \b8\HttpClient(); - $http->setHeaders($headers); - $response = $http->get($url); - - // Check we got a success response: - if (!$response['success']) { - $message = 'Could not get commits, failed API request.'; - $response->setResponseCode(500); - $response->setContent(array('status' => 'failed', 'error' => $message)); - return $response; - } - - foreach ($response['body'] as $commit) { - // Skip all but the current HEAD commit ID: - if ($commit['sha'] != $payload['pull_request']['head']['sha']) { - continue; - } - + try { $branch = str_replace('refs/heads/', '', $payload['pull_request']['base']['ref']); $committer = $commit['commit']['author']['email']; $message = $commit['commit']['message']; @@ -249,83 +268,96 @@ class WebhookController extends \PHPCI\Controller 'remote_url' => $payload['pull_request']['head']['repo']['clone_url'], ); - $this->createBuild($projectId, $commit['sha'], $branch, $committer, $message, $extra); + $results[$id] = $this->createBuild($project, $id, $branch, $committer, $message, $extra); + $status = 'ok'; + } catch (Exception $ex) { + $results[$id] = array('status' => 'failed', 'error' => $ex->getMessage()); } - } catch (\Exception $ex) { - $response->setResponseCode(500); - $response->setContent(array('status' => 'failed', 'error' => $ex->getMessage())); } - return $response; + return array('status' => $status, 'commits' => $results); } /** * Called by Gitlab Webhooks: */ - public function gitlab($project) + public function gitlab($projectId) { - $response = new b8\Http\Response\JsonResponse(); - $response->setContent(array('status' => 'ok')); + $project = $this->fetchProject($projectId, 'gitlab'); $payloadString = file_get_contents("php://input"); $payload = json_decode($payloadString, true); - try { - // build on merge request events - if (isset($payload['object_kind']) && $payload['object_kind'] == 'merge_request') { - $attributes = $payload['object_attributes']; - if ($attributes['state'] == 'opened' || $attributes['state'] == 'reopened') { - $branch = $attributes['source_branch']; - $commit = $attributes['last_commit']; - $committer = $commit['author']['email']; + // build on merge request events + if (isset($payload['object_kind']) && $payload['object_kind'] == 'merge_request') { + $attributes = $payload['object_attributes']; + if ($attributes['state'] == 'opened' || $attributes['state'] == 'reopened') { + $branch = $attributes['source_branch']; + $commit = $attributes['last_commit']; + $committer = $commit['author']['email']; - $this->createBuild($project, $commit['id'], $branch, $committer, $commit['message']); - } + return $this->createBuild($project, $commit['id'], $branch, $committer, $commit['message']); } - - // build on push events - if (isset($payload['commits']) && is_array($payload['commits'])) { - // If we have a list of commits, then add them all as builds to be tested: - - foreach ($payload['commits'] as $commit) { - $branch = str_replace('refs/heads/', '', $payload['ref']); - $committer = $commit['author']['email']; - $this->createBuild($project, $commit['id'], $branch, $committer, $commit['message']); - } - } - - } catch (\Exception $ex) { - $response->setResponseCode(500); - $response->setContent(array('status' => 'failed', 'error' => $ex->getMessage())); } - return $response; + // build on push events + if (isset($payload['commits']) && is_array($payload['commits'])) { + // If we have a list of commits, then add them all as builds to be tested: + + $results = array(); + $status = 'failed'; + foreach ($payload['commits'] as $commit) { + try { + $branch = str_replace('refs/heads/', '', $payload['ref']); + $committer = $commit['author']['email']; + $results[$commit['id']] = $this->createBuild( + $project, + $commit['id'], + $branch, + $committer, + $commit['message'] + ); + $status = 'ok'; + } catch (Exception $ex) { + $results[$commit['id']] = array('status' => 'failed', 'error' => $ex->getMessage()); + } + } + return array('status' => $status, 'commits' => $results); + } + + return array('status' => 'ignored', 'message' => 'Unusable payload.'); } /** * Wrapper for creating a new build. - * @param $projectId - * @param $commitId - * @param $branch - * @param $committer - * @param $commitMessage - * @param null $extra - * @return bool - * @throws \Exception + * + * @param Project $project + * @param string $commitId + * @param string $branch + * @param string $committer + * @param string $commitMessage + * @param array $extra + * + * @return array + * + * @throws Exception */ - protected function createBuild($projectId, $commitId, $branch, $committer, $commitMessage, $extra = null) - { + protected function createBuild( + Project $project, + $commitId, + $branch, + $committer, + $commitMessage, + array $extra = null + ) { // Check if a build already exists for this commit ID: - $builds = $this->buildStore->getByProjectAndCommit($projectId, $commitId); + $builds = $this->buildStore->getByProjectAndCommit($project->getId(), $commitId); if ($builds['count']) { - return true; - } - - $project = $this->projectStore->getById($projectId); - - if (empty($project)) { - throw new \Exception('Project does not exist:' . $projectId); + return array( + 'status' => 'ignored', + 'message' => sprintf('Duplicate of build #%d', $builds['items'][0]->getId()) + ); } // If not, create a new build job for it: @@ -335,6 +367,34 @@ class WebhookController extends \PHPCI\Controller // Send a status postback if the build type provides one: $build->sendStatusPostback(); - return true; + return array('status' => 'ok', 'buildID' => $build->getID()); + } + + /** + * Fetch a project and check its type. + * + * @param int $projectId + * @param array|string $expectedType + * + * @return Project + * + * @throws Exception If the project does not exist or is not of the expected type. + */ + protected function fetchProject($projectId, $expectedType) + { + $project = $this->projectStore->getById($projectId); + + if (empty($projectId)) { + throw new Exception('Project does not exist: ' . $projectId); + } + + if (is_array($expectedType) + ? !in_array($project->getType(), $expectedType) + : $project->getType() !== $expectedType + ) { + throw new Exception('Wrong project type: ' . $project->getType()); + } + + return $project; } } diff --git a/Tests/PHPCI/Controller/WebhookControllerTest.php b/Tests/PHPCI/Controller/WebhookControllerTest.php new file mode 100644 index 00000000..ddd13fc0 --- /dev/null +++ b/Tests/PHPCI/Controller/WebhookControllerTest.php @@ -0,0 +1,41 @@ +prophesize('b8\Config')->reveal(), + $this->prophesize('b8\Http\Request')->reveal(), + $this->prophesize('b8\Http\Response')->reveal() + ); + + $error = $webController->handleAction('test', []); + + $this->assertInstanceOf('b8\Http\Response\JsonResponse', $error); + + $responseData = $error->getData(); + $this->assertEquals(500, $responseData['code']); + + $this->assertEquals('failed', $responseData['body']['status']); + + $this->assertEquals('application/json', $responseData['headers']['Content-Type']); + + // @todo: we can't text the result is JSON file with + // $this->assertJson((string) $error); + // since the flush method automatically add the header and break the + // testing framework. + } +} From 067a60983fce1497482adf1802901df5820ddcb6 Mon Sep 17 00:00:00 2001 From: zviryatko Date: Wed, 25 Feb 2015 16:16:23 +0200 Subject: [PATCH 22/57] Fix archive link. --- PHPCI/View/layout.phtml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PHPCI/View/layout.phtml b/PHPCI/View/layout.phtml index 72ef27ff..82eabfe5 100644 --- a/PHPCI/View/layout.phtml +++ b/PHPCI/View/layout.phtml @@ -138,7 +138,7 @@
From f25b1d25dcea411f8273f4cb40dfc94a8e0c187b Mon Sep 17 00:00:00 2001 From: Adirelle Date: Tue, 14 Apr 2015 12:17:52 +0200 Subject: [PATCH 29/57] Let CommandExecutor::findBinary throw an exception when the binary is missing. Close #910 --- PHPCI/Builder.php | 8 +++--- PHPCI/Helper/BaseCommandExecutor.php | 31 +++++++++++----------- PHPCI/Helper/CommandExecutor.php | 7 +++-- PHPCI/Plugin/Codeception.php | 6 ----- PHPCI/Plugin/Composer.php | 5 ---- PHPCI/Plugin/Pdepend.php | 7 +---- PHPCI/Plugin/Phing.php | 5 ---- PHPCI/Plugin/PhpCodeSniffer.php | 5 ---- PHPCI/Plugin/PhpCpd.php | 7 +---- PHPCI/Plugin/PhpCsFixer.php | 5 ---- PHPCI/Plugin/PhpDocblockChecker.php | 5 ---- PHPCI/Plugin/PhpLoc.php | 5 ---- PHPCI/Plugin/PhpMessDetector.php | 5 ---- PHPCI/Plugin/PhpParallelLint.php | 5 ---- PHPCI/Plugin/PhpSpec.php | 5 ---- PHPCI/Plugin/PhpUnit.php | 12 --------- PHPCI/Plugin/Xmpp.php | 7 +---- Tests/PHPCI/Helper/CommandExecutorTest.php | 19 ++++++++++++- 18 files changed, 46 insertions(+), 103 deletions(-) diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index b2a135f4..39e8ca41 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -259,12 +259,14 @@ class Builder implements LoggerAwareInterface /** * Find a binary required by a plugin. - * @param $binary + * @param string $binary + * @param bool $quiet + * * @return null|string */ - public function findBinary($binary) + public function findBinary($binary, $quiet = false) { - return $this->commandExecutor->findBinary($binary, $this->buildPath); + return $this->commandExecutor->findBinary($binary, $quiet = false); } /** diff --git a/PHPCI/Helper/BaseCommandExecutor.php b/PHPCI/Helper/BaseCommandExecutor.php index 5435d597..bd948834 100644 --- a/PHPCI/Helper/BaseCommandExecutor.php +++ b/PHPCI/Helper/BaseCommandExecutor.php @@ -9,9 +9,9 @@ namespace PHPCI\Helper; -use \PHPCI\Logging\BuildLogger; +use Exception; +use PHPCI\Logging\BuildLogger; use Psr\Log\LogLevel; -use PHPCI\Helper\Lang; /** * Handles running system commands with variables. @@ -20,7 +20,7 @@ use PHPCI\Helper\Lang; abstract class BaseCommandExecutor implements CommandExecutor { /** - * @var \PHPCI\Logging\BuildLogger + * @var BuildLogger */ protected $logger; @@ -144,13 +144,12 @@ abstract class BaseCommandExecutor implements CommandExecutor /** * Find a binary required by a plugin. * @param string $binary - * @param null $buildPath + * @param bool $quiet * @return null|string */ - public function findBinary($binary, $buildPath = null) + public function findBinary($binary, $quiet = false) { - $binaryPath = null; - $composerBin = $this->getComposerBinDir(realpath($buildPath)); + $composerBin = $this->getComposerBinDir(realpath($this->buildPath)); if (is_string($binary)) { $binary = array($binary); @@ -161,30 +160,30 @@ abstract class BaseCommandExecutor implements CommandExecutor if (is_dir($composerBin) && is_file($composerBin.'/'.$bin)) { $this->logger->log(Lang::get('found_in_path', $composerBin, $bin), LogLevel::DEBUG); - $binaryPath = $composerBin . '/' . $bin; - break; + return $composerBin . '/' . $bin; } if (is_file($this->rootDir . $bin)) { $this->logger->log(Lang::get('found_in_path', 'root', $bin), LogLevel::DEBUG); - $binaryPath = $this->rootDir . $bin; - break; + return $this->rootDir . $bin; } if (is_file($this->rootDir . 'vendor/bin/' . $bin)) { $this->logger->log(Lang::get('found_in_path', 'vendor/bin', $bin), LogLevel::DEBUG); - $binaryPath = $this->rootDir . 'vendor/bin/' . $bin; - break; + return $this->rootDir . 'vendor/bin/' . $bin; } $findCmdResult = $this->findGlobalBinary($bin); if (is_file($findCmdResult)) { $this->logger->log(Lang::get('found_in_path', '', $bin), LogLevel::DEBUG); - $binaryPath = $findCmdResult; - break; + return $findCmdResult; } } - return $binaryPath; + + if ($quiet) { + return; + } + throw new Exception(Lang::get('could_not_find', implode('/', $binary))); } /** diff --git a/PHPCI/Helper/CommandExecutor.php b/PHPCI/Helper/CommandExecutor.php index bacd1a2e..4f0028eb 100644 --- a/PHPCI/Helper/CommandExecutor.php +++ b/PHPCI/Helper/CommandExecutor.php @@ -26,10 +26,13 @@ interface CommandExecutor /** * Find a binary required by a plugin. * @param string $binary - * @param string $buildPath the current build path + * @param bool $quiet Returns null instead of throwing an execption. + * * @return null|string + * + * @throws \Exception when no binary has been found and $quiet is false. */ - public function findBinary($binary, $buildPath = null); + public function findBinary($binary, $quiet = false); /** * Set the buildPath property. diff --git a/PHPCI/Plugin/Codeception.php b/PHPCI/Plugin/Codeception.php index 7d7fd81e..9a651bec 100644 --- a/PHPCI/Plugin/Codeception.php +++ b/PHPCI/Plugin/Codeception.php @@ -133,12 +133,6 @@ class Codeception implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin } else { $codecept = $this->phpci->findBinary('codecept'); - if (!$codecept) { - $this->phpci->logFailure(Lang::get('could_not_find', 'codecept')); - - return false; - } - $cmd = 'cd "%s" && ' . $codecept . ' run -c "%s" --tap ' . $this->args; if (IS_WIN) { diff --git a/PHPCI/Plugin/Composer.php b/PHPCI/Plugin/Composer.php index 3930f3d6..87a558fe 100644 --- a/PHPCI/Plugin/Composer.php +++ b/PHPCI/Plugin/Composer.php @@ -81,11 +81,6 @@ class Composer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin { $composerLocation = $this->phpci->findBinary(array('composer', 'composer.phar')); - if (!$composerLocation) { - $this->phpci->logFailure(Lang::get('could_not_find', 'composer')); - return false; - } - $cmd = ''; if (IS_WIN) { diff --git a/PHPCI/Plugin/Pdepend.php b/PHPCI/Plugin/Pdepend.php index d1039554..73b669c1 100644 --- a/PHPCI/Plugin/Pdepend.php +++ b/PHPCI/Plugin/Pdepend.php @@ -79,15 +79,10 @@ class Pdepend implements \PHPCI\Plugin $pdepend = $this->phpci->findBinary('pdepend'); - if (!$pdepend) { - $this->phpci->logFailure(Lang::get('could_not_find', 'pdepend')); - return false; - } - $cmd = $pdepend . ' --summary-xml="%s" --jdepend-chart="%s" --overview-pyramid="%s" %s "%s"'; $this->removeBuildArtifacts(); - + // If we need to ignore directories if (count($this->phpci->ignore)) { $ignore = ' --ignore=' . implode(',', $this->phpci->ignore); diff --git a/PHPCI/Plugin/Phing.php b/PHPCI/Plugin/Phing.php index 2bf64cca..3a5bd834 100644 --- a/PHPCI/Plugin/Phing.php +++ b/PHPCI/Plugin/Phing.php @@ -81,11 +81,6 @@ class Phing implements \PHPCI\Plugin { $phingExecutable = $this->phpci->findBinary('phing'); - if (!$phingExecutable) { - $this->phpci->logFailure(Lang::get('could_not_find', 'phing')); - return false; - } - $cmd[] = $phingExecutable . ' -f ' . $this->getBuildFilePath(); if ($this->getPropertyFile()) { diff --git a/PHPCI/Plugin/PhpCodeSniffer.php b/PHPCI/Plugin/PhpCodeSniffer.php index df276eac..877d24c6 100644 --- a/PHPCI/Plugin/PhpCodeSniffer.php +++ b/PHPCI/Plugin/PhpCodeSniffer.php @@ -149,11 +149,6 @@ class PhpCodeSniffer implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin $phpcs = $this->phpci->findBinary('phpcs'); - if (!$phpcs) { - $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpcs')); - return false; - } - $this->phpci->logExecOutput(false); $cmd = $phpcs . ' --report=json %s %s %s %s %s "%s"'; diff --git a/PHPCI/Plugin/PhpCpd.php b/PHPCI/Plugin/PhpCpd.php index c663db5a..6433308f 100644 --- a/PHPCI/Plugin/PhpCpd.php +++ b/PHPCI/Plugin/PhpCpd.php @@ -90,18 +90,13 @@ class PhpCpd implements \PHPCI\Plugin $phpcpd = $this->phpci->findBinary('phpcpd'); - if (!$phpcpd) { - $this->phpci->logFailure(Lang::get('could_not_find', 'phpcpd')); - return false; - } - $tmpfilename = tempnam('/tmp', 'phpcpd'); $cmd = $phpcpd . ' --log-pmd "%s" %s "%s"'; $success = $this->phpci->executeCommand($cmd, $tmpfilename, $ignore, $this->path); print $this->phpci->getLastOutput(); - + list($errorCount, $data) = $this->processReport(file_get_contents($tmpfilename)); $this->build->storeMeta('phpcpd-warnings', $errorCount); $this->build->storeMeta('phpcpd-data', $data); diff --git a/PHPCI/Plugin/PhpCsFixer.php b/PHPCI/Plugin/PhpCsFixer.php index 1374bc71..e07db718 100644 --- a/PHPCI/Plugin/PhpCsFixer.php +++ b/PHPCI/Plugin/PhpCsFixer.php @@ -69,11 +69,6 @@ class PhpCsFixer implements \PHPCI\Plugin $phpcsfixer = $this->phpci->findBinary('php-cs-fixer'); - if (!$phpcsfixer) { - $this->phpci->logFailure(Lang::get('could_not_find', 'php-cs-fixer')); - return false; - } - $cmd = $phpcsfixer . ' fix . %s %s %s'; $success = $this->phpci->executeCommand($cmd, $this->verbose, $this->diff, $this->level); diff --git a/PHPCI/Plugin/PhpDocblockChecker.php b/PHPCI/Plugin/PhpDocblockChecker.php index 9f71afef..7fb0fe11 100644 --- a/PHPCI/Plugin/PhpDocblockChecker.php +++ b/PHPCI/Plugin/PhpDocblockChecker.php @@ -104,11 +104,6 @@ class PhpDocblockChecker implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin // Check that the binary exists: $checker = $this->phpci->findBinary('phpdoccheck'); - if (!$checker) { - $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpdoccheck')); - return false; - } - // Build ignore string: $ignore = ''; if (count($this->ignore)) { diff --git a/PHPCI/Plugin/PhpLoc.php b/PHPCI/Plugin/PhpLoc.php index 65398e05..76887493 100644 --- a/PHPCI/Plugin/PhpLoc.php +++ b/PHPCI/Plugin/PhpLoc.php @@ -80,11 +80,6 @@ class PhpLoc implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin $phploc = $this->phpci->findBinary('phploc'); - if (!$phploc) { - $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phploc')); - return false; - } - $success = $this->phpci->executeCommand($phploc . ' %s "%s"', $ignore, $this->directory); $output = $this->phpci->getLastOutput(); diff --git a/PHPCI/Plugin/PhpMessDetector.php b/PHPCI/Plugin/PhpMessDetector.php index 21c171cb..b02f5f09 100644 --- a/PHPCI/Plugin/PhpMessDetector.php +++ b/PHPCI/Plugin/PhpMessDetector.php @@ -121,11 +121,6 @@ class PhpMessDetector implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin $phpmdBinaryPath = $this->phpci->findBinary('phpmd'); - if (!$phpmdBinaryPath) { - $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpmd')); - return false; - } - $this->executePhpMd($phpmdBinaryPath); list($errorCount, $data) = $this->processReport(trim($this->phpci->getLastOutput())); diff --git a/PHPCI/Plugin/PhpParallelLint.php b/PHPCI/Plugin/PhpParallelLint.php index fdaeaf65..8b7528de 100644 --- a/PHPCI/Plugin/PhpParallelLint.php +++ b/PHPCI/Plugin/PhpParallelLint.php @@ -78,11 +78,6 @@ class PhpParallelLint implements \PHPCI\Plugin $phplint = $this->phpci->findBinary('parallel-lint'); - if (!$phplint) { - $this->phpci->logFailure(Lang::get('could_not_find', 'parallel-lint')); - return false; - } - $cmd = $phplint . ' %s "%s"'; $success = $this->phpci->executeCommand( $cmd, diff --git a/PHPCI/Plugin/PhpSpec.php b/PHPCI/Plugin/PhpSpec.php index 681a5a6c..e468a718 100644 --- a/PHPCI/Plugin/PhpSpec.php +++ b/PHPCI/Plugin/PhpSpec.php @@ -59,11 +59,6 @@ class PhpSpec implements PHPCI\Plugin $phpspec = $this->phpci->findBinary(array('phpspec', 'phpspec.php')); - if (!$phpspec) { - $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpspec')); - return false; - } - $success = $this->phpci->executeCommand($phpspec . ' --format=junit --no-code-generation run'); $output = $this->phpci->getLastOutput(); diff --git a/PHPCI/Plugin/PhpUnit.php b/PHPCI/Plugin/PhpUnit.php index 70e0e74f..7fb626df 100644 --- a/PHPCI/Plugin/PhpUnit.php +++ b/PHPCI/Plugin/PhpUnit.php @@ -197,15 +197,8 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin chdir($this->phpci->buildPath.'/'.$this->runFrom); } - $phpunit = $this->phpci->findBinary('phpunit'); - if (!$phpunit) { - $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpunit')); - return false; - } - - $cmd = $phpunit . ' --tap %s -c "%s" ' . $this->coverage . $this->path; $success = $this->phpci->executeCommand($cmd, $this->args, $this->phpci->buildPath . $configPath); @@ -232,11 +225,6 @@ class PhpUnit implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin $phpunit = $this->phpci->findBinary('phpunit'); - if (!$phpunit) { - $this->phpci->logFailure(PHPCI\Helper\Lang::get('could_not_find', 'phpunit')); - return false; - } - $cmd = $phpunit . ' --tap %s "%s"'; $success = $this->phpci->executeCommand($cmd, $this->args, $this->phpci->buildPath . $directory); chdir($curdir); diff --git a/PHPCI/Plugin/Xmpp.php b/PHPCI/Plugin/Xmpp.php index add778cb..0362aa85 100644 --- a/PHPCI/Plugin/Xmpp.php +++ b/PHPCI/Plugin/Xmpp.php @@ -148,12 +148,7 @@ class XMPP implements \PHPCI\Plugin */ public function execute() { - $sendxmpp = $this->phpci->findBinary('/usr/bin/sendxmpp'); - - if (!$sendxmpp) { - $this->phpci->logFailure('Could not find sendxmpp.'); - return false; - } + $sendxmpp = $this->phpci->findBinary('sendxmpp'); /* * Without recipients we can't send notification diff --git a/Tests/PHPCI/Helper/CommandExecutorTest.php b/Tests/PHPCI/Helper/CommandExecutorTest.php index 4cf14887..5d5dc08b 100644 --- a/Tests/PHPCI/Helper/CommandExecutorTest.php +++ b/Tests/PHPCI/Helper/CommandExecutorTest.php @@ -27,7 +27,8 @@ class CommandExecutorTest extends \PHPUnit_Framework_TestCase } parent::setUp(); $mockBuildLogger = $this->prophesize('PHPCI\Logging\BuildLogger'); - $this->testedExecutor = new UnixCommandExecutor($mockBuildLogger->reveal(), __DIR__ . "/"); + $class = IS_WIN ? 'PHPCI\Helper\WindowsCommandExecutor' : 'PHPCI\Helper\UnixCommandExecutor'; + $this->testedExecutor = new $class($mockBuildLogger->reveal(), __DIR__ . "/"); } public function testGetLastOutput_ReturnsOutputOfCommand() @@ -63,4 +64,20 @@ class CommandExecutorTest extends \PHPUnit_Framework_TestCase $returnValue = $this->testedExecutor->findBinary($thisFileName); $this->assertEquals(__DIR__ . "/" . $thisFileName, $returnValue); } + + /** + * @expectedException \Exception + * @expectedMessageRegex WorldWidePeace + */ + public function testFindBinary_ThrowsWhenNotFound() + { + $thisFileName = "WorldWidePeace"; + $this->testedExecutor->findBinary($thisFileName); + } + + public function testFindBinary_ReturnsNullWihQuietArgument() + { + $thisFileName = "WorldWidePeace"; + $this->assertNull($this->testedExecutor->findBinary($thisFileName, true)); + } } From 290c34a27da14b8632bcc3a2a5cc05e68f0ab3b3 Mon Sep 17 00:00:00 2001 From: Adirelle Date: Tue, 14 Apr 2015 09:43:21 +0200 Subject: [PATCH 30/57] Updated the php_codesniffer required version and added a default phpcs.xml. Added a PHPMD configuration file. Updated phpci.yml to use the configuration files. Close #913 --- composer.json | 2 +- composer.lock | 18 ++++++++++++------ phpci.yml | 4 +++- phpcs.xml | 19 +++++++++++++++++++ phpmd.xml | 17 +++++++++++++++++ 5 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 phpcs.xml create mode 100644 phpmd.xml diff --git a/composer.json b/composer.json index 03d752a5..c6d8e92b 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "require-dev": { "phpunit/phpunit": "~4.5", "phpmd/phpmd": "~2.0", - "squizlabs/php_codesniffer": "~2.0", + "squizlabs/php_codesniffer": "~2.3", "block8/php-docblock-checker": "~1.0", "phploc/phploc": "~2.0" }, diff --git a/composer.lock b/composer.lock index 60b54a4e..dbbedd22 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "0c9efd3a0b9e924c7465e03fc97ffed7", + "hash": "a4a95f2b83e336b9e1b285c04af26ce7", "packages": [ { "name": "block8/b8framework", @@ -1851,20 +1851,21 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "b301c98f19414d836fdaa678648745fcca5aeb4f" + "reference": "5046b0e01c416fc2b06df961d0673c85bcdc896c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/b301c98f19414d836fdaa678648745fcca5aeb4f", - "reference": "b301c98f19414d836fdaa678648745fcca5aeb4f", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5046b0e01c416fc2b06df961d0673c85bcdc896c", + "reference": "5046b0e01c416fc2b06df961d0673c85bcdc896c", "shasum": "" }, "require": { "ext-tokenizer": "*", + "ext-xmlwriter": "*", "php": ">=5.1.2" }, "bin": [ @@ -1872,6 +1873,11 @@ "scripts/phpcbf" ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "classmap": [ "CodeSniffer.php", @@ -1915,7 +1921,7 @@ "phpcs", "standards" ], - "time": "2015-01-21 22:44:05" + "time": "2015-03-04 02:07:03" }, { "name": "symfony/dependency-injection", diff --git a/phpci.yml b/phpci.yml index 8f51c88f..e794939e 100644 --- a/phpci.yml +++ b/phpci.yml @@ -21,8 +21,10 @@ test: - vendor/ php_mess_detector: allowed_warnings: 0 + rules: + - phpmd.xml php_code_sniffer: - standard: "PSR2" + standard: phpcs.xml allowed_warnings: 0 allowed_errors: 0 php_loc: diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 00000000..a392a201 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,19 @@ + + + + Codestyle ruleset for PHPCI + + + + PHPCI + + + + + PHPCI/Migrations/* + PHPCI/Model/Base/* + PHPCI/Languages/* + Tests/* + vendor/* + + diff --git a/phpmd.xml b/phpmd.xml new file mode 100644 index 00000000..69b822fd --- /dev/null +++ b/phpmd.xml @@ -0,0 +1,17 @@ + + + + PHPCI rule set + + + + + + + From 81fbc6a5a0d4e4ae693f209a7bbb4a7882577310 Mon Sep 17 00:00:00 2001 From: rm3nchaca Date: Wed, 15 Apr 2015 15:17:06 -0500 Subject: [PATCH 31/57] fix file link in plugins Running builds leave a file link with an error like "http://gitlab.example.com/root/project/blob/master/index.php#L6" but it is pointing to the actual file, not the file with a bug, example "http://gitlab.example.com/root/project/blob/97f0a6453d5913f4b55d660fbf2d629240ca7237/index.php#L6" Close #915 --- PHPCI/Model/Build/GitlabBuild.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PHPCI/Model/Build/GitlabBuild.php b/PHPCI/Model/Build/GitlabBuild.php index 086bc046..a1e0562c 100644 --- a/PHPCI/Model/Build/GitlabBuild.php +++ b/PHPCI/Model/Build/GitlabBuild.php @@ -47,7 +47,7 @@ class GitlabBuild extends RemoteGitBuild 'http://%s/%s/blob/%s/{FILE}#L{LINE}', $this->getProject()->getAccessInformation("domain"), $this->getProject()->getReference(), - $this->getBranch() + $this->getCommitId() ); } From f7ca64bf6de55d6556225c7207e46fe35ecdbf12 Mon Sep 17 00:00:00 2001 From: Adam Henley Date: Sun, 19 Apr 2015 20:32:55 +1200 Subject: [PATCH 32/57] SMTP Password not masked PR #921 Signed-off-by: Adam Henley Close #923 --- PHPCI/Controller/SettingsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PHPCI/Controller/SettingsController.php b/PHPCI/Controller/SettingsController.php index aaaa637f..ea15bc3b 100644 --- a/PHPCI/Controller/SettingsController.php +++ b/PHPCI/Controller/SettingsController.php @@ -329,7 +329,7 @@ class SettingsController extends Controller $field->setContainerClass('form-group'); $form->addField($field); - $field = new Form\Element\Text('smtp_password'); + $field = new Form\Element\Password('smtp_password'); $field->setRequired(false); $field->setLabel(Lang::get('smtp_password')); $field->setClass('form-control'); From c0568d3a4b93b104061c3ad6216b693068b35a92 Mon Sep 17 00:00:00 2001 From: Alexander Garzon Date: Tue, 21 Apr 2015 18:52:42 -0400 Subject: [PATCH 33/57] Update lang.es.php Missing translation for "archived" Close #931 --- PHPCI/Languages/lang.es.php | 1 + 1 file changed, 1 insertion(+) diff --git a/PHPCI/Languages/lang.es.php b/PHPCI/Languages/lang.es.php index 7c9f5a62..95a6eb73 100644 --- a/PHPCI/Languages/lang.es.php +++ b/PHPCI/Languages/lang.es.php @@ -114,6 +114,7 @@ PHPCI', (en caso que no puedas agregar el archivo phpci.yml al repositorio)', 'default_branch' => 'Nombre de la rama por defecto', 'allow_public_status' => '¿Activar página pública con el estado del proyecto?', + 'archived' => 'Archivado', 'save_project' => 'Guardar Proyecto', 'error_mercurial' => 'La URL del repositorio de Mercurial debe comenzar con http:// or https://', From 1b7f0bbb4b79500b45dedf768e332f9cf187937a Mon Sep 17 00:00:00 2001 From: corpsee Date: Tue, 17 Mar 2015 15:11:05 +0600 Subject: [PATCH 34/57] Improved login: now you can login using name or email Close #873 --- PHPCI/Controller/SessionController.php | 4 +-- PHPCI/Languages/lang.da.php | 1 + PHPCI/Languages/lang.de.php | 1 + PHPCI/Languages/lang.el.php | 1 + PHPCI/Languages/lang.en.php | 1 + PHPCI/Languages/lang.fr.php | 1 + PHPCI/Languages/lang.it.php | 1 + PHPCI/Languages/lang.nl.php | 1 + PHPCI/Languages/lang.pl.php | 1 + PHPCI/Languages/lang.ru.php | 1 + PHPCI/Languages/lang.uk.php | 1 + ...4958_unique_email_and_name_user_fields.php | 30 +++++++++++++++++++ PHPCI/Store/Base/UserStoreBase.php | 28 ++++++++++++++++- 13 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 PHPCI/Migrations/20150324174958_unique_email_and_name_user_fields.php diff --git a/PHPCI/Controller/SessionController.php b/PHPCI/Controller/SessionController.php index eb7001df..a5f40ffb 100644 --- a/PHPCI/Controller/SessionController.php +++ b/PHPCI/Controller/SessionController.php @@ -49,7 +49,7 @@ class SessionController extends \PHPCI\Controller } else { unset($_SESSION['login_token']); - $user = $this->userStore->getByEmail($this->getParam('email')); + $user = $this->userStore->getByLoginOrEmail($this->getParam('email')); if ($user && password_verify($this->getParam('password', ''), $user->getHash())) { session_regenerate_id(true); @@ -68,7 +68,7 @@ class SessionController extends \PHPCI\Controller $form->setAction(PHPCI_URL.'session/login'); $email = new b8\Form\Element\Email('email'); - $email->setLabel(Lang::get('email_address')); + $email->setLabel(Lang::get('login')); $email->setRequired(true); $email->setContainerClass('form-group'); $email->setClass('form-control'); diff --git a/PHPCI/Languages/lang.da.php b/PHPCI/Languages/lang.da.php index b65f9ef9..20e403e1 100644 --- a/PHPCI/Languages/lang.da.php +++ b/PHPCI/Languages/lang.da.php @@ -39,6 +39,7 @@ PHPCI', 'reset_email_title' => 'PHPCI Adgangskode-nulstilling for %s', 'reset_invalid' => 'Ugyldig anmodning om adgangskode-nulstilling.', 'email_address' => 'Email-addresse', + 'login' => 'Login / Email Address', 'password' => 'Adgangskode', 'log_in' => 'Log ind', diff --git a/PHPCI/Languages/lang.de.php b/PHPCI/Languages/lang.de.php index 393459a1..8a08e37d 100644 --- a/PHPCI/Languages/lang.de.php +++ b/PHPCI/Languages/lang.de.php @@ -39,6 +39,7 @@ PHPCI', 'reset_email_title' => 'PHPCI Passwort zurücksetzen für %s', 'reset_invalid' => 'Fehlerhafte Anfrage für das Zurücksetzen eines Passwortes', 'email_address' => 'Emailadresse', + 'login' => 'Login / Email Address', 'password' => 'Passwort', 'log_in' => 'Einloggen', diff --git a/PHPCI/Languages/lang.el.php b/PHPCI/Languages/lang.el.php index e97da6d3..3e3a3b84 100644 --- a/PHPCI/Languages/lang.el.php +++ b/PHPCI/Languages/lang.el.php @@ -39,6 +39,7 @@ PHPCI', 'reset_email_title' => 'PHPCI Επαναφορά Κωδικού για %s', 'reset_invalid' => 'Μη έγκυρο αίτημα επαναφοράς κωδικού πρόσβασης.', 'email_address' => 'Διεύθυνση email', + 'login' => 'Login / Email Address', 'password' => 'Κωδικός πρόσβασης', 'log_in' => 'Είσοδος', diff --git a/PHPCI/Languages/lang.en.php b/PHPCI/Languages/lang.en.php index 19d41cbe..d11a8b39 100644 --- a/PHPCI/Languages/lang.en.php +++ b/PHPCI/Languages/lang.en.php @@ -39,6 +39,7 @@ PHPCI', 'reset_email_title' => 'PHPCI Password Reset for %s', 'reset_invalid' => 'Invalid password reset request.', 'email_address' => 'Email Address', + 'login' => 'Login / Email Address', 'password' => 'Password', 'log_in' => 'Log in', diff --git a/PHPCI/Languages/lang.fr.php b/PHPCI/Languages/lang.fr.php index a8de5991..f1ad7129 100644 --- a/PHPCI/Languages/lang.fr.php +++ b/PHPCI/Languages/lang.fr.php @@ -39,6 +39,7 @@ PHPCI', 'reset_email_title' => 'Réinitialisation du mot de passe PHPCI pour %s', 'reset_invalid' => 'Requête de réinitialisation de mot de passe invalide.', 'email_address' => 'Adresse email', + 'login' => 'Login / Email Address', 'password' => 'Mot de passe', 'log_in' => 'Connexion', diff --git a/PHPCI/Languages/lang.it.php b/PHPCI/Languages/lang.it.php index f8f41ea8..ff326d14 100644 --- a/PHPCI/Languages/lang.it.php +++ b/PHPCI/Languages/lang.it.php @@ -39,6 +39,7 @@ PHPCI', 'reset_email_title' => 'Ripristino della password di PHPCI per %s', 'reset_invalid' => 'Richeista di ripristino password non valida.', 'email_address' => 'Indirizzo Email', + 'login' => 'Login / Email Address', 'password' => 'Password', 'log_in' => 'Accedi', diff --git a/PHPCI/Languages/lang.nl.php b/PHPCI/Languages/lang.nl.php index f3c0a7c5..e0638aaf 100644 --- a/PHPCI/Languages/lang.nl.php +++ b/PHPCI/Languages/lang.nl.php @@ -39,6 +39,7 @@ PHPCI', 'reset_email_title' => 'PHPCI wachtwoord reset voor %s', 'reset_invalid' => 'Ongeldig wachtwoord reset verzoek', 'email_address' => 'E-mailadres', + 'login' => 'Login / Email Address', 'password' => 'Wachtwoord', 'log_in' => 'Log in', diff --git a/PHPCI/Languages/lang.pl.php b/PHPCI/Languages/lang.pl.php index 37a78fb6..d6f95ad6 100644 --- a/PHPCI/Languages/lang.pl.php +++ b/PHPCI/Languages/lang.pl.php @@ -39,6 +39,7 @@ PHPCI', 'reset_email_title' => 'Reset Hasła PHPCI dla %s', 'reset_invalid' => 'Prośba o zmianę hasła jest nieważna.', 'email_address' => 'Adres email', + 'login' => 'Login / Email Address', 'password' => 'Hasło', 'log_in' => 'Zaloguj się', diff --git a/PHPCI/Languages/lang.ru.php b/PHPCI/Languages/lang.ru.php index 7627db85..a13c4a18 100644 --- a/PHPCI/Languages/lang.ru.php +++ b/PHPCI/Languages/lang.ru.php @@ -38,6 +38,7 @@ PHPCI', 'reset_email_title' => 'Сброс пароля PHPCI для %s', 'reset_invalid' => 'Некорректный запрос на сброс пароля.', 'email_address' => 'Email', + 'login' => 'Логин / Email', 'password' => 'Пароль', 'log_in' => 'Войти', diff --git a/PHPCI/Languages/lang.uk.php b/PHPCI/Languages/lang.uk.php index 2b2cc027..a3ca1b37 100644 --- a/PHPCI/Languages/lang.uk.php +++ b/PHPCI/Languages/lang.uk.php @@ -39,6 +39,7 @@ PHPCI', 'reset_email_title' => 'Скидання пароль PHPCI для %s', 'reset_invalid' => 'Невірний запит скидання паролю.', 'email_address' => 'Email адреса', + 'login' => 'Логин / Email адреса', 'password' => 'Пароль', 'log_in' => 'Увійти', diff --git a/PHPCI/Migrations/20150324174958_unique_email_and_name_user_fields.php b/PHPCI/Migrations/20150324174958_unique_email_and_name_user_fields.php new file mode 100644 index 00000000..f8d24ba0 --- /dev/null +++ b/PHPCI/Migrations/20150324174958_unique_email_and_name_user_fields.php @@ -0,0 +1,30 @@ +table('user'); + $user_table + ->addIndex('email', array('unique' => true)) + ->addIndex('name', array('unique' => true)) + ->save(); + } + + /** + * Migrate Down. + */ + public function down() + { + $user_table = $this->table('user'); + $user_table + ->removeIndex('email', array('unique' => true)) + ->removeIndex('name', array('unique' => true)) + ->save(); + } +} diff --git a/PHPCI/Store/Base/UserStoreBase.php b/PHPCI/Store/Base/UserStoreBase.php index d91271d0..f2893ac5 100644 --- a/PHPCI/Store/Base/UserStoreBase.php +++ b/PHPCI/Store/Base/UserStoreBase.php @@ -59,7 +59,7 @@ class UserStoreBase extends Store /** * Returns a User model by Email. - * @param mixed $value + * @param string $value * @param string $useConnection * @throws HttpException * @return \@appNamespace\Model\User|null @@ -82,4 +82,30 @@ class UserStoreBase extends Store return null; } + + /** + * Returns a User model by Email. + * @param string $value + * @param string $useConnection + * @throws HttpException + * @return \@appNamespace\Model\User|null + */ + public function getByLoginOrEmail($value, $useConnection = 'read') + { + if (is_null($value)) { + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + } + + $query = 'SELECT * FROM `user` WHERE `name` = :value OR `email` = :value LIMIT 1'; + $stmt = Database::getConnection($useConnection)->prepare($query); + $stmt->bindValue(':value', $value); + + if ($stmt->execute()) { + if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) { + return new User($data); + } + } + + return null; + } } From 634b246ed5eb4b395fecd9a282423190d9232168 Mon Sep 17 00:00:00 2001 From: corpsee Date: Wed, 22 Apr 2015 16:24:03 +0600 Subject: [PATCH 35/57] Fixed ru strings for create build command (https://github.com/Block8/PHPCI/pull/889) Fixed ru strings for 'archived' Close #932 --- PHPCI/Languages/lang.ru.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PHPCI/Languages/lang.ru.php b/PHPCI/Languages/lang.ru.php index a13c4a18..aa0f40fb 100644 --- a/PHPCI/Languages/lang.ru.php +++ b/PHPCI/Languages/lang.ru.php @@ -113,7 +113,7 @@ PHPCI', (если вы не добавили файл phpci.yml в репозиторий вашего проекта)', 'default_branch' => 'Ветка по умолчанию', 'allow_public_status' => 'Разрешить публичный статус и изображение (статуса) для проекта', - 'archived' => 'Archived', + 'archived' => 'Запакован', 'save_project' => 'Сохранить проект', 'error_mercurial' => 'URL репозитория Mercurial должен начинаться с http:// или https://', @@ -338,10 +338,10 @@ PHPCI', 'incorrect_format' => 'Неверный формат', // Create Build Command - 'create_build_project' => 'Create a build for a project', - 'project_id_argument' => 'A project ID', - 'commit_id_option' => 'Commit ID to build', - 'branch_name_option' => 'Branch to build', + 'create_build_project' => 'Создать сборку проекта', + 'project_id_argument' => 'ID проекта', + 'commit_id_option' => 'ID коммита для сборки', + 'branch_name_option' => 'Ветка для сборки', // Run Command 'run_all_pending' => 'Запустить все ожидающие PHPCI сборки.', From 209454c5f67e9fa8d1042b2410cd8350eeb4fcb7 Mon Sep 17 00:00:00 2001 From: Adirelle Date: Tue, 21 Apr 2015 14:51:55 +0200 Subject: [PATCH 36/57] When starting a manual build, replace the "Manual" commit id with the HEAD hash. Close #928 --- PHPCI/Model/Build/RemoteGitBuild.php | 16 ++++++++-------- PHPCI/Service/BuildService.php | 2 ++ Tests/PHPCI/Service/BuildServiceTest.php | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/PHPCI/Model/Build/RemoteGitBuild.php b/PHPCI/Model/Build/RemoteGitBuild.php index 5d0c9419..faaccfb5 100644 --- a/PHPCI/Model/Build/RemoteGitBuild.php +++ b/PHPCI/Model/Build/RemoteGitBuild.php @@ -124,16 +124,16 @@ class RemoteGitBuild extends Build $success = true; $commit = $this->getCommitId(); + $chdir = IS_WIN ? 'cd /d "%s"' : 'cd "%s"'; + if (!empty($commit) && $commit != 'Manual') { - $cmd = 'cd "%s"'; + $cmd = $chdir . ' && git checkout %s --quiet'; + $success = $builder->executeCommand($cmd, $cloneTo, $commit); + } - if (IS_WIN) { - $cmd = 'cd /d "%s"'; - } - - $cmd .= ' && git checkout %s --quiet'; - - $success = $builder->executeCommand($cmd, $cloneTo, $this->getCommitId()); + // Always update the commit hash with the actual HEAD hash + if ($builder->executeCommand($chdir . ' && git rev-parse HEAD', $cloneTo)) { + $this->setCommitId(trim($builder->getLastOutput())); } return $success; diff --git a/PHPCI/Service/BuildService.php b/PHPCI/Service/BuildService.php index a95ac44f..ca2fae4d 100644 --- a/PHPCI/Service/BuildService.php +++ b/PHPCI/Service/BuildService.php @@ -9,6 +9,7 @@ namespace PHPCI\Service; +use PHPCI\Helper\Lang; use PHPCI\Model\Build; use PHPCI\Model\Project; use PHPCI\Store\BuildStore; @@ -59,6 +60,7 @@ class BuildService $build->setCommitId($commitId); } else { $build->setCommitId('Manual'); + $build->setCommitMessage(Lang::get('manual_build')); } if (!is_null($branch)) { diff --git a/Tests/PHPCI/Service/BuildServiceTest.php b/Tests/PHPCI/Service/BuildServiceTest.php index 426845a9..985f3088 100644 --- a/Tests/PHPCI/Service/BuildServiceTest.php +++ b/Tests/PHPCI/Service/BuildServiceTest.php @@ -57,7 +57,7 @@ class BuildServiceTest extends \PHPUnit_Framework_TestCase $this->assertNull($returnValue->getStarted()); $this->assertNull($returnValue->getFinished()); $this->assertNull($returnValue->getLog()); - $this->assertEmpty($returnValue->getCommitMessage()); + $this->assertEquals(\PHPCI\Helper\Lang::get('manual_build'), $returnValue->getCommitMessage()); $this->assertNull($returnValue->getCommitterEmail()); $this->assertNull($returnValue->getExtra()); $this->assertEquals('master', $returnValue->getBranch()); From 408eb5b974cb1af734053d78822621bc06ddd843 Mon Sep 17 00:00:00 2001 From: Adam Cooper Date: Mon, 8 Sep 2014 11:45:19 +0100 Subject: [PATCH 37/57] An attempt at making the codeception plugin a little more complete. Codeception JS plugin and theme changes. Improvements to the display. Extra total information plus some test file locations. Close #588 --- PHPCI/Languages/lang.el.php | 1 + PHPCI/Languages/lang.en.php | 6 + PHPCI/Plugin/Codeception.php | 178 ++++++++++-------- .../Util/TestResultParsers/Codeception.php | 108 +++++++++++ .../TestResultParsers/ParserInterface.php | 16 ++ public/assets/css/bootstrap-theme.min.css | 4 +- public/assets/css/bootstrap.min.css | 4 +- public/assets/js/bootstrap.min.js | 8 +- public/assets/js/build-plugins/codeception.js | 72 +++++-- 9 files changed, 294 insertions(+), 103 deletions(-) create mode 100644 PHPCI/Plugin/Util/TestResultParsers/Codeception.php create mode 100644 PHPCI/Plugin/Util/TestResultParsers/ParserInterface.php diff --git a/PHPCI/Languages/lang.el.php b/PHPCI/Languages/lang.el.php index 3e3a3b84..cb7d169f 100644 --- a/PHPCI/Languages/lang.el.php +++ b/PHPCI/Languages/lang.el.php @@ -172,6 +172,7 @@ Services του Bitbucket αποθετηρίου σας.', 'codeception_errors' => 'Λάθη Codeception', 'phpmd_warnings' => 'Προειδοποιήσεις PHPMD', 'phpcs_warnings' => 'Προειδοποιήσεις PHPCS ', + 'codeception_errors' => 'Λάθη Codeception', 'phpcs_errors' => 'Λάθη PHPCS', 'phplint_errors' => 'Λάθη Lint', 'phpunit_errors' => 'Λάθη PHPUnit ', diff --git a/PHPCI/Languages/lang.en.php b/PHPCI/Languages/lang.en.php index d11a8b39..d6c48754 100644 --- a/PHPCI/Languages/lang.en.php +++ b/PHPCI/Languages/lang.en.php @@ -190,6 +190,12 @@ PHPCI', 'technical_debt' => 'Technical Debt', 'behat' => 'Behat', + 'codeception_feature' => 'Feature', + 'codeception_suite' => 'Suite', + 'codeception_time' => 'Time', + 'codeception_synopsis' => '%1$d tests carried out in %2$f seconds. + %3$d failures.', + 'file' => 'File', 'line' => 'Line', 'class' => 'Class', diff --git a/PHPCI/Plugin/Codeception.php b/PHPCI/Plugin/Codeception.php index 9a651bec..fe12db76 100644 --- a/PHPCI/Plugin/Codeception.php +++ b/PHPCI/Plugin/Codeception.php @@ -9,50 +9,76 @@ namespace PHPCI\Plugin; -use PHPCI; use PHPCI\Builder; use PHPCI\Helper\Lang; use PHPCI\Model\Build; -use PHPCI\Plugin\Util\TapParser; +use PHPCI\Plugin\Util\TestResultParsers\Codeception as Parser; +use Psr\Log\LogLevel; /** - * Codeception Plugin - Enables full acceptance, unit, and functional testing - * + * Codeception Plugin - Enables full acceptance, unit, and functional testing. * @author Don Gilbert * @author Igor Timoshenko + * @author Adam Cooper * @package PHPCI * @subpackage Plugins */ -class Codeception implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin +class Codeception implements \PHPCI\Plugin, \PHPCI\ZeroConfigPlugin { - /** - * @var string - */ + /** @var string */ protected $args = ''; - /** - * @var Build - */ + /** @var Builder */ + protected $phpci; + + /** @var Build */ protected $build; /** - * @var Builder + * @var string $ymlConfigFile The path of a yml config for Codeception */ - protected $phpci; + protected $ymlConfigFile; /** - * @var string|string[] The path (or array of paths) of an yml config for Codeception + * @var string $path The path to the codeception tests folder. */ - protected $configFile; + protected $path; /** - * @var string The path where the reports and logs are stored + * @param $stage + * @param Builder $builder + * @param Build $build + * @return bool */ - protected $logPath = 'tests/_output'; + public static function canExecute($stage, Builder $builder, Build $build) + { + if ($stage == 'test' && !is_null(self::findConfigFile($builder->buildPath))) { + return true; + } + + return false; + } + + /** + * Try and find the codeception YML config file. + * @param $buildPath + * @return null|string + */ + public static function findConfigFile($buildPath) + { + if (file_exists($buildPath . 'codeception.yml')) { + return 'codeception.yml'; + } + + if (file_exists($buildPath . 'codeception.dist.yml')) { + return 'codeception.dist.yml'; + } + + return null; + } /** * Set up the plugin, configure options, etc. - * * @param Builder $phpci * @param Build $build * @param array $options @@ -61,104 +87,96 @@ class Codeception implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin { $this->phpci = $phpci; $this->build = $build; + $this->path = 'tests/'; - if (isset($options['config'])) { - $this->configFile = $options['config']; + if (empty($options['config'])) { + $this->ymlConfigFile = self::findConfigFile($this->phpci->buildPath); + } + if (isset($options['config'])) { + $this->ymlConfigFile = $options['config']; } - if (isset($options['args'])) { $this->args = (string) $options['args']; } - - if (isset($options['log_path'])) { - $this->logPath = $options['log_path']; + if (isset($options['path'])) { + $this->path = $options['path']; } } /** - * {@inheritDoc} + * Runs Codeception tests, optionally using specified config file(s). */ public function execute() { + if (empty($this->ymlConfigFile)) { + $this->phpci->logFailure('No configuration file found'); + return false; + } + $success = true; - $this->phpci->logExecOutput(false); - - // Run any config files first. This can be either a single value or an array - if ($this->configFile !== null) { - $success &= $this->runConfigFile($this->configFile); - } - - $tapString = file_get_contents( - $this->phpci->buildPath . $this->logPath . DIRECTORY_SEPARATOR . 'report.tap.log' - ); - - try { - $tapParser = new TapParser($tapString); - $output = $tapParser->parse(); - } catch (\Exception $ex) { - $this->phpci->logFailure($tapString); - - throw $ex; - } - - $failures = $tapParser->getTotalFailures(); - - $this->build->storeMeta('codeception-errors', $failures); - $this->build->storeMeta('codeception-data', $output); - - $this->phpci->logExecOutput(true); + // Run any config files first. This can be either a single value or an array. + $success &= $this->runConfigFile($this->ymlConfigFile); return $success; } /** - * {@inheritDoc} - */ - public static function canExecute($stage, Builder $builder, Build $build) - { - return $stage === 'test'; - } - - /** - * Run tests from a Codeception config file - * - * @param string $configPath + * Run tests from a Codeception config file. + * @param $configPath * @return bool|mixed + * @throws \Exception */ protected function runConfigFile($configPath) { if (is_array($configPath)) { return $this->recurseArg($configPath, array($this, 'runConfigFile')); } else { + $this->phpci->logExecOutput(false); + $codecept = $this->phpci->findBinary('codecept'); - $cmd = 'cd "%s" && ' . $codecept . ' run -c "%s" --tap ' . $this->args; + if (!$codecept) { + $this->phpci->logFailure(Lang::get('could_not_find', 'codecept')); + return false; + } + + $cmd = 'cd "%s" && ' . $codecept . ' run -c "%s" --xml ' . $this->args; if (IS_WIN) { - $cmd = 'cd /d "%s" && ' . $codecept . ' run -c "%s" --tap ' . $this->args; + $cmd = 'cd /d "%s" && ' . $codecept . ' run -c "%s" --xml ' . $this->args; } $configPath = $this->phpci->buildPath . $configPath; $success = $this->phpci->executeCommand($cmd, $this->phpci->buildPath, $configPath); + + $this->phpci->log( + 'Codeception XML path: '. $this->phpci->buildPath . $this->path . '_output/report.xml', + Loglevel::DEBUG + ); + $xml = file_get_contents($this->phpci->buildPath . $this->path . '_output/report.xml', false); + + try { + $parser = new Parser($this->phpci, $xml); + $output = $parser->parse(); + } catch (\Exception $ex) { + throw $ex; + } + + $meta = array( + 'tests' => $parser->getTotalTests(), + 'timetaken' => $parser->getTotalTimeTaken(), + 'failures' => $parser->getTotalFailures() + ); + + $this->build->storeMeta('codeception-meta', $meta); + $this->build->storeMeta('codeception-data', $output); + $this->build->storeMeta('codeception-errors', $parser->getTotalFailures()); + + $this->phpci->logExecOutput(true); + return $success; } } - - /** - * @param array $array - * @param \Callback $callable - * @return bool|mixed - */ - protected function recurseArg(array $array, $callable) - { - $success = true; - - foreach ($array as $subItem) { - $success &= call_user_func($callable, $subItem); - } - - return $success; - } } diff --git a/PHPCI/Plugin/Util/TestResultParsers/Codeception.php b/PHPCI/Plugin/Util/TestResultParsers/Codeception.php new file mode 100644 index 00000000..39f1ce6f --- /dev/null +++ b/PHPCI/Plugin/Util/TestResultParsers/Codeception.php @@ -0,0 +1,108 @@ + + * @package PHPCI\Plugin\Util\TestResultParsers + */ +class Codeception implements ParserInterface +{ + protected $phpci; + protected $resultsXml; + + protected $results; + + protected $totalTests; + protected $totalTimeTaken; + protected $totalFailures; + + /** + * @param Builder $phpci + * @param $resultsXml + */ + public function __construct(Builder $phpci, $resultsXml) + { + $this->phpci = $phpci; + $this->resultsXml = $resultsXml; + + $this->totalTests = 0; + } + + /** + * @return array An array of key/value pairs for storage in the plugins result metadata + */ + public function parse() + { + $rtn = array(); + + $this->results = new \SimpleXMLElement($this->resultsXml); + + // calculate total results + foreach ($this->results->testsuite as $testsuite) { + $this->totalTests += (int) $testsuite['tests']; + $this->totalTimeTaken += (float) $testsuite['time']; + $this->totalFailures += (int) $testsuite['failures']; + + foreach ($testsuite->testcase as $testcase) { + $testresult = array( + 'suite' => (string) $testsuite['name'], + 'file' => str_replace($this->phpci->buildPath, '/', (string) $testcase['file']), + 'name' => (string) $testcase['name'], + 'feature' => (string) $testcase['feature'], + 'assertions' => (int) $testcase['assertions'], + 'time' => (float) $testcase['time'] + ); + + if (isset($testcase['class'])) { + $testresult['class'] = (string) $testcase['class']; + } + + if (isset($testcase->failure)) { + $testresult['pass'] = false; + $testresult['message'] = (string) $testcase->failure; + } else { + $testresult['pass'] = true; + } + + $rtn[] = $testresult; + } + } + + return $rtn; + } + + /** + * Get the total number of tests performed. + * + * @return int + */ + public function getTotalTests() + { + return $this->totalTests; + } + + /** + * The time take to complete all tests + * + * @return mixed + */ + public function getTotalTimeTaken() + { + return $this->totalTimeTaken; + } + + /** + * A count of the test failures + * + * @return mixed + */ + public function getTotalFailures() + { + return $this->totalFailures; + } +} diff --git a/PHPCI/Plugin/Util/TestResultParsers/ParserInterface.php b/PHPCI/Plugin/Util/TestResultParsers/ParserInterface.php new file mode 100644 index 00000000..d0c77cb7 --- /dev/null +++ b/PHPCI/Plugin/Util/TestResultParsers/ParserInterface.php @@ -0,0 +1,16 @@ +li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top, #428bca 0, #357ebd 100%);background-image:linear-gradient(to bottom, #428bca 0, #357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top, #fff 0, #f8f8f8 100%);background-image:linear-gradient(to bottom, #fff 0, #f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top, #ebebeb 0, #f3f3f3 100%);background-image:linear-gradient(to bottom, #ebebeb 0, #f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.075);box-shadow:inset 0 3px 9px rgba(0,0,0,0.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top, #3c3c3c 0, #222 100%);background-image:linear-gradient(to bottom, #3c3c3c 0, #222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top, #222 0, #282828 100%);background-image:linear-gradient(to bottom, #222 0, #282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.25);box-shadow:inset 0 3px 9px rgba(0,0,0,0.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-linear-gradient(top, #dff0d8 0, #c8e5bc 100%);background-image:linear-gradient(to bottom, #dff0d8 0, #c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top, #d9edf7 0, #b9def0 100%);background-image:linear-gradient(to bottom, #d9edf7 0, #b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top, #fcf8e3 0, #f8efc0 100%);background-image:linear-gradient(to bottom, #fcf8e3 0, #f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top, #f2dede 0, #e7c3c3 100%);background-image:linear-gradient(to bottom, #f2dede 0, #e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top, #ebebeb 0, #f5f5f5 100%);background-image:linear-gradient(to bottom, #ebebeb 0, #f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top, #428bca 0, #3071a9 100%);background-image:linear-gradient(to bottom, #428bca 0, #3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top, #5cb85c 0, #449d44 100%);background-image:linear-gradient(to bottom, #5cb85c 0, #449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top, #5bc0de 0, #31b0d5 100%);background-image:linear-gradient(to bottom, #5bc0de 0, #31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top, #f0ad4e 0, #ec971f 100%);background-image:linear-gradient(to bottom, #f0ad4e 0, #ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top, #d9534f 0, #c9302c 100%);background-image:linear-gradient(to bottom, #d9534f 0, #c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top, #428bca 0, #3278b3 100%);background-image:linear-gradient(to bottom, #428bca 0, #3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.box-header{background-image:-webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.box-header{background-image:-webkit-linear-gradient(top, #428bca 0, #357ebd 100%);background-image:linear-gradient(to bottom, #428bca 0, #357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.box-header{background-image:-webkit-linear-gradient(top, #dff0d8 0, #d0e9c6 100%);background-image:linear-gradient(to bottom, #dff0d8 0, #d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.box-header{background-image:-webkit-linear-gradient(top, #d9edf7 0, #c4e3f3 100%);background-image:linear-gradient(to bottom, #d9edf7 0, #c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.box-header{background-image:-webkit-linear-gradient(top, #fcf8e3 0, #faf2cc 100%);background-image:linear-gradient(to bottom, #fcf8e3 0, #faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.box-header{background-image:-webkit-linear-gradient(top, #f2dede 0, #ebcccc 100%);background-image:linear-gradient(to bottom, #f2dede 0, #ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top, #e8e8e8 0, #f5f5f5 100%);background-image:linear-gradient(to bottom, #e8e8e8 0, #f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} \ No newline at end of file +.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top, #fff 0, #e0e0e0 100%);background-image:linear-gradient(to bottom, #fff 0, #e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top, #428bca 0, #2d6ca2 100%);background-image:linear-gradient(to bottom, #428bca 0, #2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top, #5cb85c 0, #419641 100%);background-image:linear-gradient(to bottom, #5cb85c 0, #419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-info{background-image:-webkit-linear-gradient(top, #5bc0de 0, #2aabd2 100%);background-image:linear-gradient(to bottom, #5bc0de 0, #2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-warning{background-image:-webkit-linear-gradient(top, #f0ad4e 0, #eb9316 100%);background-image:linear-gradient(to bottom, #f0ad4e 0, #eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top, #d9534f 0, #c12e2a 100%);background-image:linear-gradient(to bottom, #d9534f 0, #c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top, #428bca 0, #357ebd 100%);background-image:linear-gradient(to bottom, #428bca 0, #357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top, #fff 0, #f8f8f8 100%);background-image:linear-gradient(to bottom, #fff 0, #f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top, #ebebeb 0, #f3f3f3 100%);background-image:linear-gradient(to bottom, #ebebeb 0, #f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.075);box-shadow:inset 0 3px 9px rgba(0,0,0,0.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top, #3c3c3c 0, #222 100%);background-image:linear-gradient(to bottom, #3c3c3c 0, #222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top, #222 0, #282828 100%);background-image:linear-gradient(to bottom, #222 0, #282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.25);box-shadow:inset 0 3px 9px rgba(0,0,0,0.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-linear-gradient(top, #dff0d8 0, #c8e5bc 100%);background-image:linear-gradient(to bottom, #dff0d8 0, #c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top, #d9edf7 0, #b9def0 100%);background-image:linear-gradient(to bottom, #d9edf7 0, #b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top, #fcf8e3 0, #f8efc0 100%);background-image:linear-gradient(to bottom, #fcf8e3 0, #f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top, #f2dede 0, #e7c3c3 100%);background-image:linear-gradient(to bottom, #f2dede 0, #e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top, #ebebeb 0, #f5f5f5 100%);background-image:linear-gradient(to bottom, #ebebeb 0, #f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top, #428bca 0, #3071a9 100%);background-image:linear-gradient(to bottom, #428bca 0, #3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top, #5cb85c 0, #449d44 100%);background-image:linear-gradient(to bottom, #5cb85c 0, #449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top, #5bc0de 0, #31b0d5 100%);background-image:linear-gradient(to bottom, #5bc0de 0, #31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top, #f0ad4e 0, #ec971f 100%);background-image:linear-gradient(to bottom, #f0ad4e 0, #ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top, #d9534f 0, #c9302c 100%);background-image:linear-gradient(to bottom, #d9534f 0, #c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top, #428bca 0, #3278b3 100%);background-image:linear-gradient(to bottom, #428bca 0, #3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.box-header{background-image:-webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.box-header{background-image:-webkit-linear-gradient(top, #428bca 0, #357ebd 100%);background-image:linear-gradient(to bottom, #428bca 0, #357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.box-header{background-image:-webkit-linear-gradient(top, #dff0d8 0, #d0e9c6 100%);background-image:linear-gradient(to bottom, #dff0d8 0, #d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.box-header{background-image:-webkit-linear-gradient(top, #d9edf7 0, #c4e3f3 100%);background-image:linear-gradient(to bottom, #d9edf7 0, #c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.box-header{background-image:-webkit-linear-gradient(top, #fcf8e3 0, #faf2cc 100%);background-image:linear-gradient(to bottom, #fcf8e3 0, #faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.box-header{background-image:-webkit-linear-gradient(top, #f2dede 0, #ebcccc 100%);background-image:linear-gradient(to bottom, #f2dede 0, #ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top, #e8e8e8 0, #f5f5f5 100%);background-image:linear-gradient(to bottom, #e8e8e8 0, #f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} diff --git a/public/assets/css/bootstrap.min.css b/public/assets/css/bootstrap.min.css index 7af7ea7c..7e029af9 100755 --- a/public/assets/css/bootstrap.min.css +++ b/public/assets/css/bootstrap.min.css @@ -1,7 +1,7 @@ /*! - * Bootstrap v3.1.1 (http://getbootstrap.com) + * Bootstrap v3.2.0 (http://getbootstrap.com) * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.table td,.table th{background-color:#fff !important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}input[type="date"]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:none}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:none}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.box-body{padding:15px}.box-header{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.box-header>.dropdown .dropdown-toggle{color:inherit}.box-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.box-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.box-header+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.box-body+.table,.panel>.box-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .box-header{border-bottom:0}.panel-group .box-header+.panel-collapse .box-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .box-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.box-header{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.box-header+.panel-collapse .box-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .box-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.box-header{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.box-header+.panel-collapse .box-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .box-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.box-header{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.box-header+.panel-collapse .box-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .box-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.box-header{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.box-header+.panel-collapse .box-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .box-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.box-header{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.box-header+.panel-collapse .box-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .box-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.box-header{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.box-header+.panel-collapse .box-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .box-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);transform:translate(0, 0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:none}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.box-body:before,.box-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.box-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}@media print{.hidden-print{display:none !important}} \ No newline at end of file +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.table td,.table th{background-color:#fff !important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}input[type="date"]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:none}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:none}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.box-body{padding:15px}.box-header{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.box-header>.dropdown .dropdown-toggle{color:inherit}.box-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.box-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.box-header+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.box-body+.table,.panel>.box-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .box-header{border-bottom:0}.panel-group .box-header+.panel-collapse .box-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .box-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.box-header{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.box-header+.panel-collapse .box-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .box-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.box-header{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.box-header+.panel-collapse .box-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .box-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.box-header{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.box-header+.panel-collapse .box-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .box-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.box-header{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.box-header+.panel-collapse .box-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .box-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.box-header{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.box-header+.panel-collapse .box-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .box-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.box-header{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.box-header+.panel-collapse .box-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .box-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);transform:translate(0, 0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:none}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.box-body:before,.box-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.box-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}@media print{.hidden-print{display:none !important}} diff --git a/public/assets/js/bootstrap.min.js b/public/assets/js/bootstrap.min.js index 856dc42f..9e2add70 100755 --- a/public/assets/js/bootstrap.min.js +++ b/public/assets/js/bootstrap.min.js @@ -1,7 +1,11 @@ /*! - * Bootstrap v3.1.1 (http://getbootstrap.com) + * Bootstrap v3.2.0 (http://getbootstrap.com) * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function f(){e.trigger("closed.bs.alert").remove()}var c=a(this),d=c.attr("data-target");d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));var e=a(d);b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.trigger(b=a.Event("close.bs.alert"));if(b.isDefaultPrevented())return;e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.one(a.support.transition.end,f).emulateTransitionEnd(150):f()};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.isLoading=!1};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",f.resetText||d.data("resetText",d[e]()),d[e](f[b]||this.options[b]),setTimeout(a.proxy(function(){b=="loadingText"?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},b.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");c.prop("type")=="radio"&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f=typeof c=="object"&&c;e||d.data("bs.button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,this.options.pause=="hover"&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();if(b>this.$items.length-1||b<0)return;return this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){if(this.sliding)return;return this.slide("next")},b.prototype.prev=function(){if(this.sliding)return;return this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});this.$element.trigger(j);if(j.isDefaultPrevented())return;return this.sliding=!0,f&&this.pause(),this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(d.css("transition-duration").slice(0,-1)*1e3)):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")),f&&this.cycle(),this};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),typeof c=="object"&&c),g=typeof c=="string"?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),typeof c=="number"?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),c.data()),g=c.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=c.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){function e(d){a(b).remove(),a(c).each(function(){var b=f(a(this)),c={relatedTarget:this};if(!b.hasClass("open"))return;b.trigger(d=a.Event("hide.bs.dropdown",c));if(d.isDefaultPrevented())return;b.removeClass("open").trigger("hidden.bs.dropdown",c)})}function f(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}"use strict";var b=".dropdown-backdrop",c="[data-toggle=dropdown]",d=function(b){a(b).on("click.bs.dropdown",this.toggle)};d.prototype.toggle=function(b){var c=a(this);if(c.is(".disabled, :disabled"))return;var d=f(c),g=d.hasClass("open");e();if(!g){"ontouchstart"in document.documentElement&&!d.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?typeof c=="string"?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||(typeof b.content=="function"?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f=typeof c=="object"&&c;if(!e&&c=="destroy")return;e||d.data("bs.popover",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));if(b.parent("li").hasClass("active"))return;var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});b.trigger(f);if(f.isDefaultPrevented())return;var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})},b.prototype.activate=function(b,c,d){function g(){e.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),f?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var e=c.find("> .active"),f=d&&a.support.transition&&e.hasClass("fade");f?e.one(a.support.transition.end,g).emulateTransitionEnd(150):g(),e.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),typeof c=="string"&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(this.transitioning||this.$element.hasClass("in"))return;var b=a.Event("show.bs.collapse");this.$element.trigger(b);if(b.isDefaultPrevented())return;var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])},b.prototype.hide=function(){if(this.transitioning||!this.$element.hasClass("in"))return;var b=a.Event("hide.bs.collapse");this.$element.trigger(b);if(b.isDefaultPrevented())return;var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};if(!a.support.transition)return d.call(this);this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350)},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),typeof c=="object"&&c);!e&&f.toggle&&c=="show"&&(c=!c),e||d.data("bs.collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":c.data(),i=c.attr("data-parent"),j=i&&a(i);if(!g||!g.transitioning)j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(c).addClass("collapsed"),c[f.hasClass("in")?"addClass":"removeClass"]("collapsed");f.collapse(h)})}(jQuery),+function(a){function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(a.style[c]!==undefined)return{end:b[c]};return!1}"use strict",a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery) \ No newline at end of file +/*! + * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=09c8c466aa06e64a7262) + * Config saved to config.json and https://gist.github.com/09c8c466aa06e64a7262 + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(t){"use strict";function e(e){return this.each(function(){var i=t(this),s=i.data("bs.alert");s||i.data("bs.alert",s=new o(this)),"string"==typeof e&&s[e].call(i)})}var i='[data-dismiss="alert"]',o=function(e){t(e).on("click",i,this.close)};o.VERSION="3.2.0",o.prototype.close=function(e){function i(){n.detach().trigger("closed.bs.alert").remove()}var o=t(this),s=o.attr("data-target");s||(s=o.attr("href"),s=s&&s.replace(/.*(?=#[^\s]*$)/,""));var n=t(s);e&&e.preventDefault(),n.length||(n=o.hasClass("alert")?o:o.parent()),n.trigger(e=t.Event("close.bs.alert")),e.isDefaultPrevented()||(n.removeClass("in"),t.support.transition&&n.hasClass("fade")?n.one("bsTransitionEnd",i).emulateTransitionEnd(150):i())};var s=t.fn.alert;t.fn.alert=e,t.fn.alert.Constructor=o,t.fn.alert.noConflict=function(){return t.fn.alert=s,this},t(document).on("click.bs.alert.data-api",i,o.prototype.close)}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var o=t(this),s=o.data("bs.button"),n="object"==typeof e&&e;s||o.data("bs.button",s=new i(this,n)),"toggle"==e?s.toggle():e&&s.setState(e)})}var i=function(e,o){this.$element=t(e),this.options=t.extend({},i.DEFAULTS,o),this.isLoading=!1};i.VERSION="3.2.0",i.DEFAULTS={loadingText:"loading..."},i.prototype.setState=function(e){var i="disabled",o=this.$element,s=o.is("input")?"val":"html",n=o.data();e+="Text",null==n.resetText&&o.data("resetText",o[s]()),o[s](null==n[e]?this.options[e]:n[e]),setTimeout(t.proxy(function(){"loadingText"==e?(this.isLoading=!0,o.addClass(i).attr(i,i)):this.isLoading&&(this.isLoading=!1,o.removeClass(i).removeAttr(i))},this),0)},i.prototype.toggle=function(){var t=!0,e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var i=this.$element.find("input");"radio"==i.prop("type")&&(i.prop("checked")&&this.$element.hasClass("active")?t=!1:e.find(".active").removeClass("active")),t&&i.prop("checked",!this.$element.hasClass("active")).trigger("change")}t&&this.$element.toggleClass("active")};var o=t.fn.button;t.fn.button=e,t.fn.button.Constructor=i,t.fn.button.noConflict=function(){return t.fn.button=o,this},t(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(i){var o=t(i.target);o.hasClass("btn")||(o=o.closest(".btn")),e.call(o,"toggle"),i.preventDefault()})}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var o=t(this),s=o.data("bs.carousel"),n=t.extend({},i.DEFAULTS,o.data(),"object"==typeof e&&e),r="string"==typeof e?e:n.slide;s||o.data("bs.carousel",s=new i(this,n)),"number"==typeof e?s.to(e):r?s[r]():n.interval&&s.pause().cycle()})}var i=function(e,i){this.$element=t(e).on("keydown.bs.carousel",t.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=i,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",t.proxy(this.pause,this)).on("mouseleave.bs.carousel",t.proxy(this.cycle,this))};i.VERSION="3.2.0",i.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},i.prototype.keydown=function(t){switch(t.which){case 37:this.prev();break;case 39:this.next();break;default:return}t.preventDefault()},i.prototype.cycle=function(e){return e||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(t.proxy(this.next,this),this.options.interval)),this},i.prototype.getItemIndex=function(t){return this.$items=t.parent().children(".item"),this.$items.index(t||this.$active)},i.prototype.to=function(e){var i=this,o=this.getItemIndex(this.$active=this.$element.find(".item.active"));return e>this.$items.length-1||0>e?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){i.to(e)}):o==e?this.pause().cycle():this.slide(e>o?"next":"prev",t(this.$items[e]))},i.prototype.pause=function(e){return e||(this.paused=!0),this.$element.find(".next, .prev").length&&t.support.transition&&(this.$element.trigger(t.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},i.prototype.next=function(){return this.sliding?void 0:this.slide("next")},i.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},i.prototype.slide=function(e,i){var o=this.$element.find(".item.active"),s=i||o[e](),n=this.interval,r="next"==e?"left":"right",a="next"==e?"first":"last",l=this;if(!s.length){if(!this.options.wrap)return;s=this.$element.find(".item")[a]()}if(s.hasClass("active"))return this.sliding=!1;var h=s[0],p=t.Event("slide.bs.carousel",{relatedTarget:h,direction:r});if(this.$element.trigger(p),!p.isDefaultPrevented()){if(this.sliding=!0,n&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var c=t(this.$indicators.children()[this.getItemIndex(s)]);c&&c.addClass("active")}var d=t.Event("slid.bs.carousel",{relatedTarget:h,direction:r});return t.support.transition&&this.$element.hasClass("slide")?(s.addClass(e),s[0].offsetWidth,o.addClass(r),s.addClass(r),o.one("bsTransitionEnd",function(){s.removeClass([e,r].join(" ")).addClass("active"),o.removeClass(["active",r].join(" ")),l.sliding=!1,setTimeout(function(){l.$element.trigger(d)},0)}).emulateTransitionEnd(1e3*o.css("transition-duration").slice(0,-1))):(o.removeClass("active"),s.addClass("active"),this.sliding=!1,this.$element.trigger(d)),n&&this.cycle(),this}};var o=t.fn.carousel;t.fn.carousel=e,t.fn.carousel.Constructor=i,t.fn.carousel.noConflict=function(){return t.fn.carousel=o,this},t(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(i){var o,s=t(this),n=t(s.attr("data-target")||(o=s.attr("href"))&&o.replace(/.*(?=#[^\s]+$)/,""));if(n.hasClass("carousel")){var r=t.extend({},n.data(),s.data()),a=s.attr("data-slide-to");a&&(r.interval=!1),e.call(n,r),a&&n.data("bs.carousel").to(a),i.preventDefault()}}),t(window).on("load",function(){t('[data-ride="carousel"]').each(function(){var i=t(this);e.call(i,i.data())})})}(jQuery),+function(t){"use strict";function e(e){e&&3===e.which||(t(s).remove(),t(n).each(function(){var o=i(t(this)),s={relatedTarget:this};o.hasClass("open")&&(o.trigger(e=t.Event("hide.bs.dropdown",s)),e.isDefaultPrevented()||o.removeClass("open").trigger("hidden.bs.dropdown",s))}))}function i(e){var i=e.attr("data-target");i||(i=e.attr("href"),i=i&&/#[A-Za-z]/.test(i)&&i.replace(/.*(?=#[^\s]*$)/,""));var o=i&&t(i);return o&&o.length?o:e.parent()}function o(e){return this.each(function(){var i=t(this),o=i.data("bs.dropdown");o||i.data("bs.dropdown",o=new r(this)),"string"==typeof e&&o[e].call(i)})}var s=".dropdown-backdrop",n='[data-toggle="dropdown"]',r=function(e){t(e).on("click.bs.dropdown",this.toggle)};r.VERSION="3.2.0",r.prototype.toggle=function(o){var s=t(this);if(!s.is(".disabled, :disabled")){var n=i(s),r=n.hasClass("open");if(e(),!r){"ontouchstart"in document.documentElement&&!n.closest(".navbar-nav").length&&t('