diff --git a/.gitignore b/.gitignore
index c507849..eb0d60a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,73 @@
-target
-.idea
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+.idea/modules.xml
+.idea/*.iml
+.idea/modules
+*.iml
+*.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+.idea/*
+*.iml
+
+target/
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index b194ae1..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100644
index b26911b..0000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_google_guava_guava_18_0.xml b/.idea/libraries/Maven__com_google_guava_guava_18_0.xml
deleted file mode 100644
index bbd71d7..0000000
--- a/.idea/libraries/Maven__com_google_guava_guava_18_0.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_google_protobuf_protobuf_java_3_0_0_beta_2.xml b/.idea/libraries/Maven__com_google_protobuf_protobuf_java_3_0_0_beta_2.xml
deleted file mode 100644
index 0370413..0000000
--- a/.idea/libraries/Maven__com_google_protobuf_protobuf_java_3_0_0_beta_2.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_googlecode_json_simple_json_simple_1_1_1.xml b/.idea/libraries/Maven__com_googlecode_json_simple_json_simple_1_1_1.xml
deleted file mode 100644
index f3f3738..0000000
--- a/.idea/libraries/Maven__com_googlecode_json_simple_json_simple_1_1_1.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__commons_io_commons_io_2_4.xml b/.idea/libraries/Maven__commons_io_commons_io_2_4.xml
deleted file mode 100644
index bc2aad0..0000000
--- a/.idea/libraries/Maven__commons_io_commons_io_2_4.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__commons_lang_commons_lang_2_6.xml b/.idea/libraries/Maven__commons_lang_commons_lang_2_6.xml
deleted file mode 100644
index 2ec8376..0000000
--- a/.idea/libraries/Maven__commons_lang_commons_lang_2_6.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__javax_xml_stream_stax_api_1_0_2.xml b/.idea/libraries/Maven__javax_xml_stream_stax_api_1_0_2.xml
deleted file mode 100644
index 2a4dd7a..0000000
--- a/.idea/libraries/Maven__javax_xml_stream_stax_api_1_0_2.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__jaxen_jaxen_1_1_4.xml b/.idea/libraries/Maven__jaxen_jaxen_1_1_4.xml
deleted file mode 100644
index d84dbcf..0000000
--- a/.idea/libraries/Maven__jaxen_jaxen_1_1_4.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__junit_junit_4_11.xml b/.idea/libraries/Maven__junit_junit_4_11.xml
deleted file mode 100644
index f33320d..0000000
--- a/.idea/libraries/Maven__junit_junit_4_11.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_codehaus_sonar_sslr_sslr_xpath_1_20.xml b/.idea/libraries/Maven__org_codehaus_sonar_sslr_sslr_xpath_1_20.xml
deleted file mode 100644
index 40137b0..0000000
--- a/.idea/libraries/Maven__org_codehaus_sonar_sslr_sslr_xpath_1_20.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_codehaus_staxmate_staxmate_2_0_1.xml b/.idea/libraries/Maven__org_codehaus_staxmate_staxmate_2_0_1.xml
deleted file mode 100644
index cd58567..0000000
--- a/.idea/libraries/Maven__org_codehaus_staxmate_staxmate_2_0_1.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_codehaus_woodstox_stax2_api_3_1_4.xml b/.idea/libraries/Maven__org_codehaus_woodstox_stax2_api_3_1_4.xml
deleted file mode 100644
index b510642..0000000
--- a/.idea/libraries/Maven__org_codehaus_woodstox_stax2_api_3_1_4.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_codehaus_woodstox_woodstox_core_lgpl_4_4_0.xml b/.idea/libraries/Maven__org_codehaus_woodstox_woodstox_core_lgpl_4_4_0.xml
deleted file mode 100644
index c5ded28..0000000
--- a/.idea/libraries/Maven__org_codehaus_woodstox_woodstox_core_lgpl_4_4_0.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml b/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml
deleted file mode 100644
index f58bbc1..0000000
--- a/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_slf4j_jcl_over_slf4j_1_5_6.xml b/.idea/libraries/Maven__org_slf4j_jcl_over_slf4j_1_5_6.xml
deleted file mode 100644
index 3b3e1bf..0000000
--- a/.idea/libraries/Maven__org_slf4j_jcl_over_slf4j_1_5_6.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_slf4j_slf4j_api_1_5_6.xml b/.idea/libraries/Maven__org_slf4j_slf4j_api_1_5_6.xml
deleted file mode 100644
index b92b869..0000000
--- a/.idea/libraries/Maven__org_slf4j_slf4j_api_1_5_6.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_sonarsource_sslr_squid_bridge_sslr_squid_bridge_2_6_1.xml b/.idea/libraries/Maven__org_sonarsource_sslr_squid_bridge_sslr_squid_bridge_2_6_1.xml
deleted file mode 100644
index 9065ab6..0000000
--- a/.idea/libraries/Maven__org_sonarsource_sslr_squid_bridge_sslr_squid_bridge_2_6_1.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index df553a4..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1.8
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index a53c384..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1dd..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index fe69d0c..4c2e5c6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,7 @@ addons:
organization: "lequal"
jdk:
- - oraclejdk8
+ - openjdk8
script:
- mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent package sonar:sonar
diff --git a/README.md b/README.md
index 0261ea6..b5cbb6a 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,7 @@ This plugin is free software; you can redistribute it and/or modify it under the
1.2.1
2.0.0
2.1.0
+
2.2.0
1.0.0
@@ -43,6 +44,7 @@ This plugin is free software; you can redistribute it and/or modify it under the
x
-
-
+
-
1.1.0
@@ -51,6 +53,7 @@ This plugin is free software; you can redistribute it and/or modify it under the
x
-
-
+
-
1.2.0
@@ -59,6 +62,7 @@ This plugin is free software; you can redistribute it and/or modify it under the
x
-
-
+
-
1.3.0
@@ -67,6 +71,16 @@ This plugin is free software; you can redistribute it and/or modify it under the
-
x
x
+
-
+
+
+
1.4.0
+
-
+
-
+
-
+
-
+
-
+
x
diff --git a/pom.xml b/pom.xml
index 87c5331..1f1d898 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
fr.cnes.sonar.plugins.scansonar-cnes-scan-pluginsonar-plugin
- 1.3
+ 1.4SonarQube CNES Scan PluginCNES plugin for SonarQube that launches analysis directly from the web interface and export reports.
@@ -40,6 +40,13 @@
CNEShttps://cnes.fr/
+
+ louisjdmartin
+ Louis Martin
+ louis.jd.martin@gmail.com
+ CNES
+ https://cnes.fr/
+
diff --git a/src/main/java/fr/cnes/sonar/plugins/scan/web/CnesPluginPageDefinition.java b/src/main/java/fr/cnes/sonar/plugins/scan/web/CnesPluginPageDefinition.java
index a3ce62e..3c567a8 100644
--- a/src/main/java/fr/cnes/sonar/plugins/scan/web/CnesPluginPageDefinition.java
+++ b/src/main/java/fr/cnes/sonar/plugins/scan/web/CnesPluginPageDefinition.java
@@ -46,16 +46,6 @@ public void define(final Context context) {
context.addPage(page.build());
- // create a page
- page = Page.builder(StringManager.string(StringManager.CNES_PAGE_REPORT_KEY));
- // set its name
- page.setName(StringManager.string(StringManager.CNES_PAGE_REPORT_NAME));
- // set its scope (where it is displayed)
- page.setScope(Scope.GLOBAL);
- // add a new page for reporting
- context.addPage(page.build());
-
-
// create a page
page = Page.builder(StringManager.string(StringManager.CNES_PAGE_HELP_KEY));
// set its name
diff --git a/src/main/resources/static/analysis.js b/src/main/resources/static/analysis.js
index eec13fd..e5136be 100644
--- a/src/main/resources/static/analysis.js
+++ b/src/main/resources/static/analysis.js
@@ -37,12 +37,17 @@ window.registerExtension('cnesscan/analysis', function (options) {
logging.scrollTop = logging.scrollHeight;
};
+ var displayLog = function (string,color){
+ $('#last_log').html("
"+string+"
")
+ }
+
/**
* Log information in the bottom text area as info
* @param string Text to log
*/
var info = function (string) {
log("[INFO] "+string)
+ displayLog(string,"blue")
};
/**
@@ -51,6 +56,7 @@ window.registerExtension('cnesscan/analysis', function (options) {
*/
var error = function (string) {
log("[ERROR] "+string)
+ displayLog(string,"red")
};
/**
@@ -205,7 +211,8 @@ window.registerExtension('cnesscan/analysis', function (options) {
setEnabled(true);
}).catch(function (response) {
// log error
- error("Project report generation failed.");
+ error("Project report generation failed. \n" + response.logs);
+ displayLog("Project report generation failed. Please check logs. The project results are still available in the dashboard.","orange")
// unlock form
setEnabled(true);
});
@@ -373,6 +380,7 @@ window.registerExtension('cnesscan/analysis', function (options) {
// log the finally used spp
info("Here comes the finally used sonar-project.properties:\n" + spp);
+ info("The analysis is running, please wait.");
// send post request to the cnes web service
window.SonarRequest.postJSON(
@@ -621,6 +629,15 @@ window.registerExtension('cnesscan/analysis', function (options) {
return false;
}
+ // get copy button in the DOM
+ var logButton = document.querySelector('#show_logs');
+ // set copy button action
+ logButton.onclick = function () {
+ $('#logging, #copy, #show_logs').toggle();
+
+ return false;
+ }
+
// fill out quality gate drop down list
initQualityGateDropDownList();
diff --git a/src/main/resources/static/reporting.js b/src/main/resources/static/reporting.js
deleted file mode 100644
index b20397a..0000000
--- a/src/main/resources/static/reporting.js
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * This file is part of cnesscan.
- *
- * cnesscan is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * cnesscan is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with cnesscan. If not, see .
- */
-
-window.registerExtension('cnesscan/reporting', function (options) {
- // let's create a flag telling if the page is still displayed
- var isDisplayedReporting = true;
-
- /**
- * Log information in the bottom text area
- * @param string Text to log
- */
- var log = function (string) {
- // get the logging element
- var logging = document.querySelector('#logging');
- // append text to log
- logging.innerHTML = logging.innerHTML + "\n" + string;
- // scroll to bottom
- logging.scrollTop = logging.scrollHeight;
- };
-
- /**
- * Verify that the fields are correct.
- * @returns {boolean} true if all is good
- */
- var checkForm = function () {
- // check the field key
- // get it
- var key = document.forms["generation-form"]["key"].value;
- // check if void
- if (key === "") {
- // log error
- log("Key must be filled out.");
- // abort the process
- return false;
- }
-
- return true;
- };
-
- /**
- * Clear log information in text area
- */
- var clearLog = function () {
- // get the logging element
- var logging = document.querySelector('#logging');
- // set initial text to log
- logging.innerHTML = "## Logging console ##";
- };
-
- /**
- * Lock or unlock the form
- * @param isEnabled true to unlock, false to lock the form
- */
- var setEnabled = function (isEnabled) {
- // retrieve the form
- var form = document.getElementById("generation-form");
- // get all the components of the form
- var elements = form.elements;
- // change all components readOnly field to (un)lock them
- for (var i = 0, len = elements.length; i < len; i++) {
- elements[i].readOnly = !isEnabled;
- elements[i].disabled = !isEnabled;
- }
-
- if(isEnabled) {
- // hide loading when button are enabled
- $('#loading').hide();
- } else {
- // show loading otherwise
- $('#loading').show();
- }
- };
-
- /**
- * Generate the report
- * @param key
- * @param author
- */
- var produceReport = function (key, author) {
- // http GET request to the cnes web service
- window.SonarRequest.getJSON(
- '/api/cnes/report',
- { key: key, author: author }
- ).then(function (response) {
- // on success log generation
- log("[INFO] Project report generation response: \n" + response.logs);
- log("############################################################\n\tGeneration of the report terminated!\n############################################################\n");
- setEnabled(true);
- }).catch(function (error) {
- // log error
- log("[ERROR] Project report generation failed.");
- setEnabled(true);
- });
- };
-
- /**
- * Get projects list from the server and fill out the combo box
- */
- var initProjectsDropDownList = function() {
- window.SonarRequest.getJSON(
- '/api/projects/index'
- ).then(function (response) {
- // on success
- // we put each quality gate in the list
- $.each(response, function (i, item) {
- // we create a new option for each quality gate
- // in the json response
- var option = $('
', {
- value: item.k,
- text : item.nm + ' [' + item.k + ']'
- });
- // we add it to the drop down list
- $('#key').append(option);
- });
- }).catch(function (response) {
- // log error
- error(response);
- });
- };
-
- // once the request is done, and the page is still displayed (not closed already)
- if (isDisplayedReporting) {
-
- // Add html template
- var template = document.createElement("div");
- template.setAttribute("id", "template");
- options.el.appendChild(template);
- // retrieve template from html
- $('#template').load('../../static/cnesscan/templates/reportForm.html', function(){
- // set generation button action
- // set its action on click
- document.querySelector('#generation').onclick = function () {
-
- // clear logs
- clearLog();
-
- // hide loading
- $('#loading').hide();
-
- // validation of the form
- if(checkForm()) {
-
- // Get form values
- var key = document.forms["generation-form"]["key"].value;
- var author = document.forms["generation-form"]["author"].value;
-
- // lock the form
- setEnabled(false);
-
- // show loading
- $('#loading').show();
-
- // request the creation of the report
- produceReport(key, author);
- }
- };
-
- // fill out project's drop down list
- initProjectsDropDownList();
- });
-
- }
-
- // return a function, which is called when the page is being closed
- return function () {
- // we unset the `isDisplayedReporting` flag to ignore to Web API calls finished after the page is closed
- isDisplayedReporting = false;
- // clean elements of this page
- options.el.textContent = '';
- };
-});
\ No newline at end of file
diff --git a/src/main/resources/static/select2/select2.min.css b/src/main/resources/static/select2/select2.min.css
new file mode 100644
index 0000000..60d5990
--- /dev/null
+++ b/src/main/resources/static/select2/select2.min.css
@@ -0,0 +1 @@
+.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:#999;margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb}
diff --git a/src/main/resources/static/select2/select2.min.js b/src/main/resources/static/select2/select2.min.js
new file mode 100644
index 0000000..184bc49
--- /dev/null
+++ b/src/main/resources/static/select2/select2.min.js
@@ -0,0 +1 @@
+/*! Select2 4.0.7 | https://github.com/select2/select2/blob/master/LICENSE.md */!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=function(b,c){return void 0===c&&(c="undefined"!=typeof window?require("jquery"):require("jquery")(b)),a(c),c}:a(jQuery)}(function(a){var b=function(){if(a&&a.fn&&a.fn.select2&&a.fn.select2.amd)var b=a.fn.select2.amd;var b;return function(){if(!b||!b.requirejs){b?c=b:b={};var a,c,d;!function(b){function e(a,b){return v.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n,o=b&&b.split("/"),p=t.map,q=p&&p["*"]||{};if(a){for(a=a.split("/"),g=a.length-1,t.nodeIdCompat&&x.test(a[g])&&(a[g]=a[g].replace(x,"")),"."===a[0].charAt(0)&&o&&(n=o.slice(0,o.length-1),a=n.concat(a)),k=0;k0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}if((o||q)&&p){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),o)for(l=o.length;l>0;l-=1)if((e=p[o.slice(0,l).join("/")])&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&q&&q[d]&&(i=q[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,c){return function(){var d=w.call(arguments,0);return"string"!=typeof d[0]&&1===d.length&&d.push(null),o.apply(b,d.concat([a,c]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){r[a]=b}}function j(a){if(e(s,a)){var c=s[a];delete s[a],u[a]=!0,n.apply(b,c)}if(!e(r,a)&&!e(u,a))throw new Error("No "+a);return r[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return a?k(a):[]}function m(a){return function(){return t&&t.config&&t.config[a]||{}}}var n,o,p,q,r={},s={},t={},u={},v=Object.prototype.hasOwnProperty,w=[].slice,x=/\.js$/;p=function(a,b){var c,d=k(a),e=d[0],g=b[1];return a=d[1],e&&(e=f(e,g),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(g)):f(a,g):(a=f(a,g),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},q={require:function(a){return g(a)},exports:function(a){var b=r[a];return void 0!==b?b:r[a]={}},module:function(a){return{id:a,uri:"",exports:r[a],config:m(a)}}},n=function(a,c,d,f){var h,k,m,n,o,t,v,w=[],x=typeof d;if(f=f||a,t=l(f),"undefined"===x||"function"===x){for(c=!c.length&&d.length?["require","exports","module"]:c,o=0;o0&&(b.call(arguments,a.prototype.constructor),e=c.prototype.constructor),e.apply(this,arguments)}function e(){this.constructor=d}var f=b(c),g=b(a);c.displayName=a.displayName,d.prototype=new e;for(var h=0;h":">",'"':""","'":"'","/":"/"};return"string"!=typeof a?a:String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})},c.appendMany=function(b,c){if("1.7"===a.fn.jquery.substr(0,3)){var d=a();a.map(c,function(a){d=d.add(a)}),c=d}b.append(c)},c.__cache={};var e=0;return c.GetUniqueElementId=function(a){var b=a.getAttribute("data-select2-id");return null==b&&(a.id?(b=a.id,a.setAttribute("data-select2-id",b)):(a.setAttribute("data-select2-id",++e),b=e.toString())),b},c.StoreData=function(a,b,d){var e=c.GetUniqueElementId(a);c.__cache[e]||(c.__cache[e]={}),c.__cache[e][b]=d},c.GetData=function(b,d){var e=c.GetUniqueElementId(b);return d?c.__cache[e]&&null!=c.__cache[e][d]?c.__cache[e][d]:a(b).data(d):c.__cache[e]},c.RemoveData=function(a){var b=c.GetUniqueElementId(a);null!=c.__cache[b]&&delete c.__cache[b]},c}),b.define("select2/results",["jquery","./utils"],function(a,b){function c(a,b,d){this.$element=a,this.data=d,this.options=b,c.__super__.constructor.call(this)}return b.Extend(c,b.Observable),c.prototype.render=function(){var b=a('