commit 5e978d6e4f4c78b0735a7520e36cb307d74e7914 Author: Henintsoa Date: Fri Apr 16 11:34:24 2021 +0300 Aren new update diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..0371133 --- /dev/null +++ b/.classpath @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4af02b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +.vscode/ + +# Configuration files +#src/main/resources/application.properties +#src/main/resources/META-INF/persistence.xml + +launch.json \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..5c98b42 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,2 @@ +# Default ignored files +/workspace.xml \ No newline at end of file diff --git a/.idea/aren.iml b/.idea/aren.iml new file mode 100644 index 0000000..033870c --- /dev/null +++ b/.idea/aren.iml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..154b848 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__antlr_antlr_2_7_7.xml b/.idea/libraries/Maven__antlr_antlr_2_7_7.xml new file mode 100644 index 0000000..b8d93d8 --- /dev/null +++ b/.idea/libraries/Maven__antlr_antlr_2_7_7.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_classmate_1_3_4.xml b/.idea/libraries/Maven__com_fasterxml_classmate_1_3_4.xml new file mode 100644 index 0000000..33c30b4 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_classmate_1_3_4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_11_0.xml b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_11_0.xml new file mode 100644 index 0000000..32a9faa --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_11_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_11_0.xml b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_11_0.xml new file mode 100644 index 0000000..8c0738d --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_11_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_11_0.xml b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_11_0.xml new file mode 100644 index 0000000..0c83f99 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_11_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_xml_2_11_0.xml b/.idea/libraries/Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_xml_2_11_0.xml new file mode 100644 index 0000000..042804f --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_xml_2_11_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_yaml_2_11_1.xml b/.idea/libraries/Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_yaml_2_11_1.xml new file mode 100644 index 0000000..27241b7 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_yaml_2_11_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_hibernate5_2_11_0.xml b/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_hibernate5_2_11_0.xml new file mode 100644 index 0000000..d38ea19 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_hibernate5_2_11_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_11_0.xml b/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_11_0.xml new file mode 100644 index 0000000..6026270 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_11_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_11_0.xml b/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_11_0.xml new file mode 100644 index 0000000..fa76777 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_11_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_jaxrs_jackson_jaxrs_base_2_11_1.xml b/.idea/libraries/Maven__com_fasterxml_jackson_jaxrs_jackson_jaxrs_base_2_11_1.xml new file mode 100644 index 0000000..8c3c8f1 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_jaxrs_jackson_jaxrs_base_2_11_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_jaxrs_jackson_jaxrs_json_provider_2_11_1.xml b/.idea/libraries/Maven__com_fasterxml_jackson_jaxrs_jackson_jaxrs_json_provider_2_11_1.xml new file mode 100644 index 0000000..b7e2d99 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_jaxrs_jackson_jaxrs_json_provider_2_11_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_jaxb_annotations_2_10_1.xml b/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_jaxb_annotations_2_10_1.xml new file mode 100644 index 0000000..606e3b3 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_jaxb_annotations_2_10_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_jsonSchema_2_11_0.xml b/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_jsonSchema_2_11_0.xml new file mode 100644 index 0000000..36e3b62 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_jsonSchema_2_11_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_11_0.xml b/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_11_0.xml new file mode 100644 index 0000000..825f8a0 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_11_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_fasterxml_woodstox_woodstox_core_6_2_0.xml b/.idea/libraries/Maven__com_fasterxml_woodstox_woodstox_core_6_2_0.xml new file mode 100644 index 0000000..8b06024 --- /dev/null +++ b/.idea/libraries/Maven__com_fasterxml_woodstox_woodstox_core_6_2_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_mchange_c3p0_0_9_5_3.xml b/.idea/libraries/Maven__com_mchange_c3p0_0_9_5_3.xml new file mode 100644 index 0000000..ba45a9e --- /dev/null +++ b/.idea/libraries/Maven__com_mchange_c3p0_0_9_5_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_mchange_mchange_commons_java_0_2_15.xml b/.idea/libraries/Maven__com_mchange_mchange_commons_java_0_2_15.xml new file mode 100644 index 0000000..925ebab --- /dev/null +++ b/.idea/libraries/Maven__com_mchange_mchange_commons_java_0_2_15.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_sun_activation_jakarta_activation_1_2_2.xml b/.idea/libraries/Maven__com_sun_activation_jakarta_activation_1_2_2.xml new file mode 100644 index 0000000..fea99f0 --- /dev/null +++ b/.idea/libraries/Maven__com_sun_activation_jakarta_activation_1_2_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_sun_istack_istack_commons_runtime_3_0_7.xml b/.idea/libraries/Maven__com_sun_istack_istack_commons_runtime_3_0_7.xml new file mode 100644 index 0000000..4d7e82e --- /dev/null +++ b/.idea/libraries/Maven__com_sun_istack_istack_commons_runtime_3_0_7.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_sun_mail_javax_mail_1_6_2.xml b/.idea/libraries/Maven__com_sun_mail_javax_mail_1_6_2.xml new file mode 100644 index 0000000..f5980e4 --- /dev/null +++ b/.idea/libraries/Maven__com_sun_mail_javax_mail_1_6_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_sun_xml_fastinfoset_FastInfoset_1_2_15.xml b/.idea/libraries/Maven__com_sun_xml_fastinfoset_FastInfoset_1_2_15.xml new file mode 100644 index 0000000..de27a39 --- /dev/null +++ b/.idea/libraries/Maven__com_sun_xml_fastinfoset_FastInfoset_1_2_15.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__commons_codec_commons_codec_1_11.xml b/.idea/libraries/Maven__commons_codec_commons_codec_1_11.xml new file mode 100644 index 0000000..4c8ff54 --- /dev/null +++ b/.idea/libraries/Maven__commons_codec_commons_codec_1_11.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__commons_logging_commons_logging_1_2.xml b/.idea/libraries/Maven__commons_logging_commons_logging_1_2.xml new file mode 100644 index 0000000..eab40b3 --- /dev/null +++ b/.idea/libraries/Maven__commons_logging_commons_logging_1_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__de_svenkubiak_jBCrypt_0_4_1.xml b/.idea/libraries/Maven__de_svenkubiak_jBCrypt_0_4_1.xml new file mode 100644 index 0000000..c2fe437 --- /dev/null +++ b/.idea/libraries/Maven__de_svenkubiak_jBCrypt_0_4_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__io_github_classgraph_classgraph_4_8_65.xml b/.idea/libraries/Maven__io_github_classgraph_classgraph_4_8_65.xml new file mode 100644 index 0000000..556146d --- /dev/null +++ b/.idea/libraries/Maven__io_github_classgraph_classgraph_4_8_65.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__io_jsonwebtoken_jjwt_0_9_1.xml b/.idea/libraries/Maven__io_jsonwebtoken_jjwt_0_9_1.xml new file mode 100644 index 0000000..f25b99b --- /dev/null +++ b/.idea/libraries/Maven__io_jsonwebtoken_jjwt_0_9_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__io_swagger_core_v3_swagger_annotations_2_1_4.xml b/.idea/libraries/Maven__io_swagger_core_v3_swagger_annotations_2_1_4.xml new file mode 100644 index 0000000..4cb0546 --- /dev/null +++ b/.idea/libraries/Maven__io_swagger_core_v3_swagger_annotations_2_1_4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__io_swagger_core_v3_swagger_core_2_1_4.xml b/.idea/libraries/Maven__io_swagger_core_v3_swagger_core_2_1_4.xml new file mode 100644 index 0000000..01bfb1a --- /dev/null +++ b/.idea/libraries/Maven__io_swagger_core_v3_swagger_core_2_1_4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__io_swagger_core_v3_swagger_integration_2_1_4.xml b/.idea/libraries/Maven__io_swagger_core_v3_swagger_integration_2_1_4.xml new file mode 100644 index 0000000..5b98f47 --- /dev/null +++ b/.idea/libraries/Maven__io_swagger_core_v3_swagger_integration_2_1_4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__io_swagger_core_v3_swagger_jaxrs2_2_1_4.xml b/.idea/libraries/Maven__io_swagger_core_v3_swagger_jaxrs2_2_1_4.xml new file mode 100644 index 0000000..f7eee93 --- /dev/null +++ b/.idea/libraries/Maven__io_swagger_core_v3_swagger_jaxrs2_2_1_4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__io_swagger_core_v3_swagger_models_2_1_4.xml b/.idea/libraries/Maven__io_swagger_core_v3_swagger_models_2_1_4.xml new file mode 100644 index 0000000..d29e088 --- /dev/null +++ b/.idea/libraries/Maven__io_swagger_core_v3_swagger_models_2_1_4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml b/.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml new file mode 100644 index 0000000..be90656 --- /dev/null +++ b/.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml b/.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml new file mode 100644 index 0000000..cba9dd2 --- /dev/null +++ b/.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__jakarta_validation_jakarta_validation_api_2_0_2.xml b/.idea/libraries/Maven__jakarta_validation_jakarta_validation_api_2_0_2.xml new file mode 100644 index 0000000..e66afb9 --- /dev/null +++ b/.idea/libraries/Maven__jakarta_validation_jakarta_validation_api_2_0_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__jakarta_ws_rs_jakarta_ws_rs_api_2_1_6.xml b/.idea/libraries/Maven__jakarta_ws_rs_jakarta_ws_rs_api_2_1_6.xml new file mode 100644 index 0000000..fb37acc --- /dev/null +++ b/.idea/libraries/Maven__jakarta_ws_rs_jakarta_ws_rs_api_2_1_6.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml b/.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml new file mode 100644 index 0000000..04213f7 --- /dev/null +++ b/.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__javax_activation_activation_1_1.xml b/.idea/libraries/Maven__javax_activation_activation_1_1.xml new file mode 100644 index 0000000..180d587 --- /dev/null +++ b/.idea/libraries/Maven__javax_activation_activation_1_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__javax_activation_javax_activation_api_1_2_0.xml b/.idea/libraries/Maven__javax_activation_javax_activation_api_1_2_0.xml new file mode 100644 index 0000000..ff49512 --- /dev/null +++ b/.idea/libraries/Maven__javax_activation_javax_activation_api_1_2_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__javax_enterprise_cdi_api_2_0_SP1.xml b/.idea/libraries/Maven__javax_enterprise_cdi_api_2_0_SP1.xml new file mode 100644 index 0000000..2323d04 --- /dev/null +++ b/.idea/libraries/Maven__javax_enterprise_cdi_api_2_0_SP1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__javax_inject_javax_inject_1.xml b/.idea/libraries/Maven__javax_inject_javax_inject_1.xml new file mode 100644 index 0000000..93cf65a --- /dev/null +++ b/.idea/libraries/Maven__javax_inject_javax_inject_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__javax_javaee_web_api_8_0_1.xml b/.idea/libraries/Maven__javax_javaee_web_api_8_0_1.xml new file mode 100644 index 0000000..8182bf4 --- /dev/null +++ b/.idea/libraries/Maven__javax_javaee_web_api_8_0_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__javax_persistence_javax_persistence_api_2_2.xml b/.idea/libraries/Maven__javax_persistence_javax_persistence_api_2_2.xml new file mode 100644 index 0000000..b7d39c6 --- /dev/null +++ b/.idea/libraries/Maven__javax_persistence_javax_persistence_api_2_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__javax_transaction_javax_transaction_api_1_3.xml b/.idea/libraries/Maven__javax_transaction_javax_transaction_api_1_3.xml new file mode 100644 index 0000000..8f5f3c6 --- /dev/null +++ b/.idea/libraries/Maven__javax_transaction_javax_transaction_api_1_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__javax_validation_validation_api_1_1_0_Final.xml b/.idea/libraries/Maven__javax_validation_validation_api_1_1_0_Final.xml new file mode 100644 index 0000000..940ce73 --- /dev/null +++ b/.idea/libraries/Maven__javax_validation_validation_api_1_1_0_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__javax_xml_bind_jaxb_api_2_3_1.xml b/.idea/libraries/Maven__javax_xml_bind_jaxb_api_2_3_1.xml new file mode 100644 index 0000000..059f88f --- /dev/null +++ b/.idea/libraries/Maven__javax_xml_bind_jaxb_api_2_3_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_9_10.xml b/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_9_10.xml new file mode 100644 index 0000000..9bddfcc --- /dev/null +++ b/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_9_10.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_7.xml b/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_7.xml new file mode 100644 index 0000000..28edf49 --- /dev/null +++ b/.idea/libraries/Maven__org_apache_commons_commons_lang3_3_7.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apache_httpcomponents_httpclient_4_5_9.xml b/.idea/libraries/Maven__org_apache_httpcomponents_httpclient_4_5_9.xml new file mode 100644 index 0000000..c76dc2d --- /dev/null +++ b/.idea/libraries/Maven__org_apache_httpcomponents_httpclient_4_5_9.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_apache_httpcomponents_httpcore_4_4_13.xml b/.idea/libraries/Maven__org_apache_httpcomponents_httpcore_4_4_13.xml new file mode 100644 index 0000000..b475675 --- /dev/null +++ b/.idea/libraries/Maven__org_apache_httpcomponents_httpcore_4_4_13.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_codehaus_woodstox_stax2_api_4_2.xml b/.idea/libraries/Maven__org_codehaus_woodstox_stax2_api_4_2.xml new file mode 100644 index 0000000..30ed863 --- /dev/null +++ b/.idea/libraries/Maven__org_codehaus_woodstox_stax2_api_4_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_dom4j_dom4j_2_1_1.xml b/.idea/libraries/Maven__org_dom4j_dom4j_2_1_1.xml new file mode 100644 index 0000000..6c8b371 --- /dev/null +++ b/.idea/libraries/Maven__org_dom4j_dom4j_2_1_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_hk2_external_aopalliance_repackaged_2_6_1.xml b/.idea/libraries/Maven__org_glassfish_hk2_external_aopalliance_repackaged_2_6_1.xml new file mode 100644 index 0000000..aa22cc1 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_hk2_external_aopalliance_repackaged_2_6_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_hk2_external_jakarta_inject_2_6_1.xml b/.idea/libraries/Maven__org_glassfish_hk2_external_jakarta_inject_2_6_1.xml new file mode 100644 index 0000000..98fbebf --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_hk2_external_jakarta_inject_2_6_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_hk2_hk2_api_2_6_1.xml b/.idea/libraries/Maven__org_glassfish_hk2_hk2_api_2_6_1.xml new file mode 100644 index 0000000..963f506 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_hk2_hk2_api_2_6_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_hk2_hk2_locator_2_6_1.xml b/.idea/libraries/Maven__org_glassfish_hk2_hk2_locator_2_6_1.xml new file mode 100644 index 0000000..951e584 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_hk2_hk2_locator_2_6_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_hk2_hk2_utils_2_6_1.xml b/.idea/libraries/Maven__org_glassfish_hk2_hk2_utils_2_6_1.xml new file mode 100644 index 0000000..57730c4 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_hk2_hk2_utils_2_6_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_hk2_osgi_resource_locator_1_0_3.xml b/.idea/libraries/Maven__org_glassfish_hk2_osgi_resource_locator_1_0_3.xml new file mode 100644 index 0000000..18fdf9c --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_hk2_osgi_resource_locator_1_0_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jaxb_jaxb_runtime_2_3_1.xml b/.idea/libraries/Maven__org_glassfish_jaxb_jaxb_runtime_2_3_1.xml new file mode 100644 index 0000000..0c7a80a --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jaxb_jaxb_runtime_2_3_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jaxb_txw2_2_3_1.xml b/.idea/libraries/Maven__org_glassfish_jaxb_txw2_2_3_1.xml new file mode 100644 index 0000000..638d937 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jaxb_txw2_2_3_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_containers_jersey_container_servlet_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_containers_jersey_container_servlet_2_31.xml new file mode 100644 index 0000000..a2053ba --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_containers_jersey_container_servlet_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_containers_jersey_container_servlet_core_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_containers_jersey_container_servlet_core_2_31.xml new file mode 100644 index 0000000..0ad7e14 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_containers_jersey_container_servlet_core_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_core_jersey_client_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_core_jersey_client_2_31.xml new file mode 100644 index 0000000..f17f3df --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_core_jersey_client_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_core_jersey_common_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_core_jersey_common_2_31.xml new file mode 100644 index 0000000..f2eb409 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_core_jersey_common_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_core_jersey_server_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_core_jersey_server_2_31.xml new file mode 100644 index 0000000..50d19a5 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_core_jersey_server_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_ext_cdi_jersey_cdi1x_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_ext_cdi_jersey_cdi1x_2_31.xml new file mode 100644 index 0000000..7a9a7bf --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_ext_cdi_jersey_cdi1x_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_ext_jersey_entity_filtering_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_ext_jersey_entity_filtering_2_31.xml new file mode 100644 index 0000000..f654024 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_ext_jersey_entity_filtering_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_inject_jersey_hk2_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_inject_jersey_hk2_2_31.xml new file mode 100644 index 0000000..20720ab --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_inject_jersey_hk2_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_jaxb_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_jaxb_2_31.xml new file mode 100644 index 0000000..a558635 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_jaxb_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_json_jackson_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_json_jackson_2_31.xml new file mode 100644 index 0000000..eb34756 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_json_jackson_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_multipart_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_multipart_2_31.xml new file mode 100644 index 0000000..21d00ec --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_multipart_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_sse_2_31.xml b/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_sse_2_31.xml new file mode 100644 index 0000000..acde912 --- /dev/null +++ b/.idea/libraries/Maven__org_glassfish_jersey_media_jersey_media_sse_2_31.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_hibernate_common_hibernate_commons_annotations_5_1_0_Final.xml b/.idea/libraries/Maven__org_hibernate_common_hibernate_commons_annotations_5_1_0_Final.xml new file mode 100644 index 0000000..1fd775b --- /dev/null +++ b/.idea/libraries/Maven__org_hibernate_common_hibernate_commons_annotations_5_1_0_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_hibernate_hibernate_c3p0_5_4_3_Final.xml b/.idea/libraries/Maven__org_hibernate_hibernate_c3p0_5_4_3_Final.xml new file mode 100644 index 0000000..e97891f --- /dev/null +++ b/.idea/libraries/Maven__org_hibernate_hibernate_c3p0_5_4_3_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_hibernate_hibernate_core_5_4_3_Final.xml b/.idea/libraries/Maven__org_hibernate_hibernate_core_5_4_3_Final.xml new file mode 100644 index 0000000..c4e3e46 --- /dev/null +++ b/.idea/libraries/Maven__org_hibernate_hibernate_core_5_4_3_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_javassist_javassist_3_22_0_GA.xml b/.idea/libraries/Maven__org_javassist_javassist_3_22_0_GA.xml new file mode 100644 index 0000000..ad65915 --- /dev/null +++ b/.idea/libraries/Maven__org_javassist_javassist_3_22_0_GA.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_classfilewriter_jboss_classfilewriter_1_2_4_Final.xml b/.idea/libraries/Maven__org_jboss_classfilewriter_jboss_classfilewriter_1_2_4_Final.xml new file mode 100644 index 0000000..2074062 --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_classfilewriter_jboss_classfilewriter_1_2_4_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_jandex_2_0_5_Final.xml b/.idea/libraries/Maven__org_jboss_jandex_2_0_5_Final.xml new file mode 100644 index 0000000..34e9ada --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_jandex_2_0_5_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_2_1_Final.xml b/.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_2_1_Final.xml new file mode 100644 index 0000000..ce63724 --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_2_1_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_spec_javax_annotation_jboss_annotations_api_1_3_spec_1_0_0_Final.xml b/.idea/libraries/Maven__org_jboss_spec_javax_annotation_jboss_annotations_api_1_3_spec_1_0_0_Final.xml new file mode 100644 index 0000000..17df4e7 --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_spec_javax_annotation_jboss_annotations_api_1_3_spec_1_0_0_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_spec_javax_el_jboss_el_api_3_0_spec_1_0_13_Final.xml b/.idea/libraries/Maven__org_jboss_spec_javax_el_jboss_el_api_3_0_spec_1_0_13_Final.xml new file mode 100644 index 0000000..8f7baba --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_spec_javax_el_jboss_el_api_3_0_spec_1_0_13_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_spec_javax_interceptor_jboss_interceptors_api_1_2_spec_1_0_0_Final.xml b/.idea/libraries/Maven__org_jboss_spec_javax_interceptor_jboss_interceptors_api_1_2_spec_1_0_0_Final.xml new file mode 100644 index 0000000..bbc5d7d --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_spec_javax_interceptor_jboss_interceptors_api_1_2_spec_1_0_0_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_spec_javax_transaction_jboss_transaction_api_1_2_spec_1_1_1_Final.xml b/.idea/libraries/Maven__org_jboss_spec_javax_transaction_jboss_transaction_api_1_2_spec_1_1_1_Final.xml new file mode 100644 index 0000000..ec03510 --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_spec_javax_transaction_jboss_transaction_api_1_2_spec_1_1_1_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_weld_environment_weld_environment_common_3_1_1_Final.xml b/.idea/libraries/Maven__org_jboss_weld_environment_weld_environment_common_3_1_1_Final.xml new file mode 100644 index 0000000..fb2c49f --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_weld_environment_weld_environment_common_3_1_1_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_weld_module_weld_jsf_3_1_1_Final.xml b/.idea/libraries/Maven__org_jboss_weld_module_weld_jsf_3_1_1_Final.xml new file mode 100644 index 0000000..edd67d7 --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_weld_module_weld_jsf_3_1_1_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_weld_module_weld_web_3_1_1_Final.xml b/.idea/libraries/Maven__org_jboss_weld_module_weld_web_3_1_1_Final.xml new file mode 100644 index 0000000..2784191 --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_weld_module_weld_web_3_1_1_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_weld_probe_weld_probe_core_3_1_1_Final.xml b/.idea/libraries/Maven__org_jboss_weld_probe_weld_probe_core_3_1_1_Final.xml new file mode 100644 index 0000000..ebd477a --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_weld_probe_weld_probe_core_3_1_1_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_weld_servlet_weld_servlet_core_3_1_1_Final.xml b/.idea/libraries/Maven__org_jboss_weld_servlet_weld_servlet_core_3_1_1_Final.xml new file mode 100644 index 0000000..e22ed06 --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_weld_servlet_weld_servlet_core_3_1_1_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_weld_weld_api_3_1_Final.xml b/.idea/libraries/Maven__org_jboss_weld_weld_api_3_1_Final.xml new file mode 100644 index 0000000..a73cf79 --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_weld_weld_api_3_1_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_weld_weld_core_impl_3_1_1_Final.xml b/.idea/libraries/Maven__org_jboss_weld_weld_core_impl_3_1_1_Final.xml new file mode 100644 index 0000000..5366f8e --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_weld_weld_core_impl_3_1_1_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jboss_weld_weld_spi_3_1_Final.xml b/.idea/libraries/Maven__org_jboss_weld_weld_spi_3_1_Final.xml new file mode 100644 index 0000000..aa973c5 --- /dev/null +++ b/.idea/libraries/Maven__org_jboss_weld_weld_spi_3_1_Final.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jsoup_jsoup_1_13_1.xml b/.idea/libraries/Maven__org_jsoup_jsoup_1_13_1.xml new file mode 100644 index 0000000..937e3c0 --- /dev/null +++ b/.idea/libraries/Maven__org_jsoup_jsoup_1_13_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jvnet_mimepull_mimepull_1_9_13.xml b/.idea/libraries/Maven__org_jvnet_mimepull_mimepull_1_9_13.xml new file mode 100644 index 0000000..ec9caa2 --- /dev/null +++ b/.idea/libraries/Maven__org_jvnet_mimepull_mimepull_1_9_13.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jvnet_staxex_stax_ex_1_8.xml b/.idea/libraries/Maven__org_jvnet_staxex_stax_ex_1_8.xml new file mode 100644 index 0000000..ee8e8ef --- /dev/null +++ b/.idea/libraries/Maven__org_jvnet_staxex_stax_ex_1_8.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_odftoolkit_odfdom_java_0_8_7.xml b/.idea/libraries/Maven__org_odftoolkit_odfdom_java_0_8_7.xml new file mode 100644 index 0000000..5e50755 --- /dev/null +++ b/.idea/libraries/Maven__org_odftoolkit_odfdom_java_0_8_7.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_postgresql_postgresql_42_2_6.xml b/.idea/libraries/Maven__org_postgresql_postgresql_42_2_6.xml new file mode 100644 index 0000000..97d7125 --- /dev/null +++ b/.idea/libraries/Maven__org_postgresql_postgresql_42_2_6.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_25.xml b/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_25.xml new file mode 100644 index 0000000..20e8163 --- /dev/null +++ b/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_25.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_yaml_snakeyaml_1_26.xml b/.idea/libraries/Maven__org_yaml_snakeyaml_1_26.xml new file mode 100644 index 0000000..e998675 --- /dev/null +++ b/.idea/libraries/Maven__org_yaml_snakeyaml_1_26.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__xerces_xercesImpl_2_9_1.xml b/.idea/libraries/Maven__xerces_xercesImpl_2_9_1.xml new file mode 100644 index 0000000..19d39db --- /dev/null +++ b/.idea/libraries/Maven__xerces_xercesImpl_2_9_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__xml_apis_xml_apis_1_0_b2.xml b/.idea/libraries/Maven__xml_apis_xml_apis_1_0_b2.xml new file mode 100644 index 0000000..c36e717 --- /dev/null +++ b/.idea/libraries/Maven__xml_apis_xml_apis_1_0_b2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..dd6abf3 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..a331408 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.project b/.project new file mode 100644 index 0000000..e6d7786 --- /dev/null +++ b/.project @@ -0,0 +1,40 @@ + + + aren + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + + + + 1610454680507 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..abdea9a --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.apt.core.prefs b/.settings/org.eclipse.jdt.apt.core.prefs new file mode 100644 index 0000000..d4313d4 --- /dev/null +++ b/.settings/org.eclipse.jdt.apt.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.apt.aptEnabled=false diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..1b6e1ef --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 0000000..6c4d534 --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,32 @@ +# Contributors + +## List and function of all the different contributors of the AREN platform + +### LIRMM +* **Mathieu Lafourcade** - *Project manager* and *Natural Language Processing* +* **Noémie-Fleur Sandillon-Rezer** - *IT developer* and *Natural Language Processing* +* **Florent Descroix** - *IT developer* and *Design* + +### LIRDEF +* **Manuel Bächtold** - *Pedagogy of the debate* and *Contact with teaching* +* **Valérie Munier** - *Pedagogy of the debate* and *Contact with teaching* +* **Gabriel Pallarès** - *PhD : Develop the argumentative skills of high school students through numerical debates on Socio-Scientific Questions Towards a didactics of argumentation and critical thinking* +* **Kevin de Checchi** - *PhD : The training of argumentation and the development of critical thinking: contributions of personal epistemology and reflexive activities* +* **Capucine Huet** - *PhD : Digital debate and learning disabilities: a new field of possibilities?* + +### Mezoa +* **Damien Hinsinger** - *Visualisation* + +### Cartodébat +* **Claire Ollagnon** - *UX Design* and *Participative conception of the uses* +* **Philippe Estival** - *IT developer of the seminal version Dialoguea* + +### Académie de Montpellier +* **Sébastien Méjean** - *Link with the Academy* + +### Forum des débats +* **Jean Sallantin** - *Formal foundations* +* **Véronique Pinet** - *Philosophical foundation* + +### Controversciences +* **Thibault Latrille** - *Texts founding* diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..01d98cf --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 aren-consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6738a3b --- /dev/null +++ b/README.md @@ -0,0 +1,110 @@ + + +# AREN (ARgumentation Et Numérique) + +The AREN project (in French, ARgumentation Et Numérique ; argumentation and digital) aims to develop a digital platform for online debates that promotes the development of people' argumentative skills and their critical thinking, through a citizenship education perspective. This platform allows the simultaneous participation of a large number of people in a debate, offers time to build arguments and allows to keep track of exchanges, support for reflective work. + +The project has two research components : +* A didactic component consists of experimenting with the platform in order to assess its impact and suggest changes. +* An artificial intelligence (AI) component focuses on the automatic processing of natural language and aims to develop and evaluate an AI service for thematic classification of student interventions, facilitating their analysis and the preparation of the reflective synthesis. + +## Getting Started + +These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system. + +### Prerequisites + +* Java Web server (Test and work on Apache-Tomcat 7.0.80+) +* Maven +* PostgreSQL + +## Installation +### Database +Install and configure PostgreSQL specificaly to your OS, check the documentation, to ensure having a secure and remote accessible database. + +Create the user that will manage your database. Repalce `[db_user]` and `[db_password]` by your own choices. +`CREATE USER [db_user] WITH PASSWORD '[db_password]';` +Create the database, Replace `[db_name]` by your own choice. +`CREATE DATABASE [db_name] OWNER [db_user];` + +### Configuration +Download and extracte the sources in the repository of your choice. + +**Copy** the `application.properties` file from the `config` folder to the `src/main/resources` folder. +Fill the empty properties, the documentation is in the file itself. + +**Copy** the `persistence.xml` file from the `config` forlder to the `src/main/resources/META-INF` folder. +Fill the following line with the `db_user`, `db_password` and `db_name` previously set. + + + + + + +## Build +Go to the source folder and run `mvn clean install`. +A `target` folder is then created with the `aren.war` file inside. + +## Deployement +Rename the `aren.war` file to `ROOT.war`then copy it into the Java WebSever of your choice [Tomcat 7 tested and functional]. + +If you do not want the software to run at the root of your serveur, you'll need to change the `path` variable of the `context.xml` file according to the name of your `war` file + +### First launch +Go in your webserver folder, in the application folder. +Edit the `persistence.xml` in the `WEB-INF/classes/META-INF` folder. +Uncomment the two following lines to allow the application to build the whole database. + + + +Restart your webserver. + +**! WARNING !** +**To avoid any data loss yous have to re-comment those previous lines. Otherwise the full database will be rebuilt at every restart of the application !** + +## API super-admin credentials +The default credentials for the super-admin are **admin:password** +Those can be easily change throught the web interface or with an API call. + +## Documentation +The web interface is shiped with an useful *help* button. Use it if you have any issues. +The REST API documentation can be found [here](https://app.swaggerhub.com/apis-docs/aren-consortium/aren-api/3.0.0). +You can access the openapi desc directly through the application with the url `/ws/openapi.[json|yaml]` + + + +## Running the tests + +@TODO + +## Built With + +* [Maven](https://maven.apache.org/) - Dependency Management +* [Vue.js](https://vuejs.org/) - Web framework used +* [Vue-i18n](https://kazupon.github.io/vue-i18n/) - Internationalization tool for Vue.js +* [Vue-router](https://router.vuejs.org/) - Single Page Website tool for Vue.js +* [http-vue-loader](https://github.com/FranckFreiburger/http-vue-loader) - Async .vue file loading for Vue.js +* [Materialize](https://materializecss.com/) - CSS framwork used +* [D3.js](https://d3js.org/) - Visualization tool + +## Contributing + +@TODO + +## Versioning + +We use [SemVer](http://semver.org/) for versioning. + +## Authors + +* **Noémie-Fleur Sandillon-Rezer** - *Initial work, full-stack of v1.0.0* - [noemie-fleur.sandillon-rezer@lirmm.fr](mailto:noemie-fleur.sandillon-rezer@lirmm.fr?subject=[AREN]%20) +* **Florent Descroix** - *Complete rework, full stack since v3.0.0* - [florent.descroix@lirmm.fr](mailto:florent.descroix@lirmm.fr?subject=[AREN]%20) + +See also the list of [CONTRIBUTORS](CONTRIBUTORS.md) who participated in this project. + +## License + +This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details + +## Acknowledgment +[Official website](http://www.lirmm.fr/aren) diff --git a/nb-configuration.xml b/nb-configuration.xml new file mode 100644 index 0000000..b6bf903 --- /dev/null +++ b/nb-configuration.xml @@ -0,0 +1,26 @@ + + + + + + ide + true + true + /WEB-INF/sass:/assets/css + /less:/css + false + + + Tomcat + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..60d38c7 --- /dev/null +++ b/pom.xml @@ -0,0 +1,252 @@ + + 4.0.0 + + fr.lirmm + aren + 3.8.0 + war + + aren + + + ${project.build.directory}/endorsed + UTF-8 + 1.8 + 1.8 + + 1.1 + 2.31 + 2.11.0 + 0.9.1 + 3.1.1.Final + 0.4.1 + 5.4.3.Final + 42.2.6 + + + + + + + io.swagger.core.v3 + swagger-jaxrs2 + 2.1.4 + + + io.swagger.core.v3 + swagger-annotations + 2.1.4 + jar + + + + + org.odftoolkit + odfdom-java + 0.8.7 + + + + + com.sun.mail + javax.mail + 1.6.2 + + + javax + javaee-web-api + 8.0.1 + provided + + + javax.xml.bind + jaxb-api + 2.3.1 + + + xml-apis + xml-apis + 1.0.b2 + + + + + org.apache.httpcomponents + httpcore + 4.4.13 + jar + + + org.apache.httpcomponents + httpclient + 4.5.9 + jar + + + + + org.glassfish.jersey.core + jersey-common + ${jersey.version} + + + org.glassfish.jersey.core + jersey-server + 2.31 + jar + + + org.glassfish.jersey.containers + jersey-container-servlet + ${jersey.version} + + + org.glassfish.jersey.ext.cdi + jersey-cdi1x + ${jersey.version} + + + org.glassfish.jersey.media + jersey-media-json-jackson + ${jersey.version} + + + org.glassfish.jersey.core + jersey-client + ${jersey.version} + + + org.glassfish.jersey.inject + jersey-hk2 + ${jersey.version} + + + org.glassfish.jersey.media + jersey-media-sse + ${jersey.version} + + + org.glassfish.jersey.media + jersey-media-multipart + ${jersey.version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.fasterxml.jackson.module + jackson-module-parameter-names + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + ${jackson.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-hibernate5 + ${jackson.version} + + + com.fasterxml.jackson.module + jackson-module-jsonSchema + ${jackson.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson.version} + + + + + io.jsonwebtoken + jjwt + ${jjwt.version} + + + + + org.jboss.weld.servlet + weld-servlet-core + ${weld.version} + + + + + de.svenkubiak + jBCrypt + ${jbcrypt.version} + + + + + org.hibernate + hibernate-core + ${hibernate.version} + + + org.hibernate + hibernate-c3p0 + ${hibernate.version} + + + + + org.postgresql + postgresql + ${postgresql.version} + + + + + org.jsoup + jsoup + 1.13.1 + + + + + aren + + + org.apache.maven.plugins + maven-war-plugin + 2.3 + + false + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + true + + + + + + diff --git a/src/main/java/fr/lirmm/aren/exception/AbstractException.java b/src/main/java/fr/lirmm/aren/exception/AbstractException.java new file mode 100644 index 0000000..ac843cd --- /dev/null +++ b/src/main/java/fr/lirmm/aren/exception/AbstractException.java @@ -0,0 +1,31 @@ +package fr.lirmm.aren.exception; + +import java.util.HashMap; + +/** + * + * @author Florent Descroix {@literal } + */ +public class AbstractException extends RuntimeException { + + /** + * + */ + protected HashMap details = new HashMap(); + + /** + * + * @param string + */ + public AbstractException(String string) { + super(string); + } + + /** + * + * @return + */ + public HashMap getDetails() { + return details; + } +} diff --git a/src/main/java/fr/lirmm/aren/exception/AccessDeniedException.java b/src/main/java/fr/lirmm/aren/exception/AccessDeniedException.java new file mode 100644 index 0000000..3ebb5c3 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/exception/AccessDeniedException.java @@ -0,0 +1,56 @@ +package fr.lirmm.aren.exception; + +/** + * Thrown if errors occur during the authorization process. + * + * @author Florent Descroix {@literal } + */ +public class AccessDeniedException extends AbstractException { + + /** + * + */ + private static final long serialVersionUID = -6029917646671248044L; + + /** + * + * @param klass + * @param id + * @return + */ + public final static AccessDeniedException UNMUTABLE_OBJECT(Class klass, Long id) { + AccessDeniedException ade = new AccessDeniedException("unmutable_object"); + ade.details.put("type", klass.getSimpleName()); + ade.details.put("id", id+""); + return ade; + } + + /** + * + * @param klass + * @param id + * @return + */ + public final static AccessDeniedException UNERASABLE_OBJECT(Class klass, Long id) { + AccessDeniedException ade = new AccessDeniedException("unerasable_object"); + ade.details.put("type", klass.getSimpleName()); + ade.details.put("id", id+""); + return ade; + } + + /** + * + * @return + */ + public final static AccessDeniedException PERMISSION_MISSING() { + return new AccessDeniedException("permission_missing"); + } + + /** + * + * @param string + */ + private AccessDeniedException(String string) { + super(string); + } +} diff --git a/src/main/java/fr/lirmm/aren/exception/AuthenticationException.java b/src/main/java/fr/lirmm/aren/exception/AuthenticationException.java new file mode 100644 index 0000000..e05317c --- /dev/null +++ b/src/main/java/fr/lirmm/aren/exception/AuthenticationException.java @@ -0,0 +1,49 @@ +package fr.lirmm.aren.exception; + +/** + * Thrown if errors occur during the authentication process. + * + * @author Florent Descroix {@literal } + */ +public class AuthenticationException extends AbstractException { + + /** + * + */ + private static final long serialVersionUID = -315540945651188131L; + + /** + * + * @return + */ + public final static AuthenticationException BAD_CREDENTIALS() { + return new AuthenticationException("bad_credentials"); + } + + /** + * + * @param username + * @return + */ + public final static AuthenticationException INACTIVE_USER(String username) { + AuthenticationException ae = new AuthenticationException("inactive_user:" + username); + ae.details.put("username", username); + return ae; + } + + /** + * + * @return + */ + public final static AuthenticationException AUTHENTIFICATION_REQUIRED() { + return new AuthenticationException("authentification_required"); + } + + /** + * + * @param string + */ + private AuthenticationException(String string) { + super(string); + } +} diff --git a/src/main/java/fr/lirmm/aren/exception/InsertEntityException.java b/src/main/java/fr/lirmm/aren/exception/InsertEntityException.java new file mode 100644 index 0000000..6ba2d50 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/exception/InsertEntityException.java @@ -0,0 +1,63 @@ +package fr.lirmm.aren.exception; + +/** + * Thrown if an error occurs on entity insertion in DB + * + * @author Florent Descroix {@literal } + */ +public class InsertEntityException extends AbstractException { + + /** + * + */ + private static final long serialVersionUID = 8631881926079551080L; + + /** + * + * @param propertyName + * @return + */ + public static InsertEntityException MANDATORY_PROPERTY(String propertyName) { + InsertEntityException iee = new InsertEntityException("mandatory_property"); + iee.details.put("propertyName", propertyName); + return iee; + } + + /** + * + * @param keyName + * @param keyValue + * @return + */ + public static InsertEntityException DUPLICATE_KEY(String keyName, String keyValue) { + InsertEntityException iee = new InsertEntityException("duplicate_key"); + iee.details.put("keyName", keyName); + iee.details.put("keyValue", keyValue); + return iee; + } + + /** + * + * @return + */ + public static InsertEntityException INVALID_PARENT() { + return new InsertEntityException("invalid_parent"); + } + + /** + * + * @param details + * @return + */ + public static InsertEntityException OTHER(String details) { + return new InsertEntityException(details); + } + + /** + * + * @param string + */ + private InsertEntityException(String string) { + super(string); + } +} diff --git a/src/main/java/fr/lirmm/aren/exception/InvalidAuthenticationTokenException.java b/src/main/java/fr/lirmm/aren/exception/InvalidAuthenticationTokenException.java new file mode 100644 index 0000000..7e24b11 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/exception/InvalidAuthenticationTokenException.java @@ -0,0 +1,68 @@ +package fr.lirmm.aren.exception; + +/** + * Thrown if an authentication token is invalid. + * + * @author Florent Descroix {@literal } + */ +public class InvalidAuthenticationTokenException extends AbstractException { + + /** + * + */ + private static final long serialVersionUID = -2394710689872197849L; + + /** + * + * @return + */ + public final static InvalidAuthenticationTokenException INVALID_CAS_TICKET() { + return new InvalidAuthenticationTokenException("invalid_cas_ticket"); + } + + /** + * + * @param code + * @return + */ + public final static InvalidAuthenticationTokenException INVALID_CAS_TICKET(String code) { + InvalidAuthenticationTokenException iate = InvalidAuthenticationTokenException.INVALID_CAS_TICKET(); + iate.details.put("code", code); + return iate; + } + + /** + * + * @return + */ + public final static InvalidAuthenticationTokenException INVALID_TOKEN() { + return new InvalidAuthenticationTokenException("invalid_token"); + } + + /** + * + * @return + */ + public final static InvalidAuthenticationTokenException EXPIRED_TOKEN() { + return new InvalidAuthenticationTokenException("expired_token"); + } + + /** + * + * @param claimName + * @return + */ + public final static InvalidAuthenticationTokenException INVALID_CLAIM(String claimName) { + InvalidAuthenticationTokenException iate = new InvalidAuthenticationTokenException("invalid_claim"); + iate.details.put("claimName", claimName); + return iate; + } + + /** + * + * @param string + */ + private InvalidAuthenticationTokenException(String string) { + super(string); + } +} diff --git a/src/main/java/fr/lirmm/aren/model/AbstractDatedEntity.java b/src/main/java/fr/lirmm/aren/model/AbstractDatedEntity.java new file mode 100644 index 0000000..6c4ab1a --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/AbstractDatedEntity.java @@ -0,0 +1,34 @@ +package fr.lirmm.aren.model; + +import java.time.ZonedDateTime; + +import javax.persistence.Column; +import javax.persistence.MappedSuperclass; + +/** + * Model that olds a creation date + * + * @author Florent Descroix {@literal } + */ +@MappedSuperclass +public abstract class AbstractDatedEntity extends AbstractEntity { + + @Column(name = "created", nullable = false, updatable = false) + private ZonedDateTime created = ZonedDateTime.now(); + + /** + * + * @return + */ + public ZonedDateTime getCreated() { + return created; + } + + /** + * + * @param created + */ + public void setCreated(ZonedDateTime created) { + this.created = created; + } +} diff --git a/src/main/java/fr/lirmm/aren/model/AbstractEntEntity.java b/src/main/java/fr/lirmm/aren/model/AbstractEntEntity.java new file mode 100644 index 0000000..2ab4791 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/AbstractEntEntity.java @@ -0,0 +1,51 @@ +package fr.lirmm.aren.model; + +import javax.persistence.Column; +import javax.persistence.MappedSuperclass; + +/** + * Model that olds an ent id (part of the AAF) + * + * @author Florent Descroix {@literal } + */ +@MappedSuperclass +public abstract class AbstractEntEntity extends AbstractDatedEntity { + + @Column(name = "ent_id", updatable = false, unique = true) + private String entId; + + /** + * + * @return + */ + public String getEntId() { + return entId; + } + + /** + * + * @param entId + */ + public void setEntId(String entId) { + this.entId = entId; + } + + /** + * + * @param object + * @return + */ + @Override + public boolean equals(Object object) { + if (object.getClass() != this.getClass()) { + return false; + } + AbstractEntEntity other = (AbstractEntEntity) object; + if (this.getEntId() != null && other.getEntId() != null) { + return this.getEntId().equals(other.getEntId()); + } else if (this.getId() != null && other.getId() != null) { + return this.getId().equals(other.getId()); + } + return false; + } +} diff --git a/src/main/java/fr/lirmm/aren/model/AbstractEntity.java b/src/main/java/fr/lirmm/aren/model/AbstractEntity.java new file mode 100644 index 0000000..1183f97 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/AbstractEntity.java @@ -0,0 +1,178 @@ +package fr.lirmm.aren.model; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * + * Model that olds an id + * + * @author Florent Descroix {@literal } + */ +@MappedSuperclass +public abstract class AbstractEntity implements Comparable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Basic(optional = false) + @Column(name = "id") + private Long id; + + /** + * + */ + public AbstractEntity() { + } + + /** + * + * @param l + */ + public AbstractEntity(Long id) { + this.id = id; + } + + /** + * + * @return + */ + @XmlTransient + @JsonIgnore + public boolean isEditable() { + return true; + } + + /** + * + * @return + */ + @XmlTransient + @JsonIgnore + public boolean isRemovable() { + return true; + } + + /** + * + * @return + */ + public Long getId() { + return id; + } + + /** + * + * @param id + */ + public void setId(Long id) { + this.id = id; + } + + /** + * Merges the non null values of an object into this Useful to populate / + * update a persisted object + * + * @param other + */ + public void merge(AbstractEntity other) { + + // Only apply on same class + if (!this.getClass().equals(other.getClass())) { + return; + } + + // Get all methods of the current object + Method[] methods = this.getClass().getMethods(); + + for (Method getter : methods) { + // Only proceed for getter functions + if (getter.getName().startsWith("get") || getter.getName().startsWith("is")) { + + // Deduce the setter name from the getter name + String setterName = getter.getName().replaceFirst("get|is", "set"); + + try { + // Get the actual setter method + Method setter = this.getClass().getMethod(setterName, getter.getReturnType()); + // Apply the getter on the object to merge and replace the value in the actual object if it's not null + Object value = getter.invoke(other); + + if (value != null) { + /*if (value instanceof Collection) { + Collection myValue = (Collection) getter.invoke(this); + for (Object obj : (Collection) myValue) { + ((Collection) value).add(obj); + } + } else if (value instanceof Map) { + Map myValue = (Map) getter.invoke(this); + for (Map.Entry obj : ((Map) myValue).entrySortedSet()) { + ((Map) value).put(obj.getKey(), obj.getValue()); + } + }*/ + //if (!(value instanceof AbstractEntity) || ((AbstractEntity) value).getId() != null) { + setter.invoke(this, value); + //} + } + } catch (IllegalAccessException | IllegalArgumentException | SecurityException | InvocationTargetException e) { + // Really unexpected ! + System.err.println(e.getMessage()); + } catch (NoSuchMethodException e) { + // The only suposetly possible error. + // It means the field is not suposed to be updated. + } + } + } + } + + /** + * + * @return + */ + @Override + public int hashCode() { + int hash = 0; + hash += (id != null ? id.hashCode() : 0); + return hash; + } + + /** + * + * @param object + * @return + */ + @Override + public boolean equals(Object object) { + if (object == null || this == null) { + return false; + } + if (object.getClass() != this.getClass()) { + return false; + } + AbstractEntity other = this.getClass().cast(object); + return !((this.id == null && other.getId() != null) || (this.id != null && !this.id.equals(other.getId()))); + } + + /** + * + * @return + */ + @Override + public String toString() { + return "fr.lirmm.aren.model." + this.getClass().getName() + " [ id=" + id + " ]"; + } + + @Override + public int compareTo(AbstractEntity t) { + return (int) (this.getId() - t.getId()); + } +} diff --git a/src/main/java/fr/lirmm/aren/model/AbstractOwnedEntity.java b/src/main/java/fr/lirmm/aren/model/AbstractOwnedEntity.java new file mode 100644 index 0000000..36a0a1a --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/AbstractOwnedEntity.java @@ -0,0 +1,37 @@ +package fr.lirmm.aren.model; + +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.MappedSuperclass; + +/** + * Model that olds a uniq specific User + * + * @author Florent Descroix {@literal } + */ +@MappedSuperclass +public abstract class AbstractOwnedEntity extends AbstractDatedEntity { + + /** + * + */ + @JoinColumn(name = "owner_id", referencedColumnName = "id", updatable = false) + @ManyToOne(optional = false) + protected User owner; + + /** + * + * @return + */ + public User getOwner() { + return owner; + } + + /** + * + * @param owner + */ + public void setOwner(User owner) { + this.owner = owner; + } +} diff --git a/src/main/java/fr/lirmm/aren/model/Category.java b/src/main/java/fr/lirmm/aren/model/Category.java new file mode 100644 index 0000000..e40c4ad --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/Category.java @@ -0,0 +1,162 @@ +package fr.lirmm.aren.model; + +import java.io.Serializable; +import java.util.Date; +import java.util.TreeSet; +import java.util.SortedSet; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import org.hibernate.annotations.SortNatural; + +/** + * Model for Categories with anotations for storage and serialization + * + * @author Florent Descroix {@literal } + */ +@Entity +@Table(name = "categories") + +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Category.class) +public class Category extends AbstractEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 4359639152649086413L; + + @Size(max = 255) + @Column(name = "name") + private String name; + + @Size(max = 2083) + @Column(name = "picture") + private String picture; + + @OneToMany(mappedBy = "category") + @SortNatural + private SortedSet documents = new TreeSet<>(); + + @Column(name = "debates_count") + private Integer debatesCount = 0; + + @Column(name = "documents_count") + private Integer documentsCount = 0; + + @Column(name = "last_comment_date") + private Date lastCommentDate; + + /** + * + * @return + */ + public String getName() { + return name; + } + + /** + * + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * + * @return + */ + public String getPicture() { + return picture; + } + + /** + * + * @param picture + */ + public void setPicture(String picture) { + this.picture = picture; + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getDocuments() { + return documents; + } + + /** + * + * @param documents + */ + public void setDocuments(SortedSet documents) { + this.documents = documents; + } + + /** + * + * @return + */ + public Integer getDebatesCount() { + return debatesCount; + } + + /** + * + * @param debatesCount + */ + public void setDebatesCount(Integer debatesCount) { + this.debatesCount = debatesCount; + } + + /** + * + * @return + */ + public Date getLastCommentDate() { + return lastCommentDate; + } + + /** + * + * @param lastCommentDate + */ + public void setLastCommentDate(Date lastCommentDate) { + this.lastCommentDate = lastCommentDate; + } + + /** + * + * @return + */ + public Integer getDocumentsCount() { + return documentsCount; + } + + /** + * + * @param documentsCount + */ + public void setDocumentsCount(Integer documentsCount) { + this.documentsCount = documentsCount; + } + + /** + * + * @return + */ + @Override + public boolean isRemovable() { + return documentsCount == 0; + } + +} diff --git a/src/main/java/fr/lirmm/aren/model/Comment.java b/src/main/java/fr/lirmm/aren/model/Comment.java new file mode 100644 index 0000000..b4f74f4 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/Comment.java @@ -0,0 +1,558 @@ +package fr.lirmm.aren.model; + +import java.io.Serializable; +import java.util.TreeSet; +import java.util.SortedSet; + +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.JoinColumn; +import javax.persistence.Lob; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.JsonIdentityReference; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import fr.lirmm.aren.model.Comment.Hypostase; +import java.util.Arrays; +import java.util.stream.Collectors; +import javax.persistence.Convert; +import org.hibernate.annotations.SortNatural; + +import org.hibernate.annotations.Type; + +/** + * Model for Comments with anotations for storage and serialization + * + * @author Florent Descroix {@literal } + */ +@Entity +@Table(name = "comments") + +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Comment.class) +public class Comment extends AbstractOwnedEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 5278516622163143823L; + + /** + * + */ + public enum Opinion { + + /** + * + */ + FOR, + /** + * + */ + NEUTRAL, + /** + * + */ + AGAINST + } + + /** + * + */ + public enum Hypostase { + + /** + * + */ + EXPLANATION, + /** + * + */ + LAW, + /** + * + */ + PRINCIPLE, + /** + * + */ + THEORY, + /** + * + */ + BELIEF, + /** + * + */ + CONJECTURE, + /** + * + */ + HYPOTHESIS, + /** + * + */ + AXIOM, + /** + * + */ + DEFINITION, + /** + * + */ + QUALITATIVE, + /** + * + */ + VARIABLE, + /** + * + */ + OBJECT, + /** + * + */ + EVENT, + /** + * + */ + PHENOMENON, + /** + * + */ + DATA, + /** + * + */ + MODE, + /** + * + */ + DOMAIN, + /** + * + */ + QUANTITATIVE, + /** + * + */ + VARIATION, + /** + * + */ + VARIANCE, + /** + * + */ + APPROXIMATION, + /** + * + */ + VALUE, + /** + * + */ + CLUE, + /** + * + */ + INVARIANT, + /** + * + */ + DIMENSION, + /** + * + */ + STRUCTURAL, + /** + * + */ + STRUCTURE, + /** + * + */ + METHOD, + /** + * + */ + FORMALISM, + /** + * + */ + CLASSIFICATION, + /** + * + */ + PARADIGME, + /** + * + */ + DIFFICULTY, + /** + * + */ + APORIA, + /** + * + */ + PARADOXE, + /** + * + */ + PROBLEM; + } + + @Lob + @Type(type = "org.hibernate.type.TextType") + @Column(name = "reformulation") + private String reformulation; + + @Lob + @Type(type = "org.hibernate.type.TextType") + @Column(name = "argumentation") + private String argumentation; + + @Lob + @Type(type = "org.hibernate.type.TextType") + @Column(name = "selection") + private String selection; + + @Column(name = "start_container") + private String startContainer; + + @Column(name = "start_offset") + private Long startOffset; + + @Column(name = "end_container") + private String endContainer; + + @Column(name = "end_offset") + private Long endOffset; + + @Basic(optional = false) + @NotNull + @Column(name = "moderated") + private boolean moderated = false; + + @Basic(optional = false) + @NotNull + @Column(name = "signaled") + private boolean signaled = false; + + @OneToMany(mappedBy = "parent") + @SortNatural + private SortedSet comments = new TreeSet<>(); + + @JsonIdentityReference(alwaysAsId = true) + @JoinColumn(name = "parent_id", referencedColumnName = "id", updatable = false) + @ManyToOne + private Comment parent; + + @JsonIdentityReference(alwaysAsId = true) + @JoinColumn(name = "debate_id", referencedColumnName = "id", updatable = false) + @ManyToOne(optional = false) + private Debate debate; + + @Enumerated(EnumType.STRING) + @Column(name = "opinion", updatable = false) + private Opinion opinion; + + @Lob + @Type(type = "org.hibernate.type.TextType") + @Column(name = "hypostases") + private String hypostases; + + @Column(name = "tags", length = 1023) + @Convert(converter = TagSet.Converter.class) + private TagSet tags = new TagSet(); + + @Column(name = "proposed_tags", length = 1023) + @Convert(converter = TagSet.Converter.class) + private TagSet proposedTags = new TagSet(); + + /** + * + * @return + */ + public String getReformulation() { + return reformulation; + } + + /** + * + * @param reformulation + */ + public void setReformulation(String reformulation) { + this.reformulation = reformulation; + } + + /** + * + * @return + */ + public String getArgumentation() { + return argumentation; + } + + /** + * + * @param argumentation + */ + public void setArgumentation(String argumentation) { + this.argumentation = argumentation; + } + + /** + * + * @return + */ + public String getSelection() { + return selection; + } + + /** + * + * @param selection + */ + public void setSelection(String selection) { + this.selection = selection; + } + + /** + * + * @return + */ + public String getStartContainer() { + return startContainer; + } + + /** + * + * @param startContainer + */ + public void setStartContainer(String startContainer) { + this.startContainer = startContainer; + } + + /** + * + * @return + */ + public Long getStartOffset() { + return startOffset; + } + + /** + * + * @param startOffset + */ + public void setStartOffset(Long startOffset) { + this.startOffset = startOffset; + } + + /** + * + * @return + */ + public String getEndContainer() { + return endContainer; + } + + /** + * + * @param endContainer + */ + public void setEndContainer(String endContainer) { + this.endContainer = endContainer; + } + + /** + * + * @return + */ + public Long getEndOffset() { + return endOffset; + } + + /** + * + * @param endOffset + */ + public void setEndOffset(Long endOffset) { + this.endOffset = endOffset; + } + + /** + * + * @return + */ + public boolean isModerated() { + return moderated; + } + + /** + * + * @param moderated + */ + public void setModerated(boolean moderated) { + this.moderated = moderated; + } + + /** + * + * @return + */ + public boolean isSignaled() { + return signaled; + } + + /** + * + * @param signaled + */ + public void setSignaled(boolean signaled) { + this.signaled = signaled; + } + + /** + * + * @return + */ + public Opinion getOpinion() { + return opinion; + } + + /** + * + * @param opinion + */ + public void setOpinion(Opinion opinion) { + this.opinion = opinion; + } + + /** + * + * @return + */ + public SortedSet getComments() { + return comments; + } + + /** + * + * @param comments + */ + public void setComments(SortedSet comments) { + this.comments = comments; + } + + /** + * + * @return + */ + public Comment getParent() { + return parent; + } + + /** + * + * @param parent + */ + public void setParent(Comment parent) { + this.parent = parent; + } + + /** + * + * @return + */ + public Debate getDebate() { + return debate; + } + + /** + * + * @param debate + */ + public void setDebate(Debate debate) { + this.debate = debate; + } + + /** + * + * @return + */ + public SortedSet getHypostases() { + if (this.hypostases != null && this.hypostases.length() > 0) { + return Arrays.stream(this.hypostases.split(",")) + .map(Hypostase::valueOf) + .collect(Collectors.toCollection(() -> new TreeSet())); + } else { + return new TreeSet(); + } + + } + + /** + * + * @param hypostases + */ + public void setHypostases(SortedSet hypostases) { + this.hypostases = hypostases.stream() + .map(Hypostase::name) + .collect(Collectors.joining(",")); + } + + /** + * + * @return + */ + public TagSet getProposedTags() { + return proposedTags; + } + + /** + * + * @param proposedTags + */ + public void setProposedTags(TagSet proposedTags) { + this.proposedTags = proposedTags; + } + + /** + * + * @return + */ + public TagSet getTags() { + return tags; + } + + /** + * + * @param tags + */ + public void setTags(TagSet tags) { + this.tags = tags; + } + + /** + * + */ + public void removeUnusedTags() { + TagSet tagToRemove = new TagSet(); + for (TagSet.Tag tag : this.getProposedTags()) { + if (tag.isNegative() && !tags.contains(tag)) { + tagToRemove.add(tag); + } + } + this.getProposedTags().removeAll(tagToRemove); + } + +} diff --git a/src/main/java/fr/lirmm/aren/model/Debate.java b/src/main/java/fr/lirmm/aren/model/Debate.java new file mode 100644 index 0000000..2814bc4 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/Debate.java @@ -0,0 +1,358 @@ +package fr.lirmm.aren.model; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import java.time.ZonedDateTime; +import java.util.SortedSet; +import java.util.TreeSet; +import javax.persistence.FetchType; +import org.hibernate.annotations.SortNatural; +import org.hibernate.annotations.Where; + +/** + * Model for Debates with anotations for storage and serialization + * + * @author Florent Descroix {@literal } + */ +@Entity +@Table(name = "debates") + +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Debate.class) +public class Debate extends AbstractOwnedEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1862506368700355733L; + + @Size(max = 255) + @Column(name = "name") + private String name; + + @Column(name = "closed") + private ZonedDateTime closed; + + @Column(name = "is_active") + private boolean active = true; + + @JoinTable(name = "debates_teams", + joinColumns = { + @JoinColumn(name = "debate_id", referencedColumnName = "id")}, + inverseJoinColumns = { + @JoinColumn(name = "team_id", referencedColumnName = "id")}) + @ManyToMany + @SortNatural + private SortedSet teams = new TreeSet<>(); + + @JoinTable(name = "debates_guests", + joinColumns = { + @JoinColumn(name = "debate_id", referencedColumnName = "id")}, + inverseJoinColumns = { + @JoinColumn(name = "user_id", referencedColumnName = "id")}) + @ManyToMany + @Where(clause = "is_active = true") + @SortNatural + private SortedSet guests = new TreeSet<>(); + + @OneToMany(mappedBy = "debate") + @SortNatural + private SortedSet comments = new TreeSet<>(); + + @JoinColumn(name = "document_id", referencedColumnName = "id", updatable = false) + @ManyToOne(optional = false, fetch = FetchType.LAZY) + private Document document; + + @Column(name = "comments_count") + private Integer commentsCount = 0; + + @Column(name = "comments_count_for") + private Integer commentsCountFor = 0; + + @Column(name = "comments_count_against") + private Integer commentsCountAgainst = 0; + + @Column(name = "last_comment_date") + private ZonedDateTime lastCommentDate; + + @Column(name = "with_hypostases") + private boolean withHypostases = false; + + @Column(name = "reformulation_check") + private boolean reformulationCheck = true; + + @Column(name = "idfix_link") + private boolean idfixLink = false; + + @Column(name = "open_public") + private boolean openPublic = false; + + /** + * + * @return + */ + public String getName() { + return name; + } + + /** + * + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * + * @return + */ + public ZonedDateTime getClosed() { + return closed; + } + + /** + * + * @param closed + */ + public void setClosed(ZonedDateTime closed) { + this.closed = closed; + } + + /** + * + * @return + */ + public boolean isActive() { + return active; + } + + /** + * + * @param active + */ + public void setActive(boolean active) { + this.active = active; + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getTeams() { + return teams; + } + + /** + * + * @param teams + */ + public void setTeams(SortedSet teams) { + this.teams = teams; + } + + /** + * + * @param team + */ + public void addTeam(Team team) { + this.teams.add(team); + team.getDebates().add(this); + } + + /** + * + * @param team + */ + public void removeTeam(Team team) { + this.teams.remove(team); + team.getDebates().remove(this); + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getGuests() { + return guests; + } + + /** + * + * @param guests + */ + public void setGuests(SortedSet guests) { + this.guests = guests; + } + + /** + * + * @param guest + */ + public void addGuest(User guest) { + this.guests.add(guest); + guest.getInvitedDebates().add(this); + } + + /** + * + * @param guest + */ + public void removeGuest(User guest) { + this.guests.remove(guest); + guest.getInvitedDebates().remove(this); + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getComments() { + return comments; + } + + /** + * + * @param comments + */ + public void setComments(SortedSet comments) { + this.comments = comments; + } + + /** + * + * @return + */ + public Document getDocument() { + return document; + } + + /** + * + * @param document + */ + public void setDocument(Document document) { + this.document = document; + } + + /** + * + * @return + */ + public Integer getCommentsCount() { + return commentsCount; + } + + /** + * + * @return + */ + public Integer getCommentsCountFor() { + return commentsCountFor; + } + + /** + * + * @return + */ + public Integer getCommentsCountAgainst() { + return commentsCountAgainst; + } + + /** + * + * @return + */ + public ZonedDateTime getLastCommentDate() { + return lastCommentDate; + } + + /** + * + * @return + */ + public boolean isWithHypostases() { + return withHypostases; + } + + /** + * + * @param withHypostases + */ + public void setWithHypostases(boolean withHypostases) { + this.withHypostases = withHypostases; + } + + /** + * + * @return + */ + public boolean isReformulationCheck() { + return reformulationCheck; + } + + /** + * + * @param reformulationCheck + */ + public void setReformulationCheck(boolean reformulationCheck) { + this.reformulationCheck = reformulationCheck; + } + + /** + * + * @return + */ + public boolean isIdfixLink() { + return idfixLink; + } + + /** + * + * @param idfixLink + */ + public void setIdfixLink(boolean idfixLink) { + this.idfixLink = idfixLink; + } + + /** + * + * @return + */ + public boolean isOpenPublic() { + return openPublic; + } + + /** + * + * @param openPublic + */ + public void setOpenPublic(boolean openPublic) { + this.openPublic = openPublic; + } + + /** + * + * @return + */ + @Override + public boolean isRemovable() { + return comments.isEmpty(); + } + +} diff --git a/src/main/java/fr/lirmm/aren/model/Document.java b/src/main/java/fr/lirmm/aren/model/Document.java new file mode 100644 index 0000000..319d45f --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/Document.java @@ -0,0 +1,176 @@ +package fr.lirmm.aren.model; + +import java.io.Serializable; +import java.util.TreeSet; +import java.util.SortedSet; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.Lob; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import org.hibernate.annotations.SortNatural; +import org.hibernate.annotations.Type; + +/** + * Model for Documents with anotations for storage and serialization + * + * @author Florent Descroix {@literal } + */ +@Entity +@Table(name = "documents") + +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Document.class) +public class Document extends AbstractDatedEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 8507685898376675066L; + + @Size(max = 255) + @Column(name = "name") + private String name; + + @Size(max = 255) + @Column(name = "author") + private String author; + + @Lob + @Type(type = "org.hibernate.type.TextType") + @Column(name = "content") + private String content; + + @JoinColumn(name = "category_id", referencedColumnName = "id") + @ManyToOne(optional = false) + private Category category; + + @OneToMany(mappedBy = "document") + @SortNatural + private SortedSet debates = new TreeSet<>(); + + @Column(name = "debates_count") + private Integer debatesCount = 0; + + /** + * + * @return + */ + public String getName() { + return name; + } + + /** + * + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * + * @return + */ + public String getAuthor() { + return author; + } + + /** + * + * @param author + */ + public void setAuthor(String author) { + this.author = author; + } + + /** + * + * @return + */ + public String getContent() { + return content; + } + + /** + * + * @param content + */ + public void setContent(String content) { + this.content = content; + } + + /** + * + * @return + */ + public Category getCategory() { + return category; + } + + /** + * + * @param category + */ + public void setCategory(Category category) { + this.category = category; + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getDebates() { + return debates; + } + + /** + * + * @param debates + */ + public void setDebates(SortedSet debates) { + this.debates = debates; + } + + /** + * + * @return + */ + public Integer getDebatesCount() { + return debatesCount; + } + + /** + * + * @param debatesCount + */ + public void setDebatesCount(Integer debatesCount) { + this.debatesCount = debatesCount; + } + + /** + * + * @return + */ + @Override + public boolean isEditable() { + return debates.isEmpty(); + } + + /** + * + * @return + */ + @Override + public boolean isRemovable() { + return debates.isEmpty(); + } +} diff --git a/src/main/java/fr/lirmm/aren/model/Institution.java b/src/main/java/fr/lirmm/aren/model/Institution.java new file mode 100644 index 0000000..c6d5a07 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/Institution.java @@ -0,0 +1,164 @@ +package fr.lirmm.aren.model; + +import java.io.Serializable; +import java.util.TreeSet; +import java.util.SortedSet; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import org.hibernate.annotations.SortNatural; +import org.hibernate.annotations.Where; + +/** + * Model for Institutions with anotations for storage and serialization + * + * @author Florent Descroix {@literal } + */ +@Entity +@Table(name = "institutions") +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Institution.class) +public class Institution extends AbstractEntEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 4125013973438656239L; + + @Size(max = 255) + @Column(name = "type") + private String type; + + @Size(max = 255) + @Column(name = "name") + private String name; + + @Size(max = 255) + @Column(name = "academy") + private String academy; + + @OneToMany(mappedBy = "institution") + @Where(clause = "is_active = true") + @SortNatural + private SortedSet users = new TreeSet(); + + @OneToMany(mappedBy = "institution") + @SortNatural + private SortedSet teams = new TreeSet(); + + /** + * + * @return + */ + public String getName() { + return name; + } + + /** + * + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * + * @return + */ + public String getType() { + return type; + } + + /** + * + * @param type + */ + public void setType(String type) { + this.type = type; + } + + /** + * + * @return + */ + public String getAcademy() { + return academy; + } + + /** + * + * @param academy + */ + public void setAcademy(String academy) { + this.academy = academy; + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getUsers() { + return users; + } + + /** + * + * @param users + */ + public void setUsers(SortedSet users) { + this.users = users; + } + + /** + * + * @return + */ + public SortedSet getTeams() { + return teams; + } + + /** + * + * @param teams + */ + public void setTeams(SortedSet teams) { + this.teams = teams; + } + + /** + * + * @param team + */ + public void addTeam(Team team) { + team.setInstitution(this); + this.teams.add(team); + + } + + /** + * + * @return + */ + @Override + public boolean isEditable() { + return true; + } + + /** + * + * @return + */ + @Override + public boolean isRemovable() { + return true; + } + +} diff --git a/src/main/java/fr/lirmm/aren/model/Notification.java b/src/main/java/fr/lirmm/aren/model/Notification.java new file mode 100644 index 0000000..df9b686 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/Notification.java @@ -0,0 +1,198 @@ +package fr.lirmm.aren.model; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.JsonIdentityReference; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import fr.lirmm.aren.model.ws.Message; +import javax.persistence.JoinColumn; +import javax.persistence.Lob; +import javax.persistence.ManyToOne; + +/** + * Model for Notifications with anotations for storage and serialization + * + * @author Florent Descroix {@literal } + */ +@Entity +@Table(name = "notifications") + +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Notification.class) +public class Notification extends AbstractOwnedEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 6593370506138662915L; + + @Lob + private Message content; + + @Column(name = "is_unread") + private boolean unread = true; + + @JsonIdentityReference(alwaysAsId = true) + @JoinColumn(name = "debate_id", referencedColumnName = "id", updatable = false) + @ManyToOne() + private Debate debate; + + @JsonIdentityReference(alwaysAsId = true) + @JoinColumn(name = "comment_id", referencedColumnName = "id", updatable = false) + @ManyToOne() + private Comment comment; + + /** + * + */ + public Notification() { + } + + private Notification(User owner, Debate debate, Comment comment) { + this.owner = owner; + this.debate = debate; + this.comment = comment; + } + + /** + * + * @param comment + * @return + */ + public static Notification COMMENT_MODERATED(Comment comment) { + Notification n = new Notification(comment.getOwner(), comment.getDebate(), comment); + n.content = new Message("comment_moderated"); + n.content.addDetail("debateName", comment.getDebate().getDocument().getName()); + return n; + } + + /** + * + * @param modo + * @param comment + * @return + */ + public static Notification COMMENT_SINGNALED(User modo, Comment comment) { + Notification n = new Notification(modo, comment.getDebate(), comment); + n.content = new Message("comment_signaled"); + n.content.addDetail("debateName", comment.getDebate().getDocument().getName()); + return n; + } + + /** + * + * @param owner + * @param comment + * @return + */ + public static Notification COMMENT_ANSWERED(User owner, Comment comment) { + Notification n = new Notification(owner, comment.getDebate(), comment); + n.content = new Message("comment_answered"); + n.content.addDetail("firstName", comment.getOwner().getFirstName()); + n.content.addDetail("lastName", comment.getOwner().getLastName()); + return n; + } + + /** + * + * @param owner + * @param debate + * @return + */ + public static Notification INVITED_TO_DEBATE(User owner, Debate debate) { + Notification n = new Notification(owner, debate, null); + n.content = new Message("invited_to_debate"); + n.content.addDetail("debateName", debate.getDocument().getName()); + return n; + } + + /** + * + * @param owner + * @param debate + * @param team + * @return + */ + public static Notification TEAM_ADDED_TO_DEBATE(User owner, Debate debate, Team team) { + Notification n = new Notification(owner, debate, null); + n.content = new Message("team_added_to_debate"); + n.content.addDetail("debateName", debate.getDocument().getName()); + n.content.addDetail("teamName", team.getName()); + return n; + } + + /** + * + * @return + */ + public Message getContent() { + return content; + } + + /** + * + * @param content + */ + public void setContent(Message content) { + this.content = content; + } + + /** + * + * @return + */ + public boolean isUnread() { + return unread; + } + + /** + * + * @param unread + */ + public void setUnread(boolean unread) { + this.unread = unread; + } + + /** + * + * @return + */ + public Debate getDebate() { + return debate; + } + + /** + * + * @param debate + */ + public void setDebate(Debate debate) { + this.debate = debate; + } + + /** + * + * @return + */ + public Comment getComment() { + return comment; + } + + /** + * + * @param comment + */ + public void setComment(Comment comment) { + this.comment = comment; + } + + @JsonIdentityReference(alwaysAsId = true) + @Override + public User getOwner() { + return super.getOwner(); + } + +} diff --git a/src/main/java/fr/lirmm/aren/model/TagSet.java b/src/main/java/fr/lirmm/aren/model/TagSet.java new file mode 100644 index 0000000..86d88b7 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/TagSet.java @@ -0,0 +1,205 @@ +package fr.lirmm.aren.model; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.stream.Collectors; +import javax.persistence.AttributeConverter; + +/** + * + * @author florent + */ +public class TagSet extends HashSet { + + /** + * + */ + public TagSet() { + super(); + } + + /** + * + * @param serial + */ + public TagSet(String serial) { + this(); + for (String tagSerial : serial.split("\\*")) { + if (tagSerial.length() > 0) { + this.add(new Tag(tagSerial)); + } + } + } + + /** + * + * @param tag + * @return + */ + @Override + public boolean add(Tag tag) { + this.remove(tag); + return super.add(tag); + } + + /** + * + * @return + */ + @Override + public String toString() { + java.util.List tagString = this.stream().map((Tag tag) -> { + return tag.toString(); + }).collect(Collectors.toList()); + return String.join("*", tagString); + } + + /** + * + */ + @javax.persistence.Converter(autoApply = true) + public static class Converter implements AttributeConverter { + + /** + * + * @param x + * @return + */ + @Override + public String convertToDatabaseColumn(TagSet x) { + if (x == null) { + return null; + } + return x.toString(); + } + + /** + * + * @param y + * @return + */ + @Override + public TagSet convertToEntityAttribute(String y) { + if (y == null) { + return null; + } + return new TagSet(y); + } + } + + /** + * + */ + public static class Tag implements Serializable { + + private String value; + private boolean negative = false; + private Float power = 0f; + + /** + * + */ + public Tag() { + } + + /** + * + * @param serial + */ + public Tag(String serial) { + String[] split = serial.split("\\|"); + if (split.length == 2) { + split[1] = split[1].trim(); + this.power = Float.parseFloat(split[1]); + } + split[0] = split[0].trim(); + if (split[0].startsWith("-")) { + this.negative = true; + this.value = split[0].substring(1).trim(); + } else { + this.negative = false; + this.value = split[0]; + } + } + + /** + * + * @return + */ + public String getValue() { + return value; + } + + /** + * + * @param value + */ + public void setValue(String value) { + this.value = value; + } + + /** + * + * @return + */ + public boolean isNegative() { + return negative; + } + + /** + * + * @param negative + */ + public void setNegative(boolean negative) { + this.negative = negative; + } + + /** + * + * @return + */ + public Float getPower() { + return power; + } + + /** + * + * @param power + */ + public void setPower(Float power) { + this.power = power; + } + + /** + * + * @return + */ + @Override + public String toString() { + return (this.negative ? "-" : "") + this.value + (this.power == 0f ? "" : "|" + Float.toString(this.power)); + } + + /** + * + * @param t + * @return + */ + @Override + public boolean equals(Object t) { + if (t instanceof Tag) { + return this.value.equals(((Tag) t).value); + } else { + throw new IllegalArgumentException("Compared object should be a Tag"); + } + } + + /** + * + * @return + */ + @Override + public int hashCode() { + return this.value.hashCode(); + } + } +} diff --git a/src/main/java/fr/lirmm/aren/model/Team.java b/src/main/java/fr/lirmm/aren/model/Team.java new file mode 100644 index 0000000..1c077dc --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/Team.java @@ -0,0 +1,199 @@ +package fr.lirmm.aren.model; + +import java.io.Serializable; +import java.util.TreeSet; +import java.util.SortedSet; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import org.hibernate.annotations.SortNatural; +import org.hibernate.annotations.Where; + +/** + * Model for Teams with anotations for storage and serialization + * + * @author Florent Descroix {@literal } + */ +@Entity +@Table(name = "teams") +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Team.class) +public class Team extends AbstractEntEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -286738505010538851L; + + @Size(max = 255) + @Column(name = "name") + private String name; + + @Column(name = "is_community", updatable = false) + private boolean community = false; + + @JoinColumn(name = "institution_id", referencedColumnName = "id") + @ManyToOne(optional = false) + private Institution institution; + + @ManyToMany(mappedBy = "teams") + @SortNatural + private SortedSet debates = new TreeSet<>(); + + @ManyToMany(mappedBy = "teams") + @Where(clause = "is_active = true") + @SortNatural + private SortedSet users = new TreeSet<>(); + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + @Column(name = "debates_count") + private Integer debatesCount = 0; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + @Column(name = "users_count") + private Integer usersCount = 0; + + /** + * + * @return + */ + public String getName() { + return name; + } + + /** + * + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * + * @return + */ + public boolean isCommunity() { + return community; + } + + /** + * + * @param community + */ + public void setCommunity(boolean community) { + this.community = community; + } + + /** + * + * @return + */ + public Institution getInstitution() { + return institution; + } + + /** + * + * @param institution + */ + public void setInstitution(Institution institution) { + this.institution = institution; + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getDebates() { + return debates; + } + + /** + * + * @param debates + */ + public void setDebates(SortedSet debates) { + this.debates = debates; + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getUsers() { + return users; + } + + /** + * + * @param users + */ + public void setUsers(SortedSet users) { + this.users = users; + } + + /** + * + * @param user + */ + public void addUser(User user) { + this.users.add(user); + user.getTeams().add(this); + } + + /** + * + * @param user + */ + public void removeUser(User user) { + this.users.remove(user); + user.getTeams().remove(this); + } + + /** + * + * @return + */ + public Integer getDebatesCount() { + return debatesCount; + } + + /** + * + * @return + */ + public Integer getUsersCount() { + return usersCount; + } + + /** + * + * @return + */ + @Override + public boolean isEditable() { + return getEntId() == null; + } + + /** + * + * @return + */ + @Override + public boolean isRemovable() { + return getEntId() == null; + } + +} diff --git a/src/main/java/fr/lirmm/aren/model/User.java b/src/main/java/fr/lirmm/aren/model/User.java new file mode 100644 index 0000000..9a7c960 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/User.java @@ -0,0 +1,455 @@ +package fr.lirmm.aren.model; + +import java.io.Serializable; +import java.util.TreeSet; +import java.util.SortedSet; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; + +import javax.persistence.JoinTable; +import org.hibernate.annotations.Filter; +import org.hibernate.annotations.Filters; +import org.hibernate.annotations.SortNatural; + +/** + * Model for Users with anotations for storage and serialization + * + * @author Florent Descroix {@literal } + */ +@Entity +@Table(name = "users") +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = User.class) +@Filters({ + @Filter(name = "isActive", condition = "active = true") +}) +public class User extends AbstractEntEntity implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 9143251821521688592L; + + /** + * + */ + public enum Authority { + + /** + * + */ + DELETED, + /** + * + */ + GUEST, + /** + * + */ + USER, + /** + * + */ + MODO, + /** + * + */ + ADMIN, + /** + * + */ + SUPERADMIN + } + + @Size(max = 255) + @Column(name = "username", unique = true) + private String username; + + @Size(max = 255) + @Column(name = "first_name") + private String firstName; + + @Size(max = 255) + @Column(name = "last_name") + private String lastName; + + @Pattern(regexp = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message = "Invalid email")//if the field contains email address consider using this annotation to enforce field validation + @Size(max = 255) + @Column(name = "email", unique = true) + private String email; + + @Column(name = "last_login") + private ZonedDateTime lastLogin; + + @JsonIgnore + @Column(name = "token_validity") + private ZonedDateTime tokenValidity = ZonedDateTime.now().truncatedTo(ChronoUnit.SECONDS); + + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + @Column(name = "password") + private String password; + + @JsonIgnore + @Column(name = "is_active") + private boolean active = true; + + @ManyToMany(mappedBy = "guests") + @SortNatural + private SortedSet invitedDebates = new TreeSet<>(); + + @OneToMany(mappedBy = "owner") + @SortNatural + private SortedSet comments = new TreeSet<>(); + + @OneToMany(mappedBy = "owner") + @SortNatural + private SortedSet createdDebates = new TreeSet<>(); + + @JoinColumn(name = "institution_id", referencedColumnName = "id") + @ManyToOne(optional = false) + private Institution institution; + + @JoinTable(name = "teams_users", + joinColumns = { + @JoinColumn(name = "user_id", referencedColumnName = "id")}, + inverseJoinColumns = { + @JoinColumn(name = "team_id", referencedColumnName = "id")}) + @ManyToMany + @SortNatural + private SortedSet teams = new TreeSet<>(); + + @OneToMany(mappedBy = "owner") + @SortNatural + private SortedSet notifications = new TreeSet<>(); + + @Enumerated(EnumType.STRING) + @Column(name = "authority", nullable = false) + private Authority authority = Authority.GUEST; + + /** + * + * @return + */ + public String getUsername() { + return username; + } + + /** + * + * @param username + */ + public void setUsername(String username) { + this.username = username; + } + + /** + * + * @return + */ + public String getFirstName() { + return firstName; + } + + /** + * + * @param firstName + */ + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + /** + * + * @return + */ + public String getLastName() { + return lastName; + } + + /** + * + * @param lastName + */ + public void setLastName(String lastName) { + this.lastName = lastName; + } + + /** + * + * @return + */ + public String getEmail() { + return email; + } + + /** + * + * @param email + */ + public void setEmail(String email) { + this.email = email; + } + + /** + * + * @return + */ + public ZonedDateTime getLastLogin() { + return lastLogin; + } + + /** + * + * @param lastLogin + */ + public void setLastLogin(ZonedDateTime lastLogin) { + this.lastLogin = lastLogin; + } + + /** + * + * @return + */ + public ZonedDateTime getTokenValidity() { + return tokenValidity; + } + + /** + * + * @param tokenValidity + */ + public void setTokenValidity(ZonedDateTime tokenValidity) { + this.tokenValidity = tokenValidity; + } + + /** + * + * @return + */ + public String getPassword() { + return password; + } + + /** + * + * @param password + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * + * @return + */ + public boolean isActive() { + return active; + } + + /** + * + * @param active + */ + public void setActive(boolean active) { + this.active = active; + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getInvitedDebates() { + return invitedDebates; + } + + /** + * + * @param invitedDebates + */ + public void setInvitedDebates(SortedSet invitedDebates) { + this.invitedDebates = invitedDebates; + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getComments() { + return comments; + } + + /** + * + * @param comments + */ + public void setComments(SortedSet comments) { + this.comments = comments; + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getCreatedDebates() { + return createdDebates; + } + + /** + * + * @param createdDebates + */ + public void setCreatedDebates(SortedSet createdDebates) { + this.createdDebates = createdDebates; + } + + /** + * + * @return + */ + public Institution getInstitution() { + return institution; + } + + /** + * + * @param institution + */ + public void setInstitution(Institution institution) { + this.institution = institution; + } + + /** + * + * @return + */ + public SortedSet getTeams() { + return teams; + } + + /** + * + * @param teams + */ + public void setTeams(SortedSet teams) { + this.teams = teams; + } + + /** + * + * @param team + */ + public void addTeam(Team team) { + teams.add(team); + team.getUsers().add(this); + } + + /** + * + * @param team + */ + public void removeTeams(Team team) { + teams.remove(team); + team.getUsers().remove(this); + } + + /** + * + * @return + */ + @XmlTransient + public SortedSet getNotifications() { + return notifications; + } + + /** + * + * @param notifications + */ + public void setNotifications(SortedSet notifications) { + this.notifications = notifications; + } + + /** + * + * @return + */ + public Authority getAuthority() { + return authority; + } + + /** + * + * @param authority + */ + public void setAuthority(Authority authority) { + this.authority = authority; + } + + /** + * + * @param other + * @return + */ + public boolean hasSameOrMoreRightThan(User other) { + return authority.compareTo(other.getAuthority()) >= 0; + } + + /** + * + * @return + */ + @Override + public boolean isEditable() { + return institution == null; + } + + /** + * + * @return + */ + @Override + public boolean isRemovable() { + return this.getInstitution().getId() == 0L && this.getComments().size() == 0; + } + + /** + * + * @param auth + * @return + */ + public boolean is(Authority auth) { + if (this.getAuthority() == null) { + return Authority.GUEST.compareTo(auth) >= 0; + } + return this.getAuthority().compareTo(auth) >= 0; + } + + /** + * + * @param auth + * @return + */ + public boolean is(String auth) { + return this.is(Authority.valueOf(auth)); + } +} diff --git a/src/main/java/fr/lirmm/aren/model/aaf/AbstractRequest.java b/src/main/java/fr/lirmm/aren/model/aaf/AbstractRequest.java new file mode 100644 index 0000000..9906f60 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/aaf/AbstractRequest.java @@ -0,0 +1,77 @@ +package fr.lirmm.aren.model.aaf; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * Part of ficAlimMENESR object, for XML serialization. + * + * @author Florent Descroix {@literal } + */ +@XmlRootElement +public class AbstractRequest { + + @XmlElementWrapper + @XmlElements({ + @XmlElement(name = "attr", type = Attribute.class) + }) + private AttributeList operationalAttributes; + + @XmlElement + private Identifier identifier; + + /** + * + * @return + */ + @XmlTransient + public AttributeList getOperationalAttributes() { + return operationalAttributes; + } + + /** + * + * @param operationalAttributes + */ + public void setOperationalAttributes(AttributeList operationalAttributes) { + this.operationalAttributes = operationalAttributes; + } + + /** + * + * @return + */ + @XmlTransient + public Identifier getIdentifier() { + return identifier; + } + + /** + * + * @param identifier + */ + public void setIdentifier(Identifier identifier) { + this.identifier = identifier; + } + + /** + * + * @return + */ + @XmlTransient + public String getId() { + return identifier.getId(); + } + + /** + * + * @return + */ + @XmlTransient + public AttributeList getAttributes() { + return new AttributeList(); + } +} diff --git a/src/main/java/fr/lirmm/aren/model/aaf/AddRequest.java b/src/main/java/fr/lirmm/aren/model/aaf/AddRequest.java new file mode 100644 index 0000000..d74e2a6 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/aaf/AddRequest.java @@ -0,0 +1,41 @@ +package fr.lirmm.aren.model.aaf; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * Specialization of AbstractRequest for Addition. + * + * @author Florent Descroix {@literal } + */ +@XmlRootElement +public class AddRequest extends AbstractRequest { + + @XmlElementWrapper(name = "attributes") + @XmlElements({ + @XmlElement(name = "attr", type = Attribute.class) + }) + private AttributeList attributes; + + /** + * + * @return + */ + @XmlTransient + @Override + public AttributeList getAttributes() { + return attributes; + } + + /** + * + * @param attributes + */ + public void setAttributes(AttributeList attributes) { + this.attributes = attributes; + } + +} diff --git a/src/main/java/fr/lirmm/aren/model/aaf/Attribute.java b/src/main/java/fr/lirmm/aren/model/aaf/Attribute.java new file mode 100644 index 0000000..db364d9 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/aaf/Attribute.java @@ -0,0 +1,110 @@ +package fr.lirmm.aren.model.aaf; + +import java.util.Objects; +import java.util.Set; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * Part of AttributeList. + * + * @author Florent Descroix {@literal } + */ +@XmlRootElement +public class Attribute { + + @XmlAttribute(name = "name") + private String name; + + @XmlAttribute(name = "operation") + private String operation; + + @XmlElement(name = "value") + private Set values; + + Attribute() { + } + + Attribute(String name) { + this.name = name; + } + + /** + * + * @return + */ + @XmlTransient + public String getName() { + return name; + } + + /** + * + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * + * @return + */ + @XmlTransient + public String getOperation() { + return operation; + } + + /** + * + * @param operation + */ + public void setOperation(String operation) { + this.operation = operation; + } + + /** + * + * @return + */ + @XmlTransient + public Set getValues() { + return values; + } + + /** + * + * @param values + */ + public void setValues(Set values) { + this.values = values; + } + + /** + * + * @return + */ + @Override + public int hashCode() { + int hash = 7; + hash = 97 * hash + Objects.hashCode(this.name); + return hash; + } + + /** + * + * @param object + * @return + */ + @Override + public boolean equals(Object object) { + if (object instanceof Attribute) { + return this.name.equals(((Attribute) object).getName()); + } else { + return false; + } + } +} diff --git a/src/main/java/fr/lirmm/aren/model/aaf/AttributeList.java b/src/main/java/fr/lirmm/aren/model/aaf/AttributeList.java new file mode 100644 index 0000000..bafc261 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/aaf/AttributeList.java @@ -0,0 +1,173 @@ +package fr.lirmm.aren.model.aaf; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import javax.xml.bind.annotation.XmlRootElement; + +import fr.lirmm.aren.model.User.Authority; + +/** + * Part of a Request. + * + * @author Florent Descroix {@literal } + */ +@XmlRootElement +public class AttributeList extends ArrayList { + + /** + * + */ + private static final long serialVersionUID = -5945543842036181814L; + + /** + * + * @param name + * @return + */ + public Set getValuesOf(String name) { + + int i = indexOf(new Attribute(name)); + if (i == -1) { + return new HashSet<>(); + } + return get(i).getValues(); + } + + /** + * + * @param name + * @return + */ + public String getValueOf(String name) { + + int i = indexOf(new Attribute(name)); + if (i == -1) { + return null; + } + return get(i).getValues().iterator().next(); + } + + /** + * + * @return + */ + public String getFirstName() { + return getValueOf(FicAlimMENESR.PERSONNE.FIRST_NAME); + } + + /** + * + * @return + */ + public String getLastName() { + return getValueOf(FicAlimMENESR.PERSONNE.LAST_NAME); + } + + /** + * + * @return + */ + public String getEmail() { + return getValueOf(FicAlimMENESR.PERSONNE.EMAIL); + } + + /** + * + * @return + */ + public Set getClasses() { + if (!getValuesOf(FicAlimMENESR.PERSONNE.CLASSES).isEmpty()) { + return getValuesOf(FicAlimMENESR.PERSONNE.CLASSES); + } else { + return getValuesOf(FicAlimMENESR.STRUCTURE.CLASSES); + } + } + + /** + * + * @return + */ + public Set getGroups() { + if (!getValuesOf(FicAlimMENESR.PERSONNE.GROUPES).isEmpty()) { + return getValuesOf(FicAlimMENESR.PERSONNE.GROUPES); + } else { + return getValuesOf(FicAlimMENESR.STRUCTURE.GROUPES); + } + } + + /** + * + * @return + */ + public String getInstitutionId() { + return getValueOf(FicAlimMENESR.PERSONNE.INSTITUTION); + } + + /** + * + * @return + */ + public String getName() { + return getValueOf(FicAlimMENESR.STRUCTURE.NAME); + } + + /** + * + * @return + */ + public String getCategory() { + if (getValueOf(FicAlimMENESR.CATEGORY.PERSONNE) != null) { + return getValueOf(FicAlimMENESR.CATEGORY.PERSONNE); + } else if (getValueOf(FicAlimMENESR.CATEGORY.STRUCTURE) != null) { + return getValueOf(FicAlimMENESR.CATEGORY.STRUCTURE); + } + return null; + } + + /** + * + * @return + */ + public String getType() { + return getValueOf(FicAlimMENESR.STRUCTURE.TYPE); + } + + /** + * + * @return + */ + public String getAcademy() { + return getValueOf(FicAlimMENESR.STRUCTURE.ACADEMY); + } + + /** + * + * @return + */ + public Authority getAuthority() { + if (getCategory().equals(FicAlimMENESR.PERSONNE.ELEVE)) { + return Authority.USER; + } else if (getCategory().equals(FicAlimMENESR.PERSONNE.ENSEIGNANT) || getCategory().equals(FicAlimMENESR.PERSONNE.EDUC_NAT)) { + return Authority.MODO; + } + return null; + } + + /** + * + * @return + */ + public boolean isUser() { + return getValueOf(FicAlimMENESR.CATEGORY.PERSONNE) != null; + } + + /** + * + * @return + */ + public boolean isInstitution() { + return getValueOf(FicAlimMENESR.CATEGORY.STRUCTURE) != null; + } +} diff --git a/src/main/java/fr/lirmm/aren/model/aaf/DeleteRequest.java b/src/main/java/fr/lirmm/aren/model/aaf/DeleteRequest.java new file mode 100644 index 0000000..1edfe6d --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/aaf/DeleteRequest.java @@ -0,0 +1,13 @@ +package fr.lirmm.aren.model.aaf; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Specialization of AbstractRequest for Deletion. + * + * @author Florent Descroix {@literal } + */ +@XmlRootElement +public class DeleteRequest extends AbstractRequest { + +} diff --git a/src/main/java/fr/lirmm/aren/model/aaf/FicAlimMENESR.java b/src/main/java/fr/lirmm/aren/model/aaf/FicAlimMENESR.java new file mode 100644 index 0000000..12c4e9d --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/aaf/FicAlimMENESR.java @@ -0,0 +1,155 @@ +package fr.lirmm.aren.model.aaf; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * Object to serialize XML AAF file. + * + * @author Florent Descroix {@literal } + */ +@XmlRootElement(name = "ficAlimMENESR") +public class FicAlimMENESR { + + /** + * + */ + public static class CATEGORY { + + /** + * + */ + public static String PERSONNE = "categoriePersonne"; + + /** + * + */ + public static String STRUCTURE = "categorieStructure"; + } + + /** + * + */ + public static class PERSONNE { + + /** + * + */ + public static String ELEVE = "Eleve"; + + /** + * + */ + public static String ENSEIGNANT = "PersRelEleve"; + + /** + * + */ + public static String EDUC_NAT = "PersEducNat"; + + /** + * + */ + public static String LAST_NAME = "sn"; + + /** + * + */ + public static String FIRST_NAME = "givenName"; + + /** + * + */ + public static String EMAIL = "mail"; + + /** + * + */ + public static String CLASSES = "ENTEleveClasses"; + + /** + * + */ + public static String GROUPES = "ENTEleveGroupes"; + + /** + * + */ + public static String INSTITUTION = "ENTPersonStructRattach"; + } + + /** + * + */ + public static class STRUCTURE { + + /** + * + */ + public static String NAME = "ENTStructureNomCourant"; + + /** + * + */ + public static String TYPE = "ENTStructureTypeStruct"; + + /** + * + */ + public static String ACADEMY = "ENTServAcAcademie"; + + /** + * + */ + public static String CLASSES = "ENTStructureClasses"; + + /** + * + */ + public static String GROUPES = "ENTStructureGroupes"; + } + + @XmlElements({ + @XmlElement(name = "addRequest", type = AddRequest.class), + @XmlElement(name = "modifyRequest", type = ModifyRequest.class), + @XmlElement(name = "deleteRequest", type = DeleteRequest.class),}) + private List requests; + + /** + * + * @return + */ + @XmlTransient + public List getRequest() { + return requests; + } + + /** + * + * @param requests + */ + public void setRequest(List requests) { + this.requests = requests; + } + + /** + * + * @return + */ + public int length() { + + int amount = requests.size(); + for (AbstractRequest req : requests) { + if (req.getOperationalAttributes().isInstitution()) { + amount += req.getAttributes().getClasses().size(); + amount += req.getAttributes().getGroups().size(); + } + } + return amount; + } + +} diff --git a/src/main/java/fr/lirmm/aren/model/aaf/Identifier.java b/src/main/java/fr/lirmm/aren/model/aaf/Identifier.java new file mode 100644 index 0000000..a659dfb --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/aaf/Identifier.java @@ -0,0 +1,35 @@ +package fr.lirmm.aren.model.aaf; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * Part of a Request. + * + * @author Florent Descroix {@literal } + */ +@XmlRootElement +public class Identifier { + + @XmlElement + private String id; + + /** + * + * @return + */ + @XmlTransient + public String getId() { + return id; + } + + /** + * + * @param id + */ + public void setId(String id) { + this.id = id; + } + +} diff --git a/src/main/java/fr/lirmm/aren/model/aaf/ModifyRequest.java b/src/main/java/fr/lirmm/aren/model/aaf/ModifyRequest.java new file mode 100644 index 0000000..f2d2f82 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/aaf/ModifyRequest.java @@ -0,0 +1,40 @@ +package fr.lirmm.aren.model.aaf; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * Specialization of AbstractRequest for Modification. + * + * @author Florent Descroix {@literal } + */ +@XmlRootElement +public class ModifyRequest extends AbstractRequest { + + @XmlElementWrapper(name = "modifications") + @XmlElements({ + @XmlElement(name = "modification", type = Attribute.class) + }) + private AttributeList attributes; + + /** + * + * @return + */ + @XmlTransient + @Override + public AttributeList getAttributes() { + return attributes; + } + + /** + * + * @param attributes + */ + public void setAttributes(AttributeList attributes) { + this.attributes = attributes; + } +} diff --git a/src/main/java/fr/lirmm/aren/model/agenda/ACalendar.java b/src/main/java/fr/lirmm/aren/model/agenda/ACalendar.java new file mode 100644 index 0000000..0a65a20 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/agenda/ACalendar.java @@ -0,0 +1,88 @@ +package fr.lirmm.aren.model.agenda; +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + +import fr.lirmm.aren.model.AbstractEntity; +import fr.lirmm.aren.model.framadate.FDVote; +import org.hibernate.annotations.SortNatural; + +import org.hibernate.annotations.Type; + +import javax.persistence.*; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.ZonedDateTime; +import java.util.SortedSet; +import java.util.TreeSet; +/** + * Model for Calendar with anotations for storage and serialization + * + * @author Havana Andriambolaharimihanta + */ +@Entity +@Table(name = "agenda_calendars") +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = ACalendar.class) + +public class ACalendar extends AbstractEntity implements Serializable{ + + @Size(max = 255) + @Column(name = "title") + private String title; + + @Lob + @Type(type = "org.hibernate.type.TextType") + @Column(name = "description") + private String description; + + @Size(max = 1024) + @Column(name = "url") + private String url; + + @Lob + @Type(type = "org.hibernate.type.TextType") + @Column(name = "img") + private String img; + + @Column(name = "date") + private ZonedDateTime date ; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } + + public ZonedDateTime getDate() { + return date; + } + + public void setDate(ZonedDateTime date) { + this.date = date; + } +} diff --git a/src/main/java/fr/lirmm/aren/model/framadate/FDChoice.java b/src/main/java/fr/lirmm/aren/model/framadate/FDChoice.java new file mode 100644 index 0000000..a7b1723 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/framadate/FDChoice.java @@ -0,0 +1,148 @@ +package fr.lirmm.aren.model.framadate; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + +import fr.lirmm.aren.model.AbstractEntity; +import org.hibernate.annotations.SortNatural; + +import org.hibernate.annotations.Type; + +import javax.persistence.*; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.ZonedDateTime; +import java.util.SortedSet; +import java.util.TreeSet; +/** + * Model for Choice with anotations for storage and serialization + * + * @author Havana Andriambolaharimihanta + */ +@Entity +@Table(name = "framadate_choices") +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = FDChoice.class) +public class FDChoice extends AbstractEntity implements Serializable { + /** + * + */ + private static final long serialVersionUID = -8168612675806856159L; + + @JoinColumn(name = "themeId", referencedColumnName = "id") + @ManyToOne(optional = false) + private FDTheme themeId; + + @Size(max = 255) + @Column(name = "title") + private String title; + + @Lob + @Type(type = "org.hibernate.type.TextType") + @Column(name = "description") + private String description; + + @Size(max = 1024) + @Column(name = "url") + private String url; + + @Lob + @Type(type = "org.hibernate.type.TextType") + @Column(name = "img") + private String img; + + @Column(name = "_for") + private int _for=0; + + @Column(name = "neutral") + private int neutral=0; + + @Column(name = "against") + private int against=0; + + @Column(name = "createdAt") + private ZonedDateTime createdAt=ZonedDateTime.now(); + + @OneToMany(mappedBy = "subThemeId") + @SortNatural + private SortedSet votes = new TreeSet<>(); + + public FDTheme getThemeId() { + return themeId; + } + + public void setThemeId(FDTheme themeId) { + this.themeId = themeId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getImg() { + return img; + } + + public void setImg(String img) { + this.img = img; + } + + public int getFor() { + return _for; + } + + public void setFor(int aFor) { + _for = aFor; + } + + public int getNeutral() { + return neutral; + } + + public void setNeutral(int neutral) { + this.neutral = neutral; + } + + public int getAgainst() { + return against; + } + + public void setAgainst(int against) { + this.against = against; + } + + public ZonedDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(ZonedDateTime createdAt) { + this.createdAt = createdAt; + } + + public SortedSet getVotes() { + return votes; + } + + public void setVotes(SortedSet votes) { + this.votes = votes; + } +} \ No newline at end of file diff --git a/src/main/java/fr/lirmm/aren/model/framadate/FDTheme.java b/src/main/java/fr/lirmm/aren/model/framadate/FDTheme.java new file mode 100644 index 0000000..e99c385 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/framadate/FDTheme.java @@ -0,0 +1,103 @@ +package fr.lirmm.aren.model.framadate; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + +import fr.lirmm.aren.model.AbstractEntity; +import fr.lirmm.aren.model.User; +import org.hibernate.annotations.SortNatural; + +import org.hibernate.annotations.Type; + +import javax.persistence.*; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.time.ZonedDateTime; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * Model for Theme with anotations for storage and serialization + * + * @author Havana Andriambolaharimihanta + */ +@Entity +@Table(name = "framadate_themes") +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = FDTheme.class) +public class FDTheme extends AbstractEntity implements Serializable { + /** + * + */ + private static final long serialVersionUID = 7247587622965201146L; + + @JoinColumn(name = "author", referencedColumnName = "id") + @ManyToOne + private User author; + + @Size(max = 255) + @Column(name = "title") + private String title; + + @Lob + @Type(type = "org.hibernate.type.TextType") + @Column(name = "description") + private String description; + + @Column(name = "createdAt") + private ZonedDateTime createdAt=ZonedDateTime.now(); + + @Column(name = "expiracyDate") + private ZonedDateTime expiracyDate; + + @OneToMany(mappedBy = "themeId") + @SortNatural + private SortedSet choices = new TreeSet<>(); + + public User getAuthor() { + return author; + } + + public void setAuthor(User author) { + this.author = author; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public ZonedDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(ZonedDateTime createdAt) { + this.createdAt = createdAt; + } + + public ZonedDateTime getExpiracyDate() { + return expiracyDate; + } + + public void setExpiracyDate(ZonedDateTime expiracyDate) { + this.expiracyDate = expiracyDate; + } + + public SortedSet getChoices() { + return choices; + } + + public void setChoices(SortedSet choices) { + this.choices = choices; + } +} \ No newline at end of file diff --git a/src/main/java/fr/lirmm/aren/model/framadate/FDVote.java b/src/main/java/fr/lirmm/aren/model/framadate/FDVote.java new file mode 100644 index 0000000..a91b63b --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/framadate/FDVote.java @@ -0,0 +1,73 @@ +package fr.lirmm.aren.model.framadate; +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + +import fr.lirmm.aren.model.AbstractEntity; +import fr.lirmm.aren.model.User; + +import javax.persistence.*; +import java.io.Serializable; +import java.time.ZonedDateTime; +/** + * Model for Vote with anotations for storage and serialization + * + * @author Havana Andriambolaharimihanta + */ +@Entity +@Table(name = "framadate_votes") +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = FDVote.class) +public class FDVote extends AbstractEntity implements Serializable{ + + + @ManyToOne + @JoinColumn(name = "subThemeId") + private FDChoice subThemeId; + + + @ManyToOne + @JoinColumn(name = "authorId") + private User authorId ; + + @Column(name = "opinion") + private String opinion="NEUTRAL"; + + @Column(name = "createdAt") + private ZonedDateTime createdAt=ZonedDateTime.now(); + + public FDChoice getSubThemeId() { + return subThemeId; + } + + public void setSubThemeId(FDChoice subThemeId) { + this.subThemeId = subThemeId; + } + + public User getAuthorId() { + return authorId; + } + + public void setAuthorId(User authorId) { + this.authorId = authorId; + } + + public String getOpinion() { + return opinion; + } + + public void setOpinion(String opinion) { + this.opinion = opinion; + } + + public ZonedDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(ZonedDateTime createdAt) { + this.createdAt = createdAt; + } + + @Override + public String toString(){ + return getId()+" == "+getOpinion() ; + } +} \ No newline at end of file diff --git a/src/main/java/fr/lirmm/aren/model/ws/ApiErrorDetails.java b/src/main/java/fr/lirmm/aren/model/ws/ApiErrorDetails.java new file mode 100644 index 0000000..1c0bd0f --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/ws/ApiErrorDetails.java @@ -0,0 +1,69 @@ +package fr.lirmm.aren.model.ws; + +/** + * Data transfer object that holds details about an API error. + * + * @author Florent Descroix {@literal } + */ + +public class ApiErrorDetails extends Message { + + private Integer status; + private String title; + private String path; + + /** + * + */ + public ApiErrorDetails() { + + } + + /** + * + * @return + */ + public Integer getStatus() { + return status; + } + + /** + * + * @param status + */ + public void setStatus(Integer status) { + this.status = status; + } + + /** + * + * @return + */ + public String getTitle() { + return title; + } + + /** + * + * @param title + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * + * @return + */ + public String getPath() { + return path; + } + + /** + * + * @param path + */ + public void setPath(String path) { + this.path = path; + } +} diff --git a/src/main/java/fr/lirmm/aren/model/ws/ChangePassword.java b/src/main/java/fr/lirmm/aren/model/ws/ChangePassword.java new file mode 100644 index 0000000..6057701 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/ws/ChangePassword.java @@ -0,0 +1,50 @@ +package fr.lirmm.aren.model.ws; + +/** + * + * @author florent + */ +public class ChangePassword { + + private String password; + private String newPassword; + + /** + * + */ + public ChangePassword() { + } + + /** + * + * @return + */ + public String getPassword() { + return password; + } + + /** + * + * @param password + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * + * @return + */ + public String getNewPassword() { + return newPassword; + } + + /** + * + * @param newPassword + */ + public void setNewPassword(String newPassword) { + this.newPassword = newPassword; + } + +} diff --git a/src/main/java/fr/lirmm/aren/model/ws/Message.java b/src/main/java/fr/lirmm/aren/model/ws/Message.java new file mode 100644 index 0000000..b855dea --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/ws/Message.java @@ -0,0 +1,88 @@ +package fr.lirmm.aren.model.ws; + +import java.util.HashMap; + +import com.fasterxml.jackson.annotation.JsonInclude; +import javax.persistence.Embeddable; + +/** + * Data transfer object that holds details about an API error. + * + * @author Florent Descroix {@literal } + */ +@Embeddable +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Message { + + private String message; + + private HashMap details = new HashMap(); + + /** + * + */ + public Message() { + + } + + /** + * + * @param string + */ + public Message(String message) { + this.message = message; + } + + /** + * + * @return + */ + public String paseMessage() { + String result = this.message; + details.forEach((String label, String value) -> { + result.replace("{"+label+"}", value); + }); + return result; + } + + /** + * + * @return + */ + public String getMessage() { + return message; + } + + /** + * + * @param message + */ + public void setMessage(String message) { + this.message = message; + } + + /** + * + * @return + */ + public HashMap getDetails() { + return details; + } + + /** + * + * @param details + */ + public void setDetails(HashMap details) { + this.details = details; + } + + /** + * + * @param name + * @param value + */ + public void addDetail(String name, String value) { + this.details.put(name, value); + } +} diff --git a/src/main/java/fr/lirmm/aren/model/ws/Scrap.java b/src/main/java/fr/lirmm/aren/model/ws/Scrap.java new file mode 100644 index 0000000..8a95506 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/ws/Scrap.java @@ -0,0 +1,229 @@ +package fr.lirmm.aren.model.ws; + +import com.fasterxml.jackson.annotation.JsonIdentityReference; +import fr.lirmm.aren.model.Comment; +import java.util.HashSet; +import java.util.Set; + +/** + * + * @author florent + */ +public class Scrap implements Comparable { + + /** + * + */ + public static int ALL_BEFORE = -3; + + /** + * + */ + public static int OVER_BEFORE = -2; + + /** + * + */ + public static int COVERS = -1; + + /** + * + */ + public static int EQUALS = 0; + + /** + * + */ + public static int BELONGS = 1; + + /** + * + */ + public static int OVER_AFTER = 2; + + /** + * + */ + public static int ALL_AFTER = 3; + + private String startContainer; + + private Long startOffset; + + private String endContainer; + + private Long endOffset; + + @JsonIdentityReference(alwaysAsId = true) + private Set comments = new HashSet<>(); + + /** + * + */ + public Scrap() { + } + + /** + * + * @return + */ + public String getStartContainer() { + return startContainer; + } + + /** + * + * @param startContainer + */ + public void setStartContainer(String startContainer) { + this.startContainer = startContainer; + } + + /** + * + * @return + */ + public Long getStartOffset() { + return startOffset; + } + + /** + * + * @param startOffset + */ + public void setStartOffset(Long startOffset) { + this.startOffset = startOffset; + } + + /** + * + * @return + */ + public String getEndContainer() { + return endContainer; + } + + /** + * + * @param endContainer + */ + public void setEndContainer(String endContainer) { + this.endContainer = endContainer; + } + + /** + * + * @return + */ + public Long getEndOffset() { + return endOffset; + } + + /** + * + * @param endOffset + */ + public void setEndOffset(Long endOffset) { + this.endOffset = endOffset; + } + + /** + * + * @return + */ + public Set getComments() { + return comments; + } + + /** + * + * @param comments + */ + public void setComments(Set comments) { + this.comments = comments; + } + + private int comparePosition(String[] pos1, String[] pos2) { + if (pos1.equals(pos2)) { + return 0; + } + int len = Math.max(pos1.length, pos2.length); + for (int i = 0; i < len; i++) { + if (i >= pos1.length || i < pos2.length && Integer.parseInt(pos1[i]) < Integer.parseInt(pos2[i])) { + return -1; + } else if (i >= pos2.length || i < pos1.length && Integer.parseInt(pos1[i]) > Integer.parseInt(pos2[i])) { + return 1; + } + } + return 0; + } + + /** + * + * @param other + * @return + */ + public boolean equals(Scrap other) { + return this.startContainer.equals(other.startContainer) + && this.startOffset.equals(other.startOffset) + && this.endContainer.equals(other.endContainer) + && this.endOffset.equals(other.endOffset); + } + + /** + * + * @param t + * @return + */ + @Override + public int compareTo(Object t) { + if (!(t instanceof Scrap)) { + throw new IllegalArgumentException("Compared object should be a Scrap"); + } + Scrap other = (Scrap) t; + + int StS = comparePosition( + (this.startContainer + "/" + this.startOffset).split("/"), + (other.startContainer + "/" + other.startOffset).split("/")); + int StE = comparePosition( + (this.startContainer + "/" + this.startOffset).split("/"), + (other.endContainer + "/" + other.endOffset).split("/")); + int EtS = comparePosition( + (this.endContainer + "/" + this.endOffset).split("/"), + (other.startContainer + "/" + other.startOffset).split("/")); + int EtE = comparePosition( + (this.endContainer + "/" + this.endOffset).split("/"), + (other.endContainer + "/" + other.endOffset).split("/")); + + if (StS == 0 && EtE == 0) { + return Scrap.EQUALS; + } + if (EtS <= 0) { + return Scrap.ALL_BEFORE; + } + if (StE >= 0) { + return Scrap.ALL_AFTER; + } + if (StS <= 0 && EtE >= 0) { + return Scrap.COVERS; + } + if (StS >= 0 && EtE <= 0) { + return Scrap.BELONGS; + } + if (StS <= 0) { + return Scrap.OVER_BEFORE; + } + if (StS >= 0) { + return Scrap.OVER_AFTER; + } + throw new IllegalArgumentException("Imposible possitioning"); + } + + /** + * + * @return + */ + public String toString() { + return this.startContainer + "/" + this.startOffset + " > " + this.endContainer + "/" + this.endOffset; + } +} diff --git a/src/main/java/fr/lirmm/aren/model/ws/UserCredentials.java b/src/main/java/fr/lirmm/aren/model/ws/UserCredentials.java new file mode 100644 index 0000000..6cf4a9c --- /dev/null +++ b/src/main/java/fr/lirmm/aren/model/ws/UserCredentials.java @@ -0,0 +1,68 @@ +package fr.lirmm.aren.model.ws; + +/** + * API model for the user credentials. + * + * @author Florent Descroix {@literal } + */ +public class UserCredentials { + + private String username; + private String password; + private boolean rememberMe; + + /** + * + */ + public UserCredentials() { + + } + + /** + * + * @return + */ + public String getUsername() { + return username; + } + + /** + * + * @param username + */ + public void setUsername(String username) { + this.username = username; + } + + /** + * + * @return + */ + public String getPassword() { + return password; + } + + /** + * + * @param password + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * + * @return + */ + public boolean isRememberMe() { + return rememberMe; + } + + /** + * + * @param rememberMe + */ + public void setRememberMe(boolean rememberMe) { + this.rememberMe = rememberMe; + } +} diff --git a/src/main/java/fr/lirmm/aren/producer/Configurable.java b/src/main/java/fr/lirmm/aren/producer/Configurable.java new file mode 100644 index 0000000..a471f50 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/producer/Configurable.java @@ -0,0 +1,31 @@ +package fr.lirmm.aren.producer; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.enterprise.util.Nonbinding; +import javax.inject.Qualifier; + +/** + * CDI qualifier for injecting configurable values. + * + * @author Florent Descroix {@literal } + */ +@Qualifier +@Retention(RUNTIME) +@Target({TYPE, METHOD, FIELD, PARAMETER}) +public @interface Configurable { + + /** + * + * @return + */ + @Nonbinding + String value() default ""; +} diff --git a/src/main/java/fr/lirmm/aren/producer/ConfigurationProducer.java b/src/main/java/fr/lirmm/aren/producer/ConfigurationProducer.java new file mode 100644 index 0000000..7b01e19 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/producer/ConfigurationProducer.java @@ -0,0 +1,93 @@ +package fr.lirmm.aren.producer; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import javax.annotation.PostConstruct; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.InjectionPoint; + +/** + * Read the application.properties file from the classpath and + * produce values that can be injected with @{@link Configurable}. + *

+ * It's a simple and lightweight alternative to the Apache DeltaSpike + * Configuration Mechanism. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class ConfigurationProducer { + + private Properties properties; + + /** + * + */ + @PostConstruct + public void init() { + + properties = new Properties(); + InputStream stream = ConfigurationProducer.class.getResourceAsStream("/application.properties"); + + if (stream == null) { + throw new RuntimeException("Cannot find application.properties configuration file."); + } + + try { + this.properties.load(stream); + } catch (final IOException e) { + throw new RuntimeException("Configuration file cannot be loaded."); + } + } + + /** + * + * @param ip + * @return + */ + @Produces + @Configurable + public String produceString(InjectionPoint ip) { + return properties.getProperty(getKey(ip)); + } + + /** + * + * @param ip + * @return + */ + @Produces + @Configurable + public Integer produceInteger(InjectionPoint ip) { + return Integer.valueOf(properties.getProperty(getKey(ip))); + } + + /** + * + * @param ip + * @return + */ + @Produces + @Configurable + public Long produceLong(InjectionPoint ip) { + return Long.valueOf(properties.getProperty(getKey(ip))); + } + + /** + * + * @param ip + * @return + */ + @Produces + @Configurable + public Boolean produceBoolean(InjectionPoint ip) { + return Boolean.valueOf(this.properties.getProperty(getKey(ip))); + } + + private String getKey(InjectionPoint ip) { + return ip.getAnnotated().getAnnotation(Configurable.class).value(); + } +} diff --git a/src/main/java/fr/lirmm/aren/producer/EntityManagerProducer.java b/src/main/java/fr/lirmm/aren/producer/EntityManagerProducer.java new file mode 100644 index 0000000..a3c8e52 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/producer/EntityManagerProducer.java @@ -0,0 +1,88 @@ +package fr.lirmm.aren.producer; + +import static fr.lirmm.aren.producer.Scope.Type.APPLICATION; +import static fr.lirmm.aren.producer.Scope.Type.REQUEST; +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Initialized; +import javax.enterprise.context.RequestScoped; +import javax.enterprise.event.Observes; +import javax.enterprise.inject.Default; +import javax.enterprise.inject.Disposes; +import javax.enterprise.inject.Produces; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +/** + * CDI producer for the JPA {@link EntityManager}. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class EntityManagerProducer { + + private EntityManagerFactory factory; + + /** + * + */ + @PostConstruct + public void init() { + factory = Persistence.createEntityManagerFactory("default"); + } + + /** + * + * @return + */ + @Produces + @Default + @Scope(REQUEST) + @RequestScoped + public EntityManager createRequestEntityManager() { + return factory.createEntityManager(); + } + + /** + * + * @return + */ + @Produces + @Scope(APPLICATION) + @ApplicationScoped + public EntityManager createApplicationEntityManager() { + return factory.createEntityManager(); + } + + /** + * + * @param entityManager + */ + public void closeEntityManager(@Disposes EntityManager entityManager) { + if (entityManager.isOpen()) { + entityManager.close(); + } + } + + /** + * + */ + @PreDestroy + public void destroy() { + if (factory.isOpen()) { + factory.close(); + } + } + + // Hack to force the EntityManager provider (Hibernate in this case) to create + // tables and populate the database when the application starts up + /** + * + * @param init + */ + public void init(@Observes @Initialized(ApplicationScoped.class) Object init) { + factory.createEntityManager().close(); + } +} diff --git a/src/main/java/fr/lirmm/aren/producer/Scope.java b/src/main/java/fr/lirmm/aren/producer/Scope.java new file mode 100644 index 0000000..338306a --- /dev/null +++ b/src/main/java/fr/lirmm/aren/producer/Scope.java @@ -0,0 +1,24 @@ +package fr.lirmm.aren.producer; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; +import javax.inject.Qualifier; + +/** + * + * @author florent + */ +@Qualifier +@Retention(RUNTIME) +@Target({FIELD, METHOD}) +public @interface Scope { + + Type value(); + + enum Type { + REQUEST, SESSION, APPLICATION + }; +} diff --git a/src/main/java/fr/lirmm/aren/security/AuthenticatedUserDetails.java b/src/main/java/fr/lirmm/aren/security/AuthenticatedUserDetails.java new file mode 100644 index 0000000..7331bc0 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/security/AuthenticatedUserDetails.java @@ -0,0 +1,49 @@ +package fr.lirmm.aren.security; + +import java.security.Principal; + +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.model.User.Authority; + +/** + * {@link Principal} implementation with a set of {@link Authority}. + * + * @author Florent Descroix {@literal } + */ +public final class AuthenticatedUserDetails implements Principal { + + private final User user; + + /** + * + * @param user + */ + public AuthenticatedUserDetails(User user) { + this.user = user; + } + + /** + * + * @return the user's authority + */ + public Authority getAuthority() { + return user.getAuthority(); + } + + /** + * + * @return the username + */ + @Override + public String getName() { + return user.getUsername(); + } + + /** + * + * @return the user object + */ + public User getUser() { + return user; + } +} diff --git a/src/main/java/fr/lirmm/aren/security/PasswordEncoder.java b/src/main/java/fr/lirmm/aren/security/PasswordEncoder.java new file mode 100644 index 0000000..4e94ac9 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/security/PasswordEncoder.java @@ -0,0 +1,39 @@ +package fr.lirmm.aren.security; + +import javax.enterprise.context.ApplicationScoped; + +import org.mindrot.jbcrypt.BCrypt; + +/** + * bcrypt password encoder. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class PasswordEncoder { + + /** + * Hashes a password using BCrypt. + * + * @param plainTextPassword + * @return the has of the given string + */ + public String hashPassword(String plainTextPassword) { + return BCrypt.hashpw(plainTextPassword, BCrypt.gensalt()); + } + + /** + * Checks a password against a stored hash using BCrypt. + * + * @param plainTextPassword + * @param hashPassword + * @return true if the hash of the first parameter equals the the second + * parameter + */ + public boolean checkPassword(String plainTextPassword, String hashPassword) { + if (null == hashPassword || !hashPassword.startsWith("$2a$")) { + throw new RuntimeException("Hashed password is invalid"); + } + return BCrypt.checkpw(plainTextPassword, hashPassword); + } +} diff --git a/src/main/java/fr/lirmm/aren/security/TokenBasedSecurityContext.java b/src/main/java/fr/lirmm/aren/security/TokenBasedSecurityContext.java new file mode 100644 index 0000000..fe240ed --- /dev/null +++ b/src/main/java/fr/lirmm/aren/security/TokenBasedSecurityContext.java @@ -0,0 +1,77 @@ +package fr.lirmm.aren.security; + +import java.security.Principal; + +import javax.ws.rs.core.SecurityContext; + +import fr.lirmm.aren.model.User.Authority; +import fr.lirmm.aren.security.token.AuthenticationTokenDetails; + +/** + * {@link SecurityContext} implementation for token-based authentication. + * + * @author Florent Descroix {@literal } + */ +public class TokenBasedSecurityContext implements SecurityContext { + + private final AuthenticatedUserDetails authenticatedUserDetails; + private final AuthenticationTokenDetails authenticationTokenDetails; + private final boolean secure; + + /** + * + * @param authenticatedUserDetails + * @param authenticationTokenDetails + * @param secure + */ + public TokenBasedSecurityContext(AuthenticatedUserDetails authenticatedUserDetails, AuthenticationTokenDetails authenticationTokenDetails, boolean secure) { + this.authenticatedUserDetails = authenticatedUserDetails; + this.authenticationTokenDetails = authenticationTokenDetails; + this.secure = secure; + } + + /** + * + * @return + */ + @Override + public Principal getUserPrincipal() { + return authenticatedUserDetails; + } + + /** + * + * @param s + * @return + */ + @Override + public boolean isUserInRole(String s) { + return authenticatedUserDetails.getUser().is(Authority.valueOf(s)); + } + + /** + * + * @return + */ + @Override + public boolean isSecure() { + return secure; + } + + /** + * + * @return + */ + @Override + public String getAuthenticationScheme() { + return "Bearer"; + } + + /** + * + * @return + */ + public AuthenticationTokenDetails getAuthenticationTokenDetails() { + return authenticationTokenDetails; + } +} diff --git a/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenDetails.java b/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenDetails.java new file mode 100644 index 0000000..87c5103 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenDetails.java @@ -0,0 +1,188 @@ +package fr.lirmm.aren.security.token; + +import java.time.ZonedDateTime; + +import fr.lirmm.aren.model.User.Authority; + +/** + * Model that holds details about an authentication token. + * + * @author Florent Descroix {@literal } + */ +public final class AuthenticationTokenDetails { + + private final String id; + private final String username; + private final Authority authority; + private final ZonedDateTime issuedDate; + private final ZonedDateTime expirationDate; + private final int refreshCount; + private final int refreshLimit; + + private AuthenticationTokenDetails(String id, String username, Authority authority, ZonedDateTime issuedDate, ZonedDateTime expirationDate, int refreshCount, int refreshLimit) { + this.id = id; + this.username = username; + this.authority = authority; + this.issuedDate = issuedDate; + this.expirationDate = expirationDate; + this.refreshCount = refreshCount; + this.refreshLimit = refreshLimit; + } + + /** + * + * @return + */ + public String getId() { + return id; + } + + /** + * + * @return + */ + public String getUsername() { + return username; + } + + /** + * + * @return + */ + public Authority getAuthority() { + return authority; + } + + /** + * + * @return + */ + public ZonedDateTime getIssuedDate() { + return issuedDate; + } + + /** + * + * @return + */ + public ZonedDateTime getExpirationDate() { + return expirationDate; + } + + /** + * + * @return + */ + public int getRefreshCount() { + return refreshCount; + } + + /** + * + * @return + */ + public int getRefreshLimit() { + return refreshLimit; + } + + /** + * Check if the authentication token is eligible for refreshment. + * + * @return + */ + public boolean isEligibleForRefreshment() { + return refreshCount < refreshLimit; + } + + /** + * Builder for the {@link AuthenticationTokenDetails}. + */ + public static class Builder { + + private String id; + private String username; + private Authority authority; + private ZonedDateTime issuedDate; + private ZonedDateTime expirationDate; + private int refreshCount; + private int refreshLimit; + + /** + * + * @param id + * @return + */ + public Builder withId(String id) { + this.id = id; + return this; + } + + /** + * + * @param username + * @return + */ + public Builder withUsername(String username) { + this.username = username; + return this; + } + + /** + * + * @param authority + * @return + */ + public Builder withAuthority(Authority authority) { + this.authority = authority; + return this; + } + + /** + * + * @param issuedDate + * @return + */ + public Builder withIssuedDate(ZonedDateTime issuedDate) { + this.issuedDate = issuedDate; + return this; + } + + /** + * + * @param expirationDate + * @return + */ + public Builder withExpirationDate(ZonedDateTime expirationDate) { + this.expirationDate = expirationDate; + return this; + } + + /** + * + * @param refreshCount + * @return + */ + public Builder withRefreshCount(int refreshCount) { + this.refreshCount = refreshCount; + return this; + } + + /** + * + * @param refreshLimit + * @return + */ + public Builder withRefreshLimit(int refreshLimit) { + this.refreshLimit = refreshLimit; + return this; + } + + /** + * + * @return + */ + public AuthenticationTokenDetails build() { + return new AuthenticationTokenDetails(id, username, authority, issuedDate, expirationDate, refreshCount, refreshLimit); + } + } +} diff --git a/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenIssuer.java b/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenIssuer.java new file mode 100644 index 0000000..c641f83 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenIssuer.java @@ -0,0 +1,43 @@ +package fr.lirmm.aren.security.token; + +import java.util.Date; + +import javax.enterprise.context.Dependent; +import javax.inject.Inject; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +/** + * Component which provides operations for issuing JWT tokens. + * + * @author Florent Descroix {@literal } + */ +@Dependent +class AuthenticationTokenIssuer { + + @Inject + private AuthenticationTokenSettings settings; + + /** + * Issue a JWT token + * + * @param authenticationTokenDetails + * @return + */ + public String issueToken(AuthenticationTokenDetails authenticationTokenDetails) { + + return Jwts.builder() + .setId(authenticationTokenDetails.getId()) + .setIssuer(settings.getIssuer()) + .setAudience(settings.getAudience()) + .setSubject(authenticationTokenDetails.getUsername()) + .setIssuedAt(Date.from(authenticationTokenDetails.getIssuedDate().toInstant())) + .setExpiration(Date.from(authenticationTokenDetails.getExpirationDate().toInstant())) + .claim(settings.getAuthorityClaimName(), authenticationTokenDetails.getAuthority()) + .claim(settings.getRefreshCountClaimName(), authenticationTokenDetails.getRefreshCount()) + .claim(settings.getRefreshLimitClaimName(), authenticationTokenDetails.getRefreshLimit()) + .signWith(SignatureAlgorithm.HS256, settings.getSecret()) + .compact(); + } +} diff --git a/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenParser.java b/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenParser.java new file mode 100644 index 0000000..1f5b559 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenParser.java @@ -0,0 +1,137 @@ +package fr.lirmm.aren.security.token; + +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import javax.enterprise.context.Dependent; +import javax.inject.Inject; +import javax.validation.constraints.NotNull; + +import fr.lirmm.aren.exception.InvalidAuthenticationTokenException; +import fr.lirmm.aren.model.User.Authority; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.InvalidClaimException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.SignatureException; +import io.jsonwebtoken.UnsupportedJwtException; + +/** + * Component which provides operations for parsing JWT tokens. + * + * @author Florent Descroix {@literal } + */ +@Dependent +public class AuthenticationTokenParser { + + @Inject + private AuthenticationTokenSettings settings; + + /** + * Parse a JWT token. + * + * @param token + * @return + */ + public AuthenticationTokenDetails parseToken(String token) { + + try { + + Claims claims = Jwts.parser() + .setSigningKey(settings.getSecret()) + .requireAudience(settings.getAudience()) + .setAllowedClockSkewSeconds(settings.getClockSkew()) + .parseClaimsJws(token) + .getBody(); + + return new AuthenticationTokenDetails.Builder() + .withId(extractTokenIdFromClaims(claims)) + .withUsername(extractUsernameFromClaims(claims)) + .withAuthority(extractAuthorityFromClaims(claims)) + .withIssuedDate(extractIssuedDateFromClaims(claims)) + .withExpirationDate(extractExpirationDateFromClaims(claims)) + .withRefreshCount(extractRefreshCountFromClaims(claims)) + .withRefreshLimit(extractRefreshLimitFromClaims(claims)) + .build(); + + } catch (UnsupportedJwtException | MalformedJwtException | IllegalArgumentException | SignatureException e) { + throw InvalidAuthenticationTokenException.INVALID_TOKEN(); + } catch (ExpiredJwtException e) { + throw InvalidAuthenticationTokenException.INVALID_TOKEN(); + } catch (InvalidClaimException e) { + throw InvalidAuthenticationTokenException.INVALID_CLAIM(e.getClaimName()); + } + } + + /** + * Extract the token identifier from the token claims. + * + * @param claims + * @return Identifier of the JWT token + */ + private String extractTokenIdFromClaims(@NotNull Claims claims) { + return (String) claims.get(Claims.ID); + } + + /** + * Extract the username from the token claims. + * + * @param claims + * @return Username from the JWT token + */ + private String extractUsernameFromClaims(@NotNull Claims claims) { + return claims.getSubject(); + } + + /** + * Extract the user authorities from the token claims. + * + * @param claims + * @return User authorities from the JWT token + */ + private Authority extractAuthorityFromClaims(@NotNull Claims claims) { + String rolesAsString = (String) claims.getOrDefault(settings.getAuthorityClaimName(), ""); + return Authority.valueOf(rolesAsString); + } + + /** + * Extract the issued date from the token claims. + * + * @param claims + * @return Issued date of the JWT token + */ + private ZonedDateTime extractIssuedDateFromClaims(@NotNull Claims claims) { + return ZonedDateTime.ofInstant(claims.getIssuedAt().toInstant(), ZoneId.systemDefault()); + } + + /** + * Extract the expiration date from the token claims. + * + * @param claims + * @return Expiration date of the JWT token + */ + private ZonedDateTime extractExpirationDateFromClaims(@NotNull Claims claims) { + return ZonedDateTime.ofInstant(claims.getExpiration().toInstant(), ZoneId.systemDefault()); + } + + /** + * Extract the refresh count from the token claims. + * + * @param claims + * @return Refresh count from the JWT token + */ + private int extractRefreshCountFromClaims(@NotNull Claims claims) { + return (int) claims.get(settings.getRefreshCountClaimName()); + } + + /** + * Extract the refresh limit from the token claims. + * + * @param claims + * @return Refresh limit from the JWT token + */ + private int extractRefreshLimitFromClaims(@NotNull Claims claims) { + return (int) claims.get(settings.getRefreshLimitClaimName()); + } +} diff --git a/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenService.java b/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenService.java new file mode 100644 index 0000000..311df9d --- /dev/null +++ b/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenService.java @@ -0,0 +1,87 @@ +package fr.lirmm.aren.security.token; + +import java.time.ZonedDateTime; +import java.util.UUID; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; + +import fr.lirmm.aren.producer.Configurable; +import fr.lirmm.aren.model.User; +import java.time.temporal.ChronoUnit; + +/** + * Service which provides operations for authentication tokens. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class AuthenticationTokenService { + + /** + * How long the token is valid for (in seconds). + */ + @Inject + @Configurable("authentication.jwt.validFor") + private Long validFor; + + @Inject + private AuthenticationTokenIssuer tokenIssuer; + + @Inject + private AuthenticationTokenParser tokenParser; + + /** + * Issue a token for a user with the given authorities. + * + * @param user + * @param validFor + * @return + */ + public String issueToken(User user, Long validFor) { + + String id = generateTokenIdentifier(); + ZonedDateTime issuedDate = ZonedDateTime.now().truncatedTo(ChronoUnit.SECONDS); + + AuthenticationTokenDetails authenticationTokenDetails = new AuthenticationTokenDetails.Builder() + .withId(id) + .withUsername(user.getUsername()) + .withAuthority(user.getAuthority()) + .withIssuedDate(issuedDate) + .withExpirationDate(issuedDate.plusSeconds(validFor)) + .withRefreshCount(0) + .build(); + + return tokenIssuer.issueToken(authenticationTokenDetails); + } + + /** + * Issue a token for a user with the given authorities. + * + * @param user + * @return + */ + public String issueToken(User user) { + + return issueToken(user, validFor); + } + + /** + * Parse and validate the token. + * + * @param token + * @return + */ + public AuthenticationTokenDetails parseToken(String token) { + return tokenParser.parseToken(token); + } + + /** + * Generate a token identifier. + * + * @return + */ + private String generateTokenIdentifier() { + return UUID.randomUUID().toString(); + } +} diff --git a/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenSettings.java b/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenSettings.java new file mode 100644 index 0000000..4d163ec --- /dev/null +++ b/src/main/java/fr/lirmm/aren/security/token/AuthenticationTokenSettings.java @@ -0,0 +1,95 @@ +package fr.lirmm.aren.security.token; + +import javax.enterprise.context.Dependent; +import javax.inject.Inject; + +import fr.lirmm.aren.producer.Configurable; + +/** + * Settings for signing and verifying JWT tokens. + * + * @author Florent Descroix {@literal } + */ +@Dependent +class AuthenticationTokenSettings { + + /** + * Secret for signing and verifying the token signature. + */ + @Inject + @Configurable("authentication.jwt.secret") + private String secret; + + /** + * Allowed clock skew for verifying the token signature (in seconds). + */ + @Inject + @Configurable("authentication.jwt.clockSkew") + private Long clockSkew; + + /** + * Identifies the recipients that the JWT token is intended for. + */ + @Inject + @Configurable("authentication.jwt.audience") + private String audience; + + /** + * Identifies the JWT token issuer. + */ + @Inject + @Configurable("authentication.jwt.issuer") + private String issuer; + /** + * JWT claim for the authorities. + */ + @Inject + @Configurable("authentication.jwt.claimNames.authorities") + private String authorityClaimName; + /** + * JWT claim for the token refreshment count. + */ + @Inject + @Configurable("authentication.jwt.claimNames.refreshCount") + private String refreshCountClaimName; + /** + * JWT claim for the maximum times that a token can be refreshed. + */ + @Inject + @Configurable("authentication.jwt.claimNames.refreshLimit") + private String refreshLimitClaimName; + + AuthenticationTokenSettings() { + this.authorityClaimName = "authorities"; + this.refreshCountClaimName = "refreshCount"; + this.refreshLimitClaimName = "refreshLimit"; + } + + public String getSecret() { + return secret; + } + + public Long getClockSkew() { + return clockSkew; + } + + public String getAudience() { + return audience; + } + + public String getIssuer() { + return issuer; + } + + public String getAuthorityClaimName() { + return authorityClaimName; + } + + public String getRefreshCountClaimName() { + return refreshCountClaimName; + } + + public String getRefreshLimitClaimName() { + return refreshLimitClaimName; + } +} diff --git a/src/main/java/fr/lirmm/aren/service/AAFImportService.java b/src/main/java/fr/lirmm/aren/service/AAFImportService.java new file mode 100644 index 0000000..3599f2f --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/AAFImportService.java @@ -0,0 +1,411 @@ +package fr.lirmm.aren.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import fr.lirmm.aren.model.AbstractEntEntity; +import fr.lirmm.aren.model.Institution; +import fr.lirmm.aren.model.Team; +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.model.aaf.AbstractRequest; +import fr.lirmm.aren.model.aaf.AddRequest; +import fr.lirmm.aren.model.aaf.AttributeList; +import fr.lirmm.aren.model.aaf.DeleteRequest; +import fr.lirmm.aren.model.aaf.FicAlimMENESR; +import fr.lirmm.aren.model.aaf.ModifyRequest; +import fr.lirmm.aren.security.PasswordEncoder; +import java.io.File; +import java.util.HashSet; +import java.util.Set; + +/** + * Service that provides operations for AAF xml import + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class AAFImportService { + + @Inject + private PasswordEncoder passwordEncoder; + + @Inject + private EntityManager em; + + /** + * Object storing the parsed AAF xml file + */ + private FicAlimMENESR alimAAF; + + /** + * HashMap that links local ids to ent aaf ids of already stored entities + */ + private final Map, Map> maps = new HashMap<>(); + + /** + * HashMap the stores all the entities before the actual database processing + * Useful to sort the in order of priority to avoid conflicts + */ + private final Map, Map>> toProcess = new HashMap, Map>>(); + + /** + * Variables to evaluate the progression of the importation + */ + private float amoutToProcess; + private float amoutProceed; + + /** + * Function triggered to notify the progression + */ + private Consumer dispatcher; + + /** + * Enum of possible requests + */ + private enum Method { + CREATE, UPDATE, DELETE; + } + + /** + * ArrayList that store the log of the import + */ + private volatile List log = new ArrayList<>(); + + /** + * + * @return + */ + protected EntityManager getEntityManager() { + return em; + } + + /** + * + * @return + */ + public List proceedImportation(File file) { + return proceedImportation(file, true, true); + } + + /** + * + * @param insertOnUpdate if true, insert elements that should be updated but + * don't exist in local storage + * @param updateOnInsert if true, update elements that should be inserted + * but already exist in local storage + * @return + */ + public List proceedImportation(File file, boolean insertOnUpdate, boolean updateOnInsert) { + // Removes the check of external DTD on XML files + System.setProperty("javax.xml.accessExternalDTD", "all"); + + // Parse XML + try { + JAXBContext jaxbContext; + jaxbContext = JAXBContext.newInstance(FicAlimMENESR.class); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + alimAAF = (FicAlimMENESR) unmarshaller.unmarshal(file); + } catch (JAXBException ex) { + Logger.getLogger(AAFImportService.class.getName()).log(Level.SEVERE, null, ex); + } + + // Varialbe sinitialization + log.clear(); + + toProcess.clear(); + + for (Class klass : new Class[]{Institution.class, Team.class, User.class}) { + toProcess.put(klass, new HashMap>()); + for (Method method : Method.values()) { + toProcess.get(klass).put(method, new ArrayList<>()); + } + } + amoutToProcess = 0; + amoutProceed = 0; + + // Count amout to proceed + for (AbstractRequest request : alimAAF.getRequest()) { + AttributeList opAttr = request.getOperationalAttributes(); + if (opAttr.isInstitution()) { + AttributeList attrs = request.getAttributes(); + this.amoutToProcess += attrs.getClasses().size(); + this.amoutToProcess += attrs.getGroups().size(); + } + this.amoutToProcess++; + } + this.amoutToProcess = this.amoutToProcess * 2; + + loadIdsMaps(); + + // This populate the toProcess Map that will execute the real import + Set newUsersId = new HashSet(); + for (AbstractRequest request : alimAAF.getRequest()) { + AttributeList attrs = request.getAttributes(); + + if (!attrs.isEmpty()) { + String entId = request.getId(); + AttributeList opAttr = request.getOperationalAttributes(); + attrs.addAll(opAttr); + Method method = null; + if (request.getClass() == AddRequest.class) { + method = Method.CREATE; + } else if (request.getClass() == ModifyRequest.class) { + method = Method.UPDATE; + } else if (request.getClass() == DeleteRequest.class) { + method = Method.DELETE; + } + + if (opAttr.isInstitution()) { + Institution institution = parseInstitution(attrs, entId); + toProcess.get(Institution.class).get(method).add(institution); + for (Team team : ((Institution) institution).getTeams()) { + toProcess.get(Team.class).get(method).add(team); + this.dispatchProgression(); + } + } else if (opAttr.isUser()) { + User user = parseUser(attrs, entId); + toProcess.get(User.class).get(method).add(user); + } + this.dispatchProgression(); + } + } + + // This executes the real import + // The order is important to avoid foreign key error + getEntityManager().getTransaction().begin(); + for (Class klass : new Class[]{Institution.class, Team.class, User.class}) { + // The order is important too + for (Method method : new Method[]{Method.CREATE, Method.UPDATE, Method.DELETE}) { + for (AbstractEntEntity entity : toProcess.get(klass).get(method)) { + proceed(klass, method, entity, insertOnUpdate, updateOnInsert); + if (klass == User.class) { + newUsersId.add(entity.getId()); + } + this.dispatchProgression(); + } + } + } + if (!newUsersId.isEmpty()) { + getEntityManager().createQuery("UPDATE Team t SET " + + "t.usersCount = (SELECT COUNT(u) FROM t.users u) " + + "WHERE t IN (SELECT t1 FROM User u LEFT JOIN u.teams t1 WHERE u.id IN :ids)") + .setParameter("ids", newUsersId) + .executeUpdate(); + } + getEntityManager().getTransaction().commit(); + + return log; + } + + /** + * + * @param dispatcher + */ + public void setDispatcher(Consumer dispatcher) { + + this.dispatcher = dispatcher; + } + + /** + * + * @param message + * @param isTeam if true it increments the total amout to process, because + * team ar + */ + private void dispatchProgression() { + + this.amoutProceed++; + if (this.dispatcher != null) { + float progression = this.amoutProceed / this.amoutToProcess; + this.dispatcher.accept(progression); + } + } + + /** + * Populate the maps between ids and ent ids + */ + private void loadIdsMaps() { + + maps.put(User.class, getEntIdToIdMap(User.class)); + maps.put(Team.class, getEntIdToIdMap(Team.class)); + maps.put(Institution.class, getEntIdToIdMap(Institution.class)); + } + + /** + * Retreives all ids and ent ids of a certain type in one call + * + * @param klass + * @return + */ + private Map getEntIdToIdMap(Class klass) { + Map map = new HashMap(); + List result = getEntityManager().createQuery( + "SELECT t.entId, t.id " + + "FROM " + klass.getSimpleName() + " t " + + "WHERE t.entId IS NOT NULL", Object[].class) + .getResultList(); + if (result == null) { + return null; + } + + result.forEach(obj -> { + map.put((String) obj[0], (Long) obj[1]); + }); + + return map; + } + + /** + * + * This is the main logic It handles what needs to be done for Create, + * Update and Delete + * + * @param method + * @param entity + * @param entId + */ + private void proceed(Class entityClass, Method method, AbstractEntEntity entity, boolean insertOnUpdate, boolean updateOnInsert) { + + boolean alreadyExists = maps.get(entityClass).containsKey(entity.getEntId()); + + switch (method) { + case CREATE: + if (alreadyExists) { + if (updateOnInsert) { + // If the entity already exists and updateOnInsert is true, we update it + // And add a warning + log.add("WARNING : " + method.name() + " : " + entityClass.getSimpleName() + " : " + entity.getEntId() + " updated instead of created"); + proceed(entityClass, Method.UPDATE, entity, false, false); + } else { + // If the entity already exists it adds an error + log.add("ERROR : " + method.name() + " : " + entityClass.getSimpleName() + " : " + entity.getEntId() + " already exists"); + } + } else { + getEntityManager().persist(entity); + log.add("SUCCESS : " + method.name() + " : " + entityClass.getSimpleName() + " : " + entity.getEntId()); + } + break; + + case UPDATE: + if (!alreadyExists) { + if (insertOnUpdate) { + // If the entity is not found and insertOnUpdate is true, we insert it + // And add a warning + log.add("WARNING : " + method.name() + " : " + entityClass.getSimpleName() + " : " + entity.getEntId() + " created instead of updated."); + proceed(entityClass, Method.CREATE, entity, false, false); + } else { + // If the entity is not found it adds an error + log.add("ERROR : " + method.name() + " : " + entityClass.getSimpleName() + " : " + entity.getEntId() + " not found."); + } + } else { + getEntityManager().merge(entity); + log.add("SUCCESS : " + method.name() + " : " + entityClass.getSimpleName() + " : " + entity.getEntId()); + } + break; + + case DELETE: + if (!alreadyExists) { + log.add("ERROR : " + method.name() + " : " + entityClass.getSimpleName() + " : " + entity.getEntId() + " not found."); + } else { + getEntityManager().remove(entity); + log.add("SUCCESS : " + method.name() + " : " + entityClass.getSimpleName() + " : " + entity.getEntId()); + } + break; + + default: + break; + } + } + + private User parseUser(AttributeList attrs, String entId) { + + Long id = maps.get(User.class).get(entId); + User user = new User(); + if (id != null) { + user = getEntityManager().getReference(User.class, id); + } + user.setEntId(entId); + user.setLastName(attrs.getLastName()); + user.setFirstName(attrs.getFirstName()); + user.setEmail(attrs.getEmail()); + user.setAuthority(attrs.getAuthority()); + // TODO : Get the real username + user.setUsername(entId); + String hashedPassword = passwordEncoder.hashPassword("temporary"); + user.setPassword(hashedPassword); + + Long instId = maps.get(Institution.class).get(attrs.getInstitutionId()); + Institution inst = getEntityManager().getReference(Institution.class, instId); + user.setInstitution(inst); + + List classOrGroup = new ArrayList<>(); + classOrGroup.addAll(attrs.getClasses()); + classOrGroup.addAll(attrs.getGroups()); + + for (String teamEntId : classOrGroup) { + Long teamId = maps.get(Team.class).get(teamEntId); + if (teamId != null) { + Team team = getEntityManager().getReference(Team.class, teamId); + user.addTeam(team); + } + } + + return user; + } + + private Institution parseInstitution(AttributeList attrs, String entId) { + + Long id = maps.get(Institution.class).get(entId); + Institution inst = new Institution(); + if (id != null) { + inst = getEntityManager().getReference(Institution.class, id); + } + inst.setEntId(entId); + + inst.setAcademy(attrs.getAcademy()); + inst.setType(attrs.getType()); + inst.setName(attrs.getName().split("-")[1]); + + List classOrGroup = new ArrayList<>(); + classOrGroup.addAll(attrs.getClasses()); + classOrGroup.addAll(attrs.getGroups()); + + for (String teamDesc : classOrGroup) { + if (!teamDesc.isEmpty()) { + Team team = parseTeam(teamDesc, inst); + inst.addTeam(team); + } + } + + return inst; + } + + private Team parseTeam(String value, Institution inst) { + + String[] explodeName = value.split("\\$"); + String entId = inst.getEntId() + "$" + explodeName[0]; + String name = explodeName.length > 2 && explodeName[1].length() > 1 ? explodeName[1] : explodeName[0]; + + Long id = maps.get(Team.class).get(entId); + Team team = new Team(); + if (id != null) { + team = getEntityManager().getReference(Team.class, id); + } + team.setEntId(entId); + team.setName(name); + + return team; + } +} diff --git a/src/main/java/fr/lirmm/aren/service/AbstractService.java b/src/main/java/fr/lirmm/aren/service/AbstractService.java new file mode 100644 index 0000000..c52350d --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/AbstractService.java @@ -0,0 +1,231 @@ +package fr.lirmm.aren.service; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceException; +import javax.persistence.criteria.CriteriaQuery; + +import org.hibernate.PropertyValueException; +import org.hibernate.exception.ConstraintViolationException; + +import fr.lirmm.aren.exception.InsertEntityException; +import fr.lirmm.aren.model.AbstractEntity; +import fr.lirmm.aren.producer.Scope; +import static fr.lirmm.aren.producer.Scope.Type.APPLICATION; +import static fr.lirmm.aren.producer.Scope.Type.REQUEST; +import java.util.Set; +import java.util.HashSet; +import javax.inject.Inject; + +/** + * Service that provides abstract operations for the models + * + * @author Florent Descroix {@literal } + * @param + */ +public abstract class AbstractService { + + @Inject + @Scope(REQUEST) + private EntityManager emr; + + @Inject + @Scope(APPLICATION) + private EntityManager ema; + + private final Class entityClass; + + /** + * + * @param type + */ + public AbstractService(Class entityClass) { + this.entityClass = entityClass; + } + + /** + * + * @return + */ + protected EntityManager getEntityManager() { + try { + this.emr.getTransaction(); + return emr; + } catch (Exception e) { + return this.ema; + } + } + + // Wrapper so if there is multiple nested requests + // they are all commited once + /** + * + */ + protected void transactionBegin() { + if (!getEntityManager().getTransaction().isActive()) { + getEntityManager().setProperty("activeTransactions", 0); + getEntityManager().getTransaction().begin(); + } + getEntityManager().setProperty("activeTransactions", + ((int) getEntityManager().getProperties().get("activeTransactions")) + 1); + } + + /** + * + */ + protected void commit() { + if ((int) getEntityManager() + .getProperties() + .get("activeTransactions") == 1) { + getEntityManager().getTransaction().commit(); + } + getEntityManager().setProperty("activeTransactions", + ((int) getEntityManager().getProperties().get("activeTransactions")) - 1); + } + + /** + * + * @return + */ + public Class getEntityClass() { + return entityClass; + } + + /** + * + * @param entities + */ + public void create(List entities) { + this.transactionBegin(); + entities.forEach(entity -> { + this.create(entity); + }); + this.commit(); + } + + /** + * + * @param entity + */ + protected void afterCreate(T entity) { + } + + /** + * + * @param entity + */ + public void create(T entity) { + // If ever the entity is attached, it needs to be detached + getEntityManager().detach(entity); + // If ever the id is set, it needs to be removed + entity.setId(null); + + try { + this.transactionBegin(); + getEntityManager().persist(entity); + getEntityManager().refresh(entity); + this.afterCreate(entity); + this.commit(); + } catch (PersistenceException e) { + if (e.getCause() instanceof PropertyValueException) { + PropertyValueException cause = (PropertyValueException) e.getCause(); + throw InsertEntityException.MANDATORY_PROPERTY(cause.getPropertyName()); + } else if (e.getCause() instanceof ConstraintViolationException) { + // Parse the error to a client readable one + Throwable cause = e.getCause().getCause(); + String details = cause.getMessage(); + Pattern pattern = Pattern.compile("\\((.*)\\)=\\((.*)\\)"); + Matcher matcher = pattern.matcher(details); + if (matcher.find()) { + String keyName = matcher.group(1); + String keyValue = matcher.group(2); + throw InsertEntityException.DUPLICATE_KEY(keyName, keyValue); + } else { + throw InsertEntityException.OTHER(details); + } + } else { + throw e; + } + } + } + + /** + * + * @param entity + */ + protected void afterEdit(T entity) { + } + + /** + * + * @param entity + */ + public void edit(T entity) { + this.transactionBegin(); + getEntityManager().merge(entity); + this.afterEdit(entity); + this.commit(); + getEntityManager().refresh(entity); + } + + /** + * + * @param entity + */ + protected void afterRemove(T entity) { + } + + /** + * + * @param entity + */ + public void remove(T entity) { + this.transactionBegin(); + getEntityManager().remove(getEntityManager().merge(entity)); + this.afterRemove(entity); + this.commit(); + } + + /** + * + * @param id + * @return + */ + public T find(Object id) { + return getEntityManager().find(entityClass, id); + } + + /** + * + * @param id + * @return + */ + public T getReference(Long id) { + return getEntityManager().getReference(entityClass, id); + } + + /** + * + * @return + */ + public Set findAll() { + CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(entityClass); + cq.select(cq.from(entityClass)); + return new HashSet(getEntityManager().createQuery(cq).getResultList()); + } + + /** + * + * @return + */ + public int count() { + CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(Long.class); + javax.persistence.criteria.Root rt = cq.from(entityClass); + cq.select(getEntityManager().getCriteriaBuilder().count(rt)); + javax.persistence.Query q = getEntityManager().createQuery(cq); + return ((Long) q.getSingleResult()).intValue(); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/AuthentificationService.java b/src/main/java/fr/lirmm/aren/service/AuthentificationService.java new file mode 100644 index 0000000..863dd35 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/AuthentificationService.java @@ -0,0 +1,94 @@ +package fr.lirmm.aren.service; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; + +import org.glassfish.jersey.client.ClientProperties; + +import fr.lirmm.aren.producer.Configurable; +import fr.lirmm.aren.exception.AuthenticationException; +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.security.PasswordEncoder; + +/** + * Component for validating user credentials. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class AuthentificationService { + + @Inject + private UserService userService; + + @Inject + private PasswordEncoder passwordEncoder; + + @Inject + @Configurable("cas.server-login-rest") + private String casUrl; + + /** + * Validate username and password. + * + * @param username + * @param password + * @return + */ + public User validateCredentials(String username, String password) { + + User user = userService.findByUsernameOrEmail(username); + if (user == null) { + throw AuthenticationException.BAD_CREDENTIALS(); + } + + if (!user.isActive()) { + // User is not active + throw AuthenticationException.INACTIVE_USER(username); + } + + if (!passwordEncoder.checkPassword(password, user.getPassword())) { + //&& !checkCasLogin(username, password)) { + // Invalid password + throw AuthenticationException.BAD_CREDENTIALS(); + } + + return user; + } + + /** + * + * @param username + * @param password + * @return + * + * This is a trick to check if the username:password exists in the CAS + * service It is then used to login the user, but doesn't log it to the + * whole CAS system + */ + private boolean checkCasLogin(String username, String password) { + String success = "A_KEY_TO_CHECK_IF_THE_RESPONSE_IS_GOOD"; + + Client client = ClientBuilder.newClient(); + + MultivaluedMap params = new MultivaluedHashMap(); + params.add("auth_mode", "BASIC"); + params.add("orig_url", success); + params.add("user", username); + params.add("password", password); + + Response response = client.target(casUrl) + .property(ClientProperties.FOLLOW_REDIRECTS, Boolean.FALSE) + .request(MediaType.APPLICATION_FORM_URLENCODED) + .post(Entity.form(params)); + + return response.getLocation().toString().equals(success); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/BroadcasterService.java b/src/main/java/fr/lirmm/aren/service/BroadcasterService.java new file mode 100644 index 0000000..3e0c384 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/BroadcasterService.java @@ -0,0 +1,117 @@ +package fr.lirmm.aren.service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.enterprise.context.ApplicationScoped; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import fr.lirmm.aren.model.AbstractEntity; +import fr.lirmm.aren.model.Comment; +import fr.lirmm.aren.model.Debate; +import fr.lirmm.aren.model.Notification; +import fr.lirmm.aren.security.AuthenticatedUserDetails; +import javax.ws.rs.core.SecurityContext; +import javax.ws.rs.sse.OutboundSseEvent; +import javax.ws.rs.sse.Sse; +import javax.ws.rs.sse.SseBroadcaster; +import javax.ws.rs.sse.SseEventSink; + +/** + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class BroadcasterService { + + @Context + private Sse sse; + + /** + * + */ + @Context + protected SecurityContext securityContext; + + private OutboundSseEvent.Builder eventBuilder; + + private final Map, HashMap> broadcasters = new HashMap, HashMap>(); + + /** + * + * @param sse + */ + @Context + public void setSse(Sse sse) { + this.sse = sse; + this.eventBuilder = sse.newEventBuilder(); + } + + private void broadcast(Long id, AbstractEntity object, Class which) { + + if (broadcasters.containsKey(which)) { + + OutboundSseEvent sseEvent = this.eventBuilder + .comment(((AuthenticatedUserDetails) securityContext.getUserPrincipal()).getUser().getId() + "") + .name("message") + .mediaType(MediaType.APPLICATION_JSON_TYPE) + .data(which, object) + .reconnectDelay(5000) + .build(); + + if (broadcasters.get(which).containsKey(id)) { + broadcasters.get(which).get(id).broadcast(sseEvent); + } + if (broadcasters.get(which).containsKey(-1L)) { + broadcasters.get(which).get(-1L).broadcast(sseEvent); + } + } + } + + /** + * + * @param id + * @param which + * @param sink + */ + public void openListener(Long id, Class which, SseEventSink sink) { + + if (!broadcasters.containsKey(which)) { + broadcasters.put(which, new HashMap()); + } + + if (!broadcasters.get(which).containsKey(id)) { + broadcasters.get(which).put(id, sse.newBroadcaster()); + } + broadcasters.get(which).get(id).register(sink); + sink.send(sse.newEvent("registered", "true")); + } + + /** + * + * @param comment + */ + public void broadcastComment(Comment comment) { + broadcast(comment.getDebate().getId(), comment, Debate.class); + } + + /** + * + * @param notif + */ + public void broadcastNotification(Notification notif) { + broadcast(notif.getOwner().getId(), notif, Notification.class); + } + + /** + * + * @param notifs + */ + public void broadcastNotification(List notifs) { + notifs.forEach(notif -> { + broadcastNotification(notif); + }); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/CasAuthentificationService.java b/src/main/java/fr/lirmm/aren/service/CasAuthentificationService.java new file mode 100644 index 0000000..e329fcd --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/CasAuthentificationService.java @@ -0,0 +1,130 @@ +package fr.lirmm.aren.service; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.inject.Inject; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import fr.lirmm.aren.producer.Configurable; +import fr.lirmm.aren.exception.InvalidAuthenticationTokenException; +import fr.lirmm.aren.model.User; +import javax.enterprise.context.ApplicationScoped; +import javax.servlet.http.HttpServletRequest; + +/** + * Service that provides operations for CAS authentification + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class CasAuthentificationService { + + @Inject + private UserService userService; + + @Inject + private InstitutionService institutionService; + + @Inject + @Configurable("cas.url") + private String serverUrl; + + @Inject + @Configurable("reverse-proxy") + private String proxyUrl; + + @Inject + private HttpServletRequest request; + + private String encodeUrl(String url) { + String encodedUrl = null; + try { + encodedUrl = URLEncoder.encode(url, "UTF-8"); + } catch (UnsupportedEncodingException ex) { + Logger.getLogger(CasAuthentificationService.class.getName()).log(Level.SEVERE, null, ex); + } + return encodedUrl; + } + + private URL genURL(String url) { + URL result = null; + try { + result = new URL(url); + } catch (MalformedURLException ex) { + Logger.getLogger(CasAuthentificationService.class.getName()).log(Level.SEVERE, null, ex); + } + return result; + } + + private String getClientUrl() { + String clientUrl; + if (proxyUrl.length() == 0) { + clientUrl = request.getRequestURL().toString(); + } else { + clientUrl = proxyUrl + "/caslogin"; + } + return clientUrl; + } + + /** + * + * @return + */ + public String getRedirectionUrl() { + return (serverUrl + "/login?service=" + encodeUrl(getClientUrl())); + } + + /** + * + * @param ticket + * @return + * @throws InvalidAuthenticationTokenException + */ + public User getUserWithTicket(String ticket) throws InvalidAuthenticationTokenException { + URL casXml = genURL(serverUrl + "/p3/serviceValidate?service=" + encodeUrl(getClientUrl()) + "&ticket=" + ticket); + Document doc = null; + + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + doc = builder.parse(casXml.openStream()); + doc.getDocumentElement().normalize(); + } catch (IOException | SAXException | ParserConfigurationException ex) { + throw InvalidAuthenticationTokenException.INVALID_CAS_TICKET(); + } + + NodeList success = doc.getElementsByTagName("cas:authenticationSuccess"); + + if (success.getLength() == 0) { + NodeList failure = doc.getElementsByTagName("cas:authenticationFailure"); + if (failure.getLength() > 0) { + String code = failure.item(0).getAttributes().getNamedItem("code").getTextContent(); + throw InvalidAuthenticationTokenException.INVALID_CAS_TICKET(code); + } + throw InvalidAuthenticationTokenException.INVALID_CAS_TICKET(); + } else { + String username = doc.getElementsByTagName("cas:user").item(0).getTextContent(); + User user = userService.findByUsernameOrEmail(username); + if (user == null) { + user = new User(); + user.setUsername(username); + user.setAuthority(User.Authority.USER); + user.setInstitution(institutionService.getReference(0L)); + userService.create(user); + } + return user; + } + } +} diff --git a/src/main/java/fr/lirmm/aren/service/CategoryService.java b/src/main/java/fr/lirmm/aren/service/CategoryService.java new file mode 100644 index 0000000..36696ea --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/CategoryService.java @@ -0,0 +1,88 @@ +package fr.lirmm.aren.service; + +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.persistence.TypedQuery; +import javax.ws.rs.NotFoundException; + +import fr.lirmm.aren.model.Category; +import fr.lirmm.aren.model.User; +import java.util.HashSet; + +/** + * Service that provides operations for {link Category}. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class CategoryService extends AbstractService { + + /** + * + */ + public CategoryService() { + super(Category.class); + } + + private TypedQuery generateQuery(Long categoryId, User user, boolean withDocuments) { + boolean isUser = user != null && user.is(User.Authority.USER) && !user.is(User.Authority.ADMIN); + boolean onlyPublic = user != null && user.getAuthority().equals(User.Authority.GUEST); + TypedQuery query = getEntityManager().createQuery("SELECT c " + + "FROM Category c " + + (withDocuments || isUser || onlyPublic + ? "LEFT JOIN " + (withDocuments ? "FETCH" : "") + " c.documents do " + : "") + + (isUser || onlyPublic + ? "LEFT JOIN do.debates d " + : "") + + (categoryId != null + ? "WHERE c.id = :categoryId " + : "WHERE c.id IS NOT NULL ") + + (isUser + ? "AND (d.openPublic IS TRUE " + + "OR :user = d.owner " + + "OR :user IN (SELECT u FROM d.guests u) " + + "OR :user IN (SELECT u FROM d.teams t LEFT JOIN t.users u)) " + : (onlyPublic + ? "AND d.openPublic IS TRUE " + : "")), + Category.class); + if (categoryId != null) { + query.setParameter("categoryId", categoryId); + } + if (isUser) { + query.setParameter("user", user); + } + return query; + } + + public Category findByUser(Long categoryId, User user, boolean withDocuments) { + List results = generateQuery(categoryId, user, withDocuments).getResultList(); + if (results.isEmpty()) { + throw new NotFoundException(); + } + return results.get(0); + } + + public HashSet findAllByUser(User user, boolean withDocuments) { + return new HashSet(generateQuery(null, user, withDocuments).getResultList()); + } + + /** + * + * @param categoryId + * @return + */ + public Category find(Long categoryId) { + return findByUser(categoryId, null, false); + } + + /** + * + * @return + */ + public HashSet findAll() { + return findAllByUser(null, false); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/CommentService.java b/src/main/java/fr/lirmm/aren/service/CommentService.java new file mode 100644 index 0000000..84b14b3 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/CommentService.java @@ -0,0 +1,184 @@ +package fr.lirmm.aren.service; + +import java.util.List; + +import javax.ws.rs.NotFoundException; + +import fr.lirmm.aren.model.Comment; +import fr.lirmm.aren.model.TagSet; +import java.util.Set; +import java.util.HashSet; +import java.util.Iterator; +import java.util.function.BiConsumer; +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; + +/** + * Service that provides operations for {link Comment}. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class CommentService extends AbstractService { + + @Inject + private HttpRequestService httpRequestService; + + /** + * + */ + public CommentService() { + super(Comment.class); + } + + /** + * + * @param entity + */ + @Override + protected void afterCreate(Comment entity) { + this.updateExternaleTables(entity); + } + + /** + * + * @param entity + */ + @Override + protected void afterRemove(Comment entity) { + this.updateExternaleTables(entity); + } + + /** + * + * @param commentId + * @return + */ + public Comment find(Long commentId) { + List results = getEntityManager().createQuery("SELECT c " + + "FROM Comment c " + + "WHERE c.id = :commentId ", Comment.class) + .setParameter("commentId", commentId) + .setMaxResults(1) + .getResultList(); + if (results.isEmpty()) { + throw new NotFoundException(); + } + return results.get(0); + } + + /** + * + * @return + */ + public Set findAll() { + return new HashSet(getEntityManager().createQuery("SELECT c " + + "FROM Comment c", Comment.class) + .getResultList()); + } + + /** + * + * @param ids + * @return + */ + public Set findAll(List ids) { + return new HashSet(getEntityManager().createQuery("SELECT c " + + "FROM Comment c " + + "WHERE id IN :ids", Comment.class) + .setParameter("ids", ids) + .getResultList()); + } + + /** + * + * @param comment + */ + public void updateExternaleTables(Comment comment) { + super.transactionBegin(); + getEntityManager().createQuery("UPDATE Debate d SET " + + "d.lastCommentDate = (SELECT MAX(c.created) FROM d.comments c), " + + "d.commentsCount = (SELECT COUNT(c) FROM d.comments c), " + + "d.commentsCountFor = (SELECT COUNT(c) FROM d.comments c WHERE c.opinion = :for), " + + "d.commentsCountAgainst = (SELECT COUNT(c) FROM d.comments c WHERE c.opinion = :against) " + + "WHERE d.id = :id") + .setParameter("for", Comment.Opinion.FOR) + .setParameter("against", Comment.Opinion.AGAINST) + .setParameter("id", comment.getDebate().getId()) + .executeUpdate(); + getEntityManager().createQuery("UPDATE Category cat SET " + + "cat.lastCommentDate = (SELECT MAX(c.created) FROM cat.documents doc LEFT JOIN doc.debates d LEFT JOIN d.comments c) " + + "WHERE cat.id = :id") + .setParameter("id", comment.getDebate().getDocument().getCategory().getId()) + .executeUpdate(); + super.commit(); + } + + private TagSet fetchNewTags(Comment comment, boolean fetchOnly) { + TagSet tags = new TagSet(); + if (comment.getReformulation() != null && !comment.getReformulation().isEmpty()) { + if (!fetchOnly && !comment.getProposedTags().isEmpty()) { + tags = httpRequestService.sendTag(comment.getProposedTags(), comment.getReformulation()); + } else { + tags = httpRequestService.retrieveTags(comment.getReformulation(), comment); + } + } + return tags; + } + + private TagSet fetchNewTags(Comment comment) { + return fetchNewTags(comment, false); + } + + /** + * + * @param comment + * @param fetchOnly + */ + public void updateTags(Comment comment, boolean fetchOnly) { + TagSet tags = fetchNewTags(comment); + getEntityManager().refresh(comment); + comment.setTags(tags); + comment.removeUnusedTags(); + this.edit(comment); + } + + /** + * + * @param comment + */ + public void updateTags(Comment comment) { + updateTags(comment, false); + } + + /** + * + * @param cms + */ + public void updateAllTags(BiConsumer callback) { + Set comments = this.findAll(); + System.out.println("Starting tags update on " + comments.size() + " comments"); + int cpt = 0; + Iterator it = comments.iterator(); + while (it.hasNext()) { + Comment comment = it.next(); + if (comment.getDebate().isIdfixLink()) { + this.updateTags(comment, true); + } + if (callback != null) { + callback.accept(comment, ((float) cpt / (float) comments.size())); + } + cpt++; + System.out.print("."); + } + System.out.println(); + System.out.println("Tags update done"); + } + + /** + * + */ + public void updateAllTags() { + this.updateAllTags(null); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/DebateService.java b/src/main/java/fr/lirmm/aren/service/DebateService.java new file mode 100644 index 0000000..86956e0 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/DebateService.java @@ -0,0 +1,212 @@ +package fr.lirmm.aren.service; + +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.persistence.TypedQuery; +import javax.ws.rs.NotFoundException; + +import fr.lirmm.aren.model.Debate; +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.model.User.Authority; +import java.util.Set; +import java.util.HashSet; + +/** + * Service that provides operations for {link Debate}. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class DebateService extends AbstractService { + + /** + * + */ + public DebateService() { + super(Debate.class); + } + + /** + * + * @param entity + */ + @Override + protected void afterCreate(Debate entity) { + this.updateExternaleTables(entity); + } + + /** + * + * @param entity + */ + @Override + protected void afterRemove(Debate entity) { + this.updateExternaleTables(entity); + } + + /** + * + * @param entity + */ + @Override + protected void afterEdit(Debate entity) { + this.updateExternaleTables(entity); + } + + private TypedQuery generateQuery(Long debateId, User user, Long categoryId, boolean withDocument, boolean withComments, boolean withTeams, boolean withGuests, boolean withUsers) { + boolean isUser = user != null && user.is(Authority.USER) && !user.is(Authority.ADMIN); + boolean onlyPublic = user != null && user.getAuthority().equals(Authority.GUEST); + TypedQuery query = getEntityManager().createQuery("SELECT d " + + "FROM Debate d " + + (withComments + ? "LEFT JOIN FETCH d.comments c " + : "") + + (withTeams || withUsers || isUser + ? "LEFT JOIN " + (withTeams || withUsers ? "FETCH" : "") + " d.teams t " + : "") + + (withUsers || isUser + ? "LEFT JOIN " + (withUsers ? "FETCH" : "") + " t.users u " + : "") + + (withGuests || isUser + ? "LEFT JOIN " + (withGuests ? "FETCH" : "") + " d.guests g " + : "") + + (withDocument + ? "LEFT JOIN FETCH d.document do " + : "") + + (debateId != null + ? "WHERE d.id = :debateId " + : "WHERE d.id IS NOT NULL ") + + (categoryId != null + ? "AND d.document.category.id = :categoryId " + : "") + + (isUser + ? "AND (d.openPublic IS TRUE " + + "OR :user = d.owner " + + "OR :user IN g " + + "OR :user IN u) " + : (onlyPublic + ? "AND d.openPublic IS TRUE " + : "")), + Debate.class + ); + + if (debateId != null) { + query.setParameter("debateId", debateId); + } + if (isUser) { + query.setParameter("user", user); + } + if (categoryId != null) { + query.setParameter("categoryId", categoryId); + } + return query; + } + + /** + * + * @param debateId + * @param user + * @param withDocument + * @param withComments + * @param withTeams + * @param withGuests + * @param withUsers + * @return + */ + public Debate findByUser(Long debateId, User user, boolean withDocument, boolean withComments, boolean withTeams, boolean withGuests, boolean withUsers) { + List results = generateQuery(debateId, user, null, withDocument, withComments, withTeams, withGuests, withUsers).getResultList(); + if (results.isEmpty()) { + throw new NotFoundException(); + } + return results.get(0); + } + + /** + * + * @param user + * @param categoryId + * @param withDocument + * @param withComments + * @param withTeams + * @param withGuests + * @param withUsers + * @return + */ + public Set findAllByUser(User user, Long categoryId, boolean withDocument, boolean withComments, boolean withTeams, boolean withGuests, boolean withUsers) { + return new HashSet(generateQuery(null, user, categoryId, withDocument, withComments, withTeams, withGuests, withUsers).getResultList()); + } + + /** + * + * @param debateId + * @param withDocument + * @param withComments + * @param withTeams + * @param withGuests + * @param withUsers + * @return + */ + public Debate find(Long debateId, boolean withDocument, boolean withComments, boolean withTeams, boolean withGuests, boolean withUsers) { + return findByUser(debateId, null, withDocument, withComments, withTeams, withGuests, withUsers); + } + + /** + * + * @param categoryId + * @param withDocument + * @param withComments + * @param withTeams + * @param withGuests + * @param withUsers + * @return + */ + public Set findAll(Long categoryId, boolean withDocument, boolean withComments, boolean withTeams, boolean withGuests, boolean withUsers) { + return findAllByUser(null, categoryId, withDocument, withComments, withTeams, withGuests, withUsers); + } + + /** + * + * @param debateId + */ + public void clearComments(Long debateId) { + this.transactionBegin(); + getEntityManager().createQuery("DELETE FROM Comment c " + + "WHERE c.debate.id = :debateId") + .setParameter("debateId", debateId) + .executeUpdate(); + getEntityManager().createQuery("UPDATE Debate d SET " + + "d.commentsCount = 0, " + + "d.commentsCountFor = 0, " + + "d.commentsCountAgainst = 0, " + + "d.lastCommentDate = null " + + "WHERE d.id = :debateId") + .setParameter("debateId", debateId) + .executeUpdate(); + this.commit(); + } + + /** + * + * @param debate + */ + public void updateExternaleTables(Debate debate) { + super.transactionBegin(); + getEntityManager().createQuery("UPDATE Category c SET " + + "c.debatesCount = (SELECT COUNT(d) FROM c.documents doc LEFT JOIN doc.debates d) " + + "WHERE c.id = :id") + .setParameter("id", debate.getDocument().getCategory().getId()) + .executeUpdate(); + getEntityManager().createQuery("UPDATE Document doc SET " + + "doc.debatesCount = (SELECT COUNT(d) FROM doc.debates d) " + + "WHERE doc.id = :id") + .setParameter("id", debate.getDocument().getId()) + .executeUpdate(); + getEntityManager().createQuery("UPDATE Team t SET " + + "t.debatesCount = (SELECT COUNT(d) from t.debates d) " + + "WHERE t IN (SELECT t1 FROM Debate d LEFT JOIN d.teams t1 WHERE d.id = :id)") + .setParameter("id", debate.getId()) + .executeUpdate(); + super.commit(); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/DocumentService.java b/src/main/java/fr/lirmm/aren/service/DocumentService.java new file mode 100644 index 0000000..48719b3 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/DocumentService.java @@ -0,0 +1,98 @@ +package fr.lirmm.aren.service; + +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.persistence.TypedQuery; +import javax.ws.rs.NotFoundException; + +import fr.lirmm.aren.model.Document; +import java.util.Set; +import java.util.HashSet; + +/** + * Service that provides operations for {link Document}. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class DocumentService extends AbstractService { + + /** + * + */ + public DocumentService() { + super(Document.class); + } + + /** + * + * @param entity + */ + @Override + protected void afterCreate(Document entity) { + this.updateExternaleTables(entity); + } + + /** + * + * @param entity + */ + @Override + protected void afterRemove(Document entity) { + this.updateExternaleTables(entity); + } + + private TypedQuery generateQuery(Long documentId, boolean withDebates) { + TypedQuery query = getEntityManager().createQuery("SELECT do " + + "FROM Document do " + + (withDebates + ? "LEFT JOIN FETCH do.debates d " + : "") + + (documentId != null + ? "WHERE do.id = :documentId " + : ""), + Document.class); + if (documentId != null) { + query.setParameter("documentId", documentId); + } + return query; + } + + /** + * + * @param debateId + * @param withDebates + * @return + */ + public Document find(Long debateId, boolean withDebates) { + List results = generateQuery(debateId, withDebates).getResultList(); + if (results.isEmpty()) { + throw new NotFoundException(); + } + return results.get(0); + } + + /** + * + * @param withDebates + * @return + */ + public Set findAll(boolean withDebates) { + return new HashSet(generateQuery(null, withDebates).getResultList()); + } + + /** + * + * @param document + */ + public void updateExternaleTables(Document document) { + super.transactionBegin(); + getEntityManager().createQuery("UPDATE Category c SET " + + "c.documentsCount = (SELECT COUNT(doc) FROM c.documents doc) " + + "WHERE c.id = :id") + .setParameter("id", document.getCategory().getId()) + .executeUpdate(); + super.commit(); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/HttpRequestService.java b/src/main/java/fr/lirmm/aren/service/HttpRequestService.java new file mode 100644 index 0000000..fe9806f --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/HttpRequestService.java @@ -0,0 +1,236 @@ +package fr.lirmm.aren.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import fr.lirmm.aren.model.Comment; +import fr.lirmm.aren.model.TagSet; +import fr.lirmm.aren.producer.Configurable; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.xml.parsers.ParserConfigurationException; +import org.apache.http.NameValuePair; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; + +/** + * Service that provides operations for AAF xml import + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class HttpRequestService { + + @Inject + @Configurable("idefix.url") + private String idefixUrl; + + @Inject + @Configurable("scalar.url") + private String scalarUrl; + + @Inject + @Configurable("plateform.id") + private String plateformId; + + @Inject + @Configurable("theme.url") + private String themeUrl; + + /** + * + * @throws ParserConfigurationException + */ + public HttpRequestService() throws ParserConfigurationException { + } + + /** + * + * @param comment + * @return + */ + public String getScalar(Comment comment) { + String result = ""; + try { + CloseableHttpClient httpClient = HttpClients.createSystem(); + HttpPost request = new HttpPost(scalarUrl); + RequestConfig requestConfig = RequestConfig.custom() + .setSocketTimeout(5000) + .setConnectTimeout(5000) + .setConnectionRequestTimeout(5000) + .build(); + + request.setConfig(requestConfig); + + List< NameValuePair> params = new ArrayList(3); + params.add(new BasicNameValuePair("ppl_name", "Complete")); + params.add(new BasicNameValuePair("fragment1", comment.getSelection() + "")); + params.add(new BasicNameValuePair("fragment2", comment.getReformulation())); + request.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + + CloseableHttpResponse response = httpClient.execute(request); + result = EntityUtils.toString(response.getEntity(), "UTF-8"); + + } catch (UnsupportedEncodingException ex) { + Logger.getLogger(HttpRequestService.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(HttpRequestService.class.getName()).log(Level.SEVERE, null, ex); + } + return result; + } + + /** + * + * @param debateId + * @param theme + * @return + */ + public String getTheme(Long debateId, String theme) { + String result = ""; + try { + CloseableHttpClient httpClient = HttpClients.createSystem(); + HttpPost request = new HttpPost(themeUrl); + RequestConfig requestConfig = RequestConfig.custom() + .setSocketTimeout(5000) + .setConnectTimeout(5000) + .setConnectionRequestTimeout(5000) + .build(); + + request.setConfig(requestConfig); + + List< NameValuePair> params = new ArrayList(3); + params.add(new BasicNameValuePair("ppl_name", "Complete")); + params.add(new BasicNameValuePair("debate_id", debateId + "")); + params.add(new BasicNameValuePair("platform_id", plateformId)); + params.add(new BasicNameValuePair("text", theme)); + request.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + + CloseableHttpResponse response = httpClient.execute(request); + JsonNode node = new ObjectMapper().readTree(response.getEntity().getContent()); + ObjectNode obj = JsonNodeFactory.instance.objectNode(); + ArrayNode arr = JsonNodeFactory.instance.arrayNode(); + node.get("arguments").fieldNames().forEachRemaining((String val) -> { + arr.add(Long.parseLong(val)); + }); + obj.set("comments", arr); + obj.set("theme", node.get("theme")); + result = obj.toString(); + + } catch (UnsupportedEncodingException ex) { + Logger.getLogger(HttpRequestService.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(HttpRequestService.class.getName()).log(Level.SEVERE, null, ex); + } + return result; + } + + /** + * + * @param text + * @param comment + * @return + */ + public TagSet retrieveTags(String text, Comment comment) { + TagSet tags = new TagSet(); + try { + CloseableHttpClient httpClient = HttpClients.createSystem(); + HttpPost httppost = new HttpPost(idefixUrl); + RequestConfig requestConfig = RequestConfig.custom() + .setSocketTimeout(1 * 60 * 1000) + .setConnectTimeout(1 * 60 * 1000) + .setConnectionRequestTimeout(1 * 60 * 1000) + .build(); + httppost.setConfig(requestConfig); + + List< NameValuePair> params = new ArrayList(3); + params.add(new BasicNameValuePair("extract_term_list", text)); + params.add(new BasicNameValuePair("extract_submit", "Extraire")); + params.add(new BasicNameValuePair("number", "20")); + httppost.setEntity(new UrlEncodedFormEntity(params, "windows-1252")); + + CloseableHttpResponse response = httpClient.execute(httppost); + String responseString = EntityUtils.toString(response.getEntity(), "windows-1252"); + + if (responseString.contains("Pas assez de termes, bye")) { + return null; + } + tags = this.parseTags(responseString); + + } catch (UnsupportedEncodingException ex) { + Logger.getLogger(HttpRequestService.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(HttpRequestService.class.getName()).log(Level.SEVERE, null, ex); + } + return tags; + } + + /** + * + * @param tags + * @param text + * @return + */ + public TagSet sendTag(TagSet tags, String text) { + TagSet newTags = new TagSet(); + try { + CloseableHttpClient httpClient = HttpClients.createSystem(); + HttpPost httppost = new HttpPost(idefixUrl); + RequestConfig requestConfig = RequestConfig.custom() + .setSocketTimeout(1 * 60 * 1000) + .setConnectTimeout(1 * 60 * 1000) + .setConnectionRequestTimeout(1 * 60 * 1000) + .build(); + httppost.setConfig(requestConfig); + + List< NameValuePair> params = new ArrayList(5); + params.add(new BasicNameValuePair("linkit_add", "Valider")); + params.add(new BasicNameValuePair("add_items", tags.toString())); + params.add(new BasicNameValuePair("extract_submit", "1")); + params.add(new BasicNameValuePair("extract_term_list", text)); + params.add(new BasicNameValuePair("extract_termid_list", "")); + httppost.setEntity(new UrlEncodedFormEntity(params, "windows-1252")); + + CloseableHttpResponse response = httpClient.execute(httppost); + String responseString = EntityUtils.toString(response.getEntity(), "windows-1252"); + if (responseString.contains("Pas assez de termes, bye")) { + return null; + } + newTags = this.parseTags(responseString); + } catch (UnsupportedEncodingException ex) { + Logger.getLogger(HttpRequestService.class + .getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(HttpRequestService.class + .getName()).log(Level.SEVERE, null, ex); + } + return newTags; + } + + private TagSet parseTags(String string) throws IOException { + TagSet tags = new TagSet(); + Document doc = Jsoup.parse(string, "windows-1252"); + if (doc.getElementsByTag("result").size() > 0) { + String tagString = doc.getElementsByTag("result").get(0).text(); + if (tagString.length() > 0) { + tags = new TagSet(tagString); + } + } + return tags; + } +} diff --git a/src/main/java/fr/lirmm/aren/service/InstitutionService.java b/src/main/java/fr/lirmm/aren/service/InstitutionService.java new file mode 100644 index 0000000..ef4f66a --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/InstitutionService.java @@ -0,0 +1,62 @@ +package fr.lirmm.aren.service; + +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.ws.rs.NotFoundException; + +import fr.lirmm.aren.model.Institution; +import java.util.Set; +import java.util.HashSet; + +/** + * Service that provides operations for {link Institution}. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class InstitutionService extends AbstractService { + + /** + * + */ + public InstitutionService() { + super(Institution.class); + } + + /** + * + * @param entId + * @return + */ + public Institution findByEntId(String entId) { + List results = getEntityManager().createQuery("SELECT i " + + "FROM Institution i " + + "WHERE i.entId = :entId", Institution.class) + .setParameter("entId", entId) + .getResultList(); + + if (results.isEmpty()) { + throw new NotFoundException(); + } + return results.get(0); + } + + /** + * + * @param withTeam + * @param withUsers + * @return + */ + public Set findAll(boolean withTeam, boolean withUsers) { + return new HashSet(getEntityManager().createQuery("SELECT i " + + "FROM Institution i " + + (withTeam || withUsers + ? "LEFT JOIN FETCH i.users u " + : "") + + (withUsers + ? "LEFT JOIN FETCH i.teams t" + : ""), Institution.class) + .getResultList()); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/MailingService.java b/src/main/java/fr/lirmm/aren/service/MailingService.java new file mode 100644 index 0000000..1720f22 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/MailingService.java @@ -0,0 +1,92 @@ +package fr.lirmm.aren.service; + +import fr.lirmm.aren.producer.Configurable; + +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.util.Properties; +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.mail.PasswordAuthentication; +import javax.mail.Transport; +import javax.mail.internet.AddressException; + +/** + * + * @author florent + */ +@ApplicationScoped +public class MailingService { + + @Inject + @Configurable("smtp.server") + private String smtpServer; + + @Inject + @Configurable("smtp.username") + private String smtpUsername; + + @Inject + @Configurable("smtp.password") + private String smtpPassword; + + @Inject + @Configurable("smtp.port") + private String smtpPort; + + @Inject + @Configurable("smtp.tls") + private String smtpTls; + + @Inject + @Configurable("smtp.auth") + private String smtpAuth; + + /** + * + * @param from + * @param to + * @param subject + * @param content + */ + public void sendMail(String from, String to, String subject, String content) throws AddressException, MessagingException { + + Properties props = new Properties(); + props.put("mail.smtp.auth", smtpAuth); + props.put("mail.smtp.starttls.enable", smtpTls); + props.put("mail.smtp.host", smtpServer); + props.put("mail.smtp.port", smtpPort); + + // Get the Session object. + Session session = Session.getInstance(props, + new javax.mail.Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(smtpUsername, smtpPassword); + } + }); + + // Create a default MimeMessage object. + Message message = new MimeMessage(session); + + // Set From: header field of the header. + message.setFrom(new InternetAddress(from)); + + // Set To: header field of the header. + message.setRecipients(Message.RecipientType.TO, + InternetAddress.parse(to)); + + // Set Subject: header field + message.setSubject(subject); + + // Send the actual HTML message, as big as you like + message.setContent(content, "text/html"); + + // Send message + Transport.send(message); + } + +} diff --git a/src/main/java/fr/lirmm/aren/service/NotificationService.java b/src/main/java/fr/lirmm/aren/service/NotificationService.java new file mode 100644 index 0000000..a6cc5c0 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/NotificationService.java @@ -0,0 +1,91 @@ +package fr.lirmm.aren.service; + +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; + +import fr.lirmm.aren.model.Notification; +import java.util.Set; +import java.util.HashSet; + +/** + * Service that provides operations for {link Notification}. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class NotificationService extends AbstractService { + + /** + * + */ + public NotificationService() { + super(Notification.class); + } + + /** + * + * @param userId + * @return + */ + public Set findAllByUser(Long userId) { + + List notifs = getEntityManager().createQuery("SELECT n " + + "FROM Notification n " + + "WHERE n.owner.id = :userId " + + "ORDER BY n.created DESC", Notification.class) + .setParameter("userId", userId) + .getResultList(); + if (notifs.isEmpty()) { + return null; + } + return new HashSet(notifs); + } + + /** + * + * @param userId + * @param readenLimit + * @return + */ + public Set findAllFirstsByUser(Long userId, int readenLimit) { + return new HashSet(getEntityManager().createQuery("SELECT n1 " + + "FROM Notification n1 " + + "WHERE n1.owner.id = :userId " + + "AND (n1.unread = true " + + "OR (SELECT COUNT(id) " + + " FROM Notification n2 " + + " WHERE n2.owner.id = :userId " + + " AND n2.created >= n1.created) <= :readenLimit)") + .setParameter("userId", userId) + .setParameter("readenLimit", Long.valueOf(readenLimit)) + .getResultList()); + } + + /** + * + * @param userId + */ + public void readAllByUser(Long userId) { + super.transactionBegin(); + getEntityManager().createQuery("UPDATE Notification n " + + "SET n.unread = false " + + "WHERE n.owner.id = :userId") + .setParameter("userId", userId) + .executeUpdate(); + super.commit(); + } + + /** + * + * @param userId + */ + public void removeAllByUser(Long userId) { + super.transactionBegin(); + getEntityManager().createQuery("DELETE Notification n " + + "WHERE n.owner.id = :userId") + .setParameter("userId", userId) + .executeUpdate(); + super.commit(); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/ODFService.java b/src/main/java/fr/lirmm/aren/service/ODFService.java new file mode 100644 index 0000000..36e145f --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/ODFService.java @@ -0,0 +1,423 @@ +package fr.lirmm.aren.service; + +import fr.lirmm.aren.model.Comment; +import fr.lirmm.aren.model.Debate; +import java.io.File; +import java.time.format.DateTimeFormatter; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.enterprise.context.ApplicationScoped; +import org.jsoup.Jsoup; +import org.jsoup.helper.W3CDom; +import org.odftoolkit.odfdom.doc.OdfTextDocument; +import org.odftoolkit.odfdom.dom.element.style.StyleParagraphPropertiesElement; +import org.odftoolkit.odfdom.dom.element.office.OfficeTextElement; +import org.odftoolkit.odfdom.dom.element.style.StyleListLevelPropertiesElement; +import org.odftoolkit.odfdom.dom.element.style.StyleMasterPageElement; +import org.odftoolkit.odfdom.dom.element.style.StyleTextPropertiesElement; +import org.odftoolkit.odfdom.dom.element.table.TableTableCellElement; +import org.odftoolkit.odfdom.dom.element.table.TableTableElement; +import org.odftoolkit.odfdom.dom.element.table.TableTableRowElement; +import org.odftoolkit.odfdom.dom.element.text.TextListItemElement; +import org.odftoolkit.odfdom.dom.element.text.TextListLevelStyleNumberElement; +import org.odftoolkit.odfdom.dom.style.OdfStyleFamily; +import org.odftoolkit.odfdom.dom.style.OdfStylePropertySet; +import org.odftoolkit.odfdom.dom.style.props.OdfPageLayoutProperties; +import org.odftoolkit.odfdom.dom.style.props.OdfStyleProperty; +import org.odftoolkit.odfdom.incubator.doc.draw.OdfDrawImage; +import org.odftoolkit.odfdom.incubator.doc.office.OdfOfficeStyles; +import org.odftoolkit.odfdom.incubator.doc.style.OdfStylePageLayout; +import org.odftoolkit.odfdom.incubator.doc.text.OdfTextHeading; +import org.odftoolkit.odfdom.incubator.doc.text.OdfTextList; +import org.odftoolkit.odfdom.incubator.doc.text.OdfTextListStyle; +import org.odftoolkit.odfdom.incubator.doc.text.OdfTextParagraph; +import org.odftoolkit.odfdom.incubator.doc.text.OdfTextSpan; +import org.odftoolkit.odfdom.pkg.OdfFileDom; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * + * @author florent + */ +@ApplicationScoped +public class ODFService { + + private OdfTextDocument outputDocument; + private OdfFileDom contentDom; + private OdfOfficeStyles stylesOfficeStyles; + private OfficeTextElement officeText; + private DateTimeFormatter formater = DateTimeFormatter.ofPattern("dd/MM/yyyy - HH:mm:ss"); + + private OdfStyleProcessor styleProcessor = new OdfStyleProcessor(); + + /** + * + */ + public ODFService() { + try { + this.outputDocument = OdfTextDocument.newTextDocument(); + this.contentDom = outputDocument.getContentDom(); + this.stylesOfficeStyles = outputDocument.getOrCreateDocumentStyles(); + this.officeText = outputDocument.getContentRoot(); + } catch (Exception ex) { + Logger.getLogger(ODFService.class.getName()).log(Level.SEVERE, null, ex); + } + } + + /** + * + * @param debate + * @return + * @throws Exception + */ + public File parseDebate(Debate debate) throws Exception { + Document document = W3CDom.convert(Jsoup.parse(debate.getDocument().getContent())); + + cleanOutDocument(); + setOfficeStyles(); + + //Set main heading + OdfTextHeading heading = new OdfTextHeading(contentDom, "Heading", debate.getDocument().getName()); + OdfTextSpan span = new OdfTextSpan(contentDom, "Text_20_indice", ""); + span.appendChild(new OdfTextSpan(contentDom, "Text_20_grey", " par ")); + span.addContent(debate.getDocument().getAuthor()); + heading.appendChild(span); + officeText.appendChild(heading); + + TableTableElement table = new TableTableElement(contentDom); + table.newTableTableColumnElement().setTableNumberColumnsRepeatedAttribute(2); + TableTableRowElement row = table.newTableTableRowElement(); + officeText.appendChild(table); + + TableTableCellElement cell = new TableTableCellElement(contentDom); + htmlToOdf(document.getElementsByTagName("body").item(0), cell); + cell.setProperty(StyleParagraphPropertiesElement.MarginRight, "0.5cm"); + row.appendChild(cell); + + TableTableCellElement commentsList = new TableTableCellElement(contentDom); + debate.getComments().forEach((Comment comment) -> { + if (comment.getParent() == null) { + parseComment(comment, commentsList, 0); + } + }); + row.appendChild(commentsList); + + File file = new File("/tmp/aren_export_" + System.currentTimeMillis() + ".odt"); + this.outputDocument.save(file); + return file; + } + + /** + * + * @param comment + * @param root + * @param level + */ + public void parseComment(Comment comment, Node root, int level) { + OdfTextSpan span; + OdfTextParagraph paragraph; + String color; + + if (comment.getOpinion() == Comment.Opinion.AGAINST) { + color = "orange"; + } else if (comment.getOpinion() == Comment.Opinion.FOR) { + color = "blue"; + } else { + color = "grey"; + } + + paragraph = new OdfTextParagraph(contentDom, "Text_20_border_left_" + color); + paragraph.setProperty(StyleParagraphPropertiesElement.MarginLeft, level * 0.5 + "cm"); + paragraph.appendChild(new OdfTextSpan(contentDom, "Text_20_" + color, + comment.getOwner().getFirstName() + " " + comment.getOwner().getLastName() + " - " + comment.getCreated().format(formater))); + root.appendChild(paragraph); + + Document selection = W3CDom.convert(Jsoup.parse(comment.getSelection())); + paragraph = new OdfTextParagraph(contentDom, "Text_20_border_left_" + color, + selection.getElementsByTagName("body").item(0).getTextContent()); + paragraph.setProperty(StyleParagraphPropertiesElement.MarginLeft, level * 0.5 + "cm"); + styleProcessor.setStyle(paragraph).backgroundColor("#dddfe2"); + root.appendChild(paragraph); + + paragraph = new OdfTextParagraph(contentDom, "Text_20_border_left_" + color); + paragraph.setProperty(StyleParagraphPropertiesElement.MarginLeft, level * 0.5 + "cm"); + span = new OdfTextSpan(contentDom, "Text_20_italic", comment.getReformulation()); + paragraph.appendChild(span); + root.appendChild(paragraph); + + paragraph = new OdfTextParagraph(contentDom, "Text_20_border_left_" + color, comment.getArgumentation()); + paragraph.setProperty(StyleParagraphPropertiesElement.MarginLeft, level * 0.5 + "cm"); + root.appendChild(paragraph); + + paragraph = new OdfTextParagraph(contentDom); + styleProcessor.setStyle(paragraph).fontSize("9pt"); + root.appendChild(paragraph); + + comment.getComments().forEach((Comment child) -> { + parseComment(child, root, level + 1); + }); + } + + private void htmlToOdf(Node rootHtml, Node rootOdf) { + if (rootHtml.hasChildNodes()) { + for (int i = 0; i < rootHtml.getChildNodes().getLength(); i++) { + Node childHtml = rootHtml.getChildNodes().item(i); + Node childOdf; + switch (childHtml.getNodeName()) { + case "#text": + if (rootOdf instanceof TextListItemElement) { + childOdf = new OdfTextParagraph(contentDom, "", childHtml.getTextContent()); + } else { + childOdf = contentDom.createTextNode(childHtml.getTextContent()); + } + break; + case "span": + childOdf = new OdfTextSpan(contentDom); + break; + case "h1": + childOdf = new OdfTextHeading(contentDom, "Heading_20_1"); + break; + case "h2": + childOdf = new OdfTextHeading(contentDom, "Heading_20_2"); + break; + case "h3": + childOdf = new OdfTextHeading(contentDom, "Heading_20_3"); + break; + case "h4": + childOdf = new OdfTextHeading(contentDom, "Heading_20_4"); + break; + case "b": + case "strong": + childOdf = new OdfTextSpan(contentDom, "Text_20_bold"); + break; + case "i": + case "em": + childOdf = new OdfTextSpan(contentDom, "Text_20_italic"); + break; + case "u": + childOdf = new OdfTextSpan(contentDom, "Text_20_uderline"); + break; + case "ul": + childOdf = new OdfTextList(contentDom); + break; + case "li": + childOdf = new TextListItemElement(contentDom); + break; + case "img": + childOdf = new OdfDrawImage(contentDom); + break; + default: + childOdf = new OdfTextParagraph(contentDom); + } + + rootOdf.appendChild(childOdf); + htmlToOdf(childHtml, childOdf); + } + + } + } + + private void cleanOutDocument() { + org.w3c.dom.Node childNode = officeText.getFirstChild(); + while (childNode != null) { + officeText.removeChild(childNode); + childNode = officeText.getFirstChild(); + } + } + + private void setOfficeStyles() { + // Set landscape layout + StyleMasterPageElement defaultPage = outputDocument.getOfficeMasterStyles().getMasterPage("Standard"); + String pageLayoutName = defaultPage.getStylePageLayoutNameAttribute(); + OdfStylePageLayout pageLayoutStyle = defaultPage.getAutomaticStyles().getPageLayout(pageLayoutName); + pageLayoutStyle.setProperty(OdfPageLayoutProperties.PrintOrientation, "landscape"); + pageLayoutStyle.setProperty(OdfPageLayoutProperties.PageHeight, "21cm"); + pageLayoutStyle.setProperty(OdfPageLayoutProperties.PageWidth, "29.7cm"); + + // Set default font + styleProcessor.setStyle(stylesOfficeStyles.getDefaultStyle(OdfStyleFamily.Paragraph)) + .margins("0cm", "0cm", "0.1cm", "0cm") + .fontFamilly("Arial") + .fontSize("11pt") + .textAlign("justify"); + + // Main title + styleProcessor.setStyle(stylesOfficeStyles.getStyle("Heading", OdfStyleFamily.Paragraph)) + .textAlign("center") + .margins("0.4cm", "0cm", "0.2cm", "0cm") + .fontWeight("bold") + .fontSize("18pt") + .color("#b84000"); + + // Title 1 + styleProcessor.setStyle(stylesOfficeStyles.getStyle("Heading_20_1", OdfStyleFamily.Paragraph)) + .margins("0.35cm", "0cm", "0.2cm", "0cm") + .fontWeight("bold") + .fontSize("17pt") + .color("#b84000"); + + // Title 2 + styleProcessor.setStyle(stylesOfficeStyles.getStyle("Heading_20_2", OdfStyleFamily.Paragraph)) + .margins("0.3cm", "0cm", "0.2cm", "0cm") + .fontWeight("bold") + .fontSize("15pt") + .color("#b84000"); + + // Title 3 + styleProcessor.setStyle(stylesOfficeStyles.getStyle("Heading_20_3", OdfStyleFamily.Paragraph)) + .margins("0.25cm", "0cm", "0.2cm", "0cm") + .fontWeight("bold") + .fontSize("13pt"); + + // Title 4 + styleProcessor.setStyle(stylesOfficeStyles.getStyle("Heading_20_4", OdfStyleFamily.Paragraph)) + .margins("0.2cm", "0cm", "0.2cm", "0cm") + .fontWeight("bold") + .fontSize("11pt") + .color("#b84000"); + + // Bold + styleProcessor.setStyle(stylesOfficeStyles.newStyle("Text_20_bold", OdfStyleFamily.Text)) + .fontWeight("bold"); + + // Italic + styleProcessor.setStyle(stylesOfficeStyles.newStyle("Text_20_italic", OdfStyleFamily.Text)) + .fontStyle("italic"); + + // Underline + styleProcessor.setStyle(stylesOfficeStyles.newStyle("Text_20_underline", OdfStyleFamily.Text)) + .textUnderline("auto", "solid", "font-color"); + + // Orange + styleProcessor.setStyle(stylesOfficeStyles.newStyle("Text_20_orange", OdfStyleFamily.Text)) + .color("#b84000"); + + // Blue + styleProcessor.setStyle(stylesOfficeStyles.newStyle("Text_20_blue", OdfStyleFamily.Text)) + .color("#4d9999"); + + // Grey + styleProcessor.setStyle(stylesOfficeStyles.newStyle("Text_20_grey", OdfStyleFamily.Text)) + .color("#b2b2b2"); + + // Indice + styleProcessor.setStyle(stylesOfficeStyles.newStyle("Text_20_indice", OdfStyleFamily.Text)) + .textPosition("sub 50%"); + + // Comment List + TextListLevelStyleNumberElement level; + OdfTextListStyle listStyle = stylesOfficeStyles.getListStyle("Numbering_20_1"); + for (int i = 0; i < 10; i++) { + level = (TextListLevelStyleNumberElement) listStyle.getLevel(i + 1); + level.setStyleNumFormatAttribute(""); + level.setStyleNumSuffixAttribute(""); + level.setProperty(StyleListLevelPropertiesElement.SpaceBefore, (i * 0.5) + "cm"); + level.setProperty(StyleListLevelPropertiesElement.MinLabelWidth, 0 + "cm"); + } + + // Border Orange + styleProcessor.setStyle(stylesOfficeStyles.newStyle("Text_20_border_left_orange", OdfStyleFamily.Paragraph)) + .paddings("0cm", "0cm", "0cm", "0.2cm") + .setProperty(StyleParagraphPropertiesElement.BorderLeft, "3pt solid #b84000"); + + // Border Blue + styleProcessor.setStyle(stylesOfficeStyles.newStyle("Text_20_border_left_blue", OdfStyleFamily.Paragraph)) + .paddings("0cm", "0cm", "0cm", "0.2cm") + .setProperty(StyleParagraphPropertiesElement.BorderLeft, "3pt solid #4d9999"); + + // Border Grey + styleProcessor.setStyle(stylesOfficeStyles.newStyle("Text_20_border_left_grey", OdfStyleFamily.Paragraph)) + .paddings("0cm", "0cm", "0cm", "0.2cm") + .setProperty(StyleParagraphPropertiesElement.BorderLeft, "3pt solid #b2b2b2"); + } + + private class OdfStyleProcessor { + + private OdfStylePropertySet style; + + public OdfStyleProcessor() { + } + + public OdfStyleProcessor setStyle(OdfStylePropertySet style) { + this.style = style; + return this; + } + + public OdfStyleProcessor fontFamilly(String value) { + this.style.setProperty(StyleTextPropertiesElement.FontFamily, value); + this.style.setProperty(StyleTextPropertiesElement.FontName, value); + return this; + } + + public OdfStyleProcessor fontWeight(String value) { + this.style.setProperty(StyleTextPropertiesElement.FontWeight, value); + this.style.setProperty(StyleTextPropertiesElement.FontWeightAsian, value); + this.style.setProperty(StyleTextPropertiesElement.FontWeightComplex, value); + return this; + } + + public OdfStyleProcessor fontStyle(String value) { + this.style.setProperty(StyleTextPropertiesElement.FontStyle, value); + this.style.setProperty(StyleTextPropertiesElement.FontStyleAsian, value); + this.style.setProperty(StyleTextPropertiesElement.FontStyleComplex, value); + return this; + } + + public OdfStyleProcessor fontSize(String value) { + this.style.setProperty(StyleTextPropertiesElement.FontSize, value); + this.style.setProperty(StyleTextPropertiesElement.FontSizeAsian, value); + this.style.setProperty(StyleTextPropertiesElement.FontSizeComplex, value); + return this; + } + + public OdfStyleProcessor textUnderline(String width, String style, String color) { + this.style.setProperty(StyleTextPropertiesElement.TextUnderlineWidth, width); + this.style.setProperty(StyleTextPropertiesElement.TextUnderlineStyle, style); + this.style.setProperty(StyleTextPropertiesElement.TextUnderlineColor, color); + return this; + } + + public OdfStyleProcessor margins(String top, String right, String bottom, String left) { + this.style.setProperty(StyleParagraphPropertiesElement.MarginTop, top); + this.style.setProperty(StyleParagraphPropertiesElement.MarginRight, right); + this.style.setProperty(StyleParagraphPropertiesElement.MarginBottom, bottom); + this.style.setProperty(StyleParagraphPropertiesElement.MarginLeft, left); + return this; + } + + public OdfStyleProcessor paddings(String top, String right, String bottom, String left) { + this.style.setProperty(StyleParagraphPropertiesElement.PaddingTop, top); + this.style.setProperty(StyleParagraphPropertiesElement.PaddingRight, right); + this.style.setProperty(StyleParagraphPropertiesElement.PaddingBottom, bottom); + this.style.setProperty(StyleParagraphPropertiesElement.PaddingLeft, left); + return this; + } + + public OdfStyleProcessor color(String value) { + this.style.setProperty(StyleTextPropertiesElement.Color, value); + return this; + } + + public OdfStyleProcessor backgroundColor(String value) { + this.style.setProperty(StyleParagraphPropertiesElement.BackgroundColor, value); + return this; + } + + public OdfStyleProcessor textAlign(String value) { + this.style.setProperty(StyleParagraphPropertiesElement.TextAlign, value); + return this; + } + + public OdfStyleProcessor textPosition(String value) { + this.style.setProperty(StyleTextPropertiesElement.TextPosition, value); + return this; + } + + public OdfStyleProcessor setProperty(OdfStyleProperty prop, String value) { + this.style.setProperty(prop, value); + return this; + } + } + +} diff --git a/src/main/java/fr/lirmm/aren/service/TeamService.java b/src/main/java/fr/lirmm/aren/service/TeamService.java new file mode 100644 index 0000000..fe52d69 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/TeamService.java @@ -0,0 +1,83 @@ +package fr.lirmm.aren.service; + +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.ws.rs.NotFoundException; + +import fr.lirmm.aren.model.Team; +import java.util.Set; +import java.util.HashSet; + +/** + * Service that provides operations for {link Team}. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class TeamService extends AbstractService { + + /** + * + */ + public TeamService() { + super(Team.class); + } + + /** + * + * @param entity + */ + @Override + protected void afterEdit(Team entity) { + this.updateExternaleTables(entity); + } + + /** + * + * @param standalone + * @return + */ + public Set findAll(boolean standalone) { + + return new HashSet(getEntityManager().createQuery("SELECT t " + + "FROM Team t " + + (standalone + ? "WHERE t.institution IS NULL" + : ""), Team.class) + .getResultList()); + } + + /** + * + * @param entId + * @return + */ + public Team findByEntId(String entId) { + List results = getEntityManager().createQuery("SELECT i " + + "FROM Team t " + + "WHERE t.entId = :entId", Team.class) + .setParameter("entId", entId) + .getResultList(); + + if (results.isEmpty()) { + throw new NotFoundException(); + } + return results.get(0); + } + + /** + * + * @param team + */ + public void updateExternaleTables(Team team) { + super.transactionBegin(); + getEntityManager().createQuery("UPDATE Team t SET " + + "t.usersCount = (SELECT COUNT(u) FROM t.users u), " + + "t.debatesCount = (SELECT COUNT(d) FROM t.debates d) " + + "WHERE t.id = :id") + .setParameter("id", team.getId()) + .executeUpdate(); + super.commit(); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/UserService.java b/src/main/java/fr/lirmm/aren/service/UserService.java new file mode 100644 index 0000000..39d9d44 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/UserService.java @@ -0,0 +1,217 @@ +package fr.lirmm.aren.service; + +import java.util.List; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; + +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.security.PasswordEncoder; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Set; +import java.util.HashSet; + +/** + * Service that provides operations for {@link User}. + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +public class UserService extends AbstractService { + + @Inject + private PasswordEncoder passwordEncoder; + + /** + * + */ + public UserService() { + super(User.class); + } + + /** + * + * @param entity + */ + @Override + protected void afterEdit(User entity) { + this.updateExternaleTables(entity); + } + + /** + * + * @param user + */ + @Override + public void create(User user) { + String hashedPassword = passwordEncoder.hashPassword(user.getPassword()); + user.setPassword(hashedPassword); + super.create(user); + } + + /** + * + * @param user + */ + @Override + public void edit(User user) { + super.edit(user); + } + + /** + * + * @param user + * @param newPassword + */ + public void changePassword(User user, String newPassword) { + String hashedPassword = passwordEncoder.hashPassword(newPassword); + user.setPassword(hashedPassword); + super.edit(user); + this.invalidateToken(user); + } + + /** + * Find a user by username or email. + * + * @param identifier + * @return + */ + public User findByUsernameOrEmail(String identifier) { + List results = getEntityManager().createQuery("SELECT u " + + "FROM User u " + + "WHERE (u.username = :identifier " + + "OR u.email = :identifier)", User.class) + .setParameter("identifier", identifier) + .getResultList(); + + if (results.isEmpty()) { + return null; + } + return results.get(0); + } + + /** + * + * @param entId + * @return + */ + public User findByEntId(String entId) { + List results = getEntityManager().createQuery("SELECT u " + + "FROM User u " + + "WHERE u.active = true " + + "AND u.entId = :entId", User.class) + .setParameter("entId", entId) + .getResultList(); + + if (results.isEmpty()) { + return null; + } + return results.get(0); + } + + /** + * + * @param standalone + * @return + */ + public Set findAll(boolean standalone) { + + return new HashSet(getEntityManager().createQuery("SELECT u " + + "FROM User u " + + "WHERE u.active = true " + + (standalone + ? "AND u.institution IS NULL " + : ""), User.class) + .getResultList()); + } + + /** + * + * @param debateId + * @return + */ + public List findByDebate(Long debateId) { + List users = getEntityManager().createQuery("SELECT u " + + "FROM User u " + + "LEFT JOIN u.teams t " + + "LEFT JOIN t.debates d " + + "WHERE u.active = true " + + "AND d.id = :debateId", User.class) + .setParameter("debateId", debateId) + .getResultList(); + + if (users.isEmpty()) { + return null; + } + return users; + } + + /** + * + * @param user + */ + public void updateLastLogin(User user) { + super.transactionBegin(); + getEntityManager().createQuery("UPDATE User u " + + "SET u.lastLogin = :now " + + "WHERE u.id = :userId") + .setParameter("now", ZonedDateTime.now().truncatedTo(ChronoUnit.SECONDS)) + .setParameter("userId", user.getId()) + .executeUpdate(); + super.commit(); + getEntityManager().refresh(user); + } + + /** + * + * @param user + */ + public void invalidateToken(User user) { + super.transactionBegin(); + getEntityManager().createQuery("UPDATE User u " + + "SET u.tokenValidity = :now " + + "WHERE u.id = :userId") + .setParameter("now", ZonedDateTime.now().truncatedTo(ChronoUnit.SECONDS)) + .setParameter("userId", user.getId()) + .executeUpdate(); + super.commit(); + getEntityManager().refresh(user); + } + + /** + * + * @param userId + */ + public void hide(Long userId) { + super.transactionBegin(); + getEntityManager().createQuery("UPDATE User u " + + "SET u.active = :active " + + ", u.password = NULL " + + ", u.username = NULL " + + ", u.firstName = NULL " + + ", u.lastName = NULL " + + ", u.email = NULL " + + ", u.authority = :authority " + + "WHERE u.id = :userId") + .setParameter("authority", User.Authority.DELETED) + .setParameter("active", false) + .setParameter("userId", userId) + .executeUpdate(); + super.commit(); + } + + /** + * + * @param user + */ + public void updateExternaleTables(User user) { + super.transactionBegin(); + getEntityManager().createQuery("UPDATE Team t SET " + + "t.usersCount = (SELECT COUNT(u) from t.users u) " + + "WHERE t IN (SELECT t1 FROM User u LEFT JOIN u.teams t1 WHERE u.id = :id)") + .setParameter("id", user.getId()) + .executeUpdate(); + super.commit(); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/agenda/ACalendarService.java b/src/main/java/fr/lirmm/aren/service/agenda/ACalendarService.java new file mode 100644 index 0000000..6e65a7b --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/agenda/ACalendarService.java @@ -0,0 +1,56 @@ +package fr.lirmm.aren.service.agenda; + +import fr.lirmm.aren.model.agenda.ACalendar; +import fr.lirmm.aren.service.AbstractService; +import fr.lirmm.aren.service.HttpRequestService; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.persistence.TypedQuery; +import javax.ws.rs.NotFoundException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Havana Andriambolaharimihanta + */ +@ApplicationScoped +public class ACalendarService extends AbstractService { + public ACalendarService() { + super(ACalendar.class); + } + + private TypedQuery generateQuery(Long aCalendarId) { + TypedQuery query = getEntityManager().createQuery("SELECT ac " + +"FROM ACalendar ac " + + (aCalendarId != null + ? "WHERE ac.id = :choiceId " + : "WHERE ac.id IS NOT NULL ") + ,ACalendar.class + ) ; + if (aCalendarId != null) { + query.setParameter("choiceId", aCalendarId); + } + return query ; + } + + public Set findAll() { + return new HashSet(generateQuery(null).getResultList()); + } + + @Override + public void edit(ACalendar aCalendar) { + super.edit(aCalendar); + } + + public ACalendar find(Long aCalendarId, boolean withVotes) { + List results = generateQuery(aCalendarId).getResultList(); + if (results.isEmpty()) { + throw new NotFoundException(); + } + return results.get(0); + } + + +} \ No newline at end of file diff --git a/src/main/java/fr/lirmm/aren/service/framadate/FDChoiceService.java b/src/main/java/fr/lirmm/aren/service/framadate/FDChoiceService.java new file mode 100644 index 0000000..12a1d4a --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/framadate/FDChoiceService.java @@ -0,0 +1,60 @@ +package fr.lirmm.aren.service.framadate; + +import fr.lirmm.aren.model.Category; +import fr.lirmm.aren.model.Document; +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.model.framadate.FDChoice; +import fr.lirmm.aren.service.AbstractService; +import fr.lirmm.aren.service.HttpRequestService; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.persistence.TypedQuery; +import javax.ws.rs.NotFoundException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Havana Andriambolaharimihanta + */ +@ApplicationScoped +public class FDChoiceService extends AbstractService { + public FDChoiceService() { + super(FDChoice.class); + } + + private TypedQuery generateQuery(Long choiceId, boolean withVotes) { + TypedQuery query = getEntityManager().createQuery("SELECT fdc " + +"FROM FDChoice fdc " + +(withVotes? "LEFT JOIN FETCH fdc.votes vo " : "") + + (choiceId != null + ? "WHERE fdc.id = :choiceId " + : "WHERE fdc.id IS NOT NULL ") + ,FDChoice.class + ) ; + if (choiceId != null) { + query.setParameter("choiceId", choiceId); + } + return query ; + } + + public Set findAll(boolean withVotes) { + return new HashSet(generateQuery(null, withVotes).getResultList()); + } + + @Override + public void edit(FDChoice fdChoice) { + super.edit(fdChoice); + } + + public FDChoice find(Long fdChoiceId, boolean withVotes) { + List results = generateQuery(fdChoiceId, withVotes).getResultList(); + if (results.isEmpty()) { + throw new NotFoundException(); + } + return results.get(0); + } + + +} \ No newline at end of file diff --git a/src/main/java/fr/lirmm/aren/service/framadate/FDThemeService.java b/src/main/java/fr/lirmm/aren/service/framadate/FDThemeService.java new file mode 100644 index 0000000..0c3df0a --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/framadate/FDThemeService.java @@ -0,0 +1,48 @@ +package fr.lirmm.aren.service.framadate; +import fr.lirmm.aren.model.framadate.FDTheme; +import fr.lirmm.aren.service.AbstractService; + +import javax.enterprise.context.ApplicationScoped; +import javax.persistence.TypedQuery; +import javax.ws.rs.NotFoundException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +@ApplicationScoped +public class FDThemeService extends AbstractService { + public FDThemeService() { + super(FDTheme.class); + } + private TypedQuery generateQuery(Long themeId, boolean withChoices, boolean withVotes){ + TypedQuery query = getEntityManager().createQuery("SELECT ft " + +"FROM FDTheme ft " + +(withChoices? "LEFT JOIN FETCH ft.choices co " : "") + +(withVotes? "LEFT JOIN FETCH co.votes vo " : "") + + (themeId != null + ? "WHERE ft.id = :themeId " + : "WHERE ft.id IS NOT NULL ") + , FDTheme.class + ) ; + if (themeId != null) { + query.setParameter("themeId", themeId); + } + return query ; + } + + public Set findAll(boolean withChoices, boolean withVotes) { + return new HashSet(generateQuery(null, withChoices,withVotes).getResultList()); + } + + @Override + public void edit(FDTheme fdTheme) { + super.edit(fdTheme); + } + + public FDTheme find(Long fdPollId, boolean withChoices, boolean withVotes) { + List results = generateQuery(fdPollId, withChoices,withVotes).getResultList(); + if (results.isEmpty()) { + throw new NotFoundException(); + } + return results.get(0); + } +} diff --git a/src/main/java/fr/lirmm/aren/service/framadate/FDVoteService.java b/src/main/java/fr/lirmm/aren/service/framadate/FDVoteService.java new file mode 100644 index 0000000..ed9d034 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/service/framadate/FDVoteService.java @@ -0,0 +1,52 @@ +package fr.lirmm.aren.service.framadate; + +import fr.lirmm.aren.model.framadate.FDChoice; +import fr.lirmm.aren.model.framadate.FDVote; +import fr.lirmm.aren.service.AbstractService; + +import javax.enterprise.context.ApplicationScoped; +import javax.ws.rs.NotFoundException; +import java.util.List; + +/** + * @author Havana Andriambolaharimihanta + */ +@ApplicationScoped +public class FDVoteService extends AbstractService { + public FDVoteService(){super(FDVote.class);} + + @Override + protected void afterCreate(FDVote entity){ + this.updateExternaleTables(entity); + } + + public void updateExternaleTables(FDVote vote){ + super.transactionBegin(); + List results = getEntityManager().createQuery("SELECT c " + + "FROM FDChoice c " + + "WHERE c.id = :id", FDChoice.class) + .setParameter("id", vote.getSubThemeId().getId()) + .getResultList(); + + if (results.isEmpty()) { + throw new NotFoundException(); + } + FDChoice choice=results.get(0) ; + if(vote.getOpinion().equals("FOR"))choice.setFor(choice.getFor()+1); + if(vote.getOpinion().equals("NEUTRAL"))choice.setNeutral(choice.getNeutral()+1); + if(vote.getOpinion().equals("AGAINST"))choice.setAgainst(choice.getAgainst()+1); + + getEntityManager().createQuery("UPDATE FDChoice c SET " + + "c._for = :for, " + + "c.against = :against, " + + "c.neutral = :neutral " + +"WHERE c.id=:id" + ) + .setParameter("for", choice.getFor()) + .setParameter("against", choice.getAgainst()) + .setParameter("neutral", choice.getNeutral()) + .setParameter("id", vote.getSubThemeId().getId()) + .executeUpdate(); + super.commit() ; + } +} \ No newline at end of file diff --git a/src/main/java/fr/lirmm/aren/servlet/BackgroundJobManager.java b/src/main/java/fr/lirmm/aren/servlet/BackgroundJobManager.java new file mode 100644 index 0000000..ed56f03 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/servlet/BackgroundJobManager.java @@ -0,0 +1,51 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package fr.lirmm.aren.servlet; + +import fr.lirmm.aren.service.CommentService; +import java.util.Calendar; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.inject.Inject; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +/** + * + * @author florent + */ +@WebListener +public class BackgroundJobManager implements ServletContextListener { + + @Inject + private CommentService commentService; + + private ScheduledExecutorService scheduler; + + @Override + public void contextInitialized(ServletContextEvent event) { + Calendar c = Calendar.getInstance(); + c.add(Calendar.DAY_OF_MONTH, 1); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + long untilMidnight = (c.getTimeInMillis() - System.currentTimeMillis()); + long millisInDay = 24 * 60 * 60 * 1000; + + this.scheduler = Executors.newSingleThreadScheduledExecutor(); + this.scheduler.scheduleAtFixedRate(() -> { + this.commentService.updateAllTags(); + }, untilMidnight, millisInDay, TimeUnit.MILLISECONDS); + } + + @Override + public void contextDestroyed(ServletContextEvent event) { + this.scheduler.shutdownNow(); + } +} diff --git a/src/main/java/fr/lirmm/aren/servlet/CasLogin.java b/src/main/java/fr/lirmm/aren/servlet/CasLogin.java new file mode 100644 index 0000000..95155b3 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/servlet/CasLogin.java @@ -0,0 +1,107 @@ +package fr.lirmm.aren.servlet; + +import java.io.IOException; + +import javax.inject.Inject; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.HttpHeaders; + +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.producer.Configurable; +import fr.lirmm.aren.security.token.AuthenticationTokenService; +import fr.lirmm.aren.service.CasAuthentificationService; +import java.net.MalformedURLException; +import java.net.URL; +import javax.servlet.http.Cookie; + +/** + * + * @author Florent Descroix {@literal } + */ +@WebServlet(name = "CasLogin", urlPatterns = {"/caslogin"}) +public class CasLogin extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = 1063853970050165333L; + + @Inject + private CasAuthentificationService casService; + + @Inject + private AuthenticationTokenService authenticationTokenService; + + @Inject + @Configurable("reverse-proxy") + private String proxyUrl; + + /** + * Handles the HTTP GET method. + * + * @param request servlet request + * @param response servlet response + * @throws java.io.IOException + * @throws javax.servlet.ServletException + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + + if (request.getParameter("ticket") != null) { + User user = null; + user = casService.getUserWithTicket(request.getParameter("ticket")); + String token = authenticationTokenService.issueToken(user); + + int maxAge = 360 * 24 * 60 * 60; + + String domain; + try { + domain = new URL(request.getRequestURL().toString()).getHost(); + Cookie cookie = new Cookie(HttpHeaders.AUTHORIZATION, token); + cookie.setComment("Authentification token for Aren platform"); + cookie.setDomain(domain); + cookie.setPath("/"); + cookie.setMaxAge(maxAge); + cookie.setSecure(false); + cookie.setHttpOnly(true); + response.addCookie(cookie); + } catch (MalformedURLException ex) { + } + if (proxyUrl.isEmpty()) { + response.sendRedirect("/"); + } else { + response.sendRedirect(proxyUrl); + } + } else { + response.sendRedirect(casService.getRedirectionUrl()); + } + } + + /** + * Handles the HTTP POST method. + * + * @param request servlet request + * @param response servlet response + * @throws ServletException if a servlet-specific error occurs + * @throws IOException if an I/O error occurs + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + } + + /** + * Returns a short description of the servlet. + * + * @return a String containing servlet description + */ + @Override + public String getServletInfo() { + return "Short description"; + } + +} diff --git a/src/main/java/fr/lirmm/aren/servlet/Root.java b/src/main/java/fr/lirmm/aren/servlet/Root.java new file mode 100644 index 0000000..99ecfd8 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/servlet/Root.java @@ -0,0 +1,58 @@ +package fr.lirmm.aren.servlet; + +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; + +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Florent Descroix {@literal } + */ +@WebFilter(asyncSupported = true, urlPatterns = {"/*"}) +public class Root implements Filter { + + /** + * + * @param filterConfig + * @throws ServletException + */ + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + /** + * + * @param req + * @param res + * @param chain + * @throws IOException + * @throws ServletException + */ + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) req; + HttpServletResponse response = (HttpServletResponse) res; + String path = request.getRequestURI().substring(request.getContextPath().length()); + if (!path.startsWith("/caslogin") && !path.startsWith("/ws/") && !path.startsWith("/assets/")) { + request.getRequestDispatcher("/index.jsp").forward(request, response); + } else { + chain.doFilter(request, response); + } + } + + /** + * + */ + @Override + public void destroy() { + } + +} diff --git a/src/main/java/fr/lirmm/aren/ws/ApiDefinition.java b/src/main/java/fr/lirmm/aren/ws/ApiDefinition.java new file mode 100644 index 0000000..d0190e9 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/ApiDefinition.java @@ -0,0 +1,52 @@ +package fr.lirmm.aren.ws; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.info.License; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.security.SecuritySchemes; + +/** + * + * @author florent + */ +@OpenAPIDefinition( + info = @Info( + title = "AREN API", + description = "API for the ARgumentation Et Numérique project", + version = "3.8.0", + license = @License(name = "MIT License", url = "https://github.com/aren-consortium/AREN/blob/master/LICENSE") + ), + security = { + @SecurityRequirement(name = "CookieAuth"), + @SecurityRequirement(name = "BearerAuth"), + @SecurityRequirement(name = "QueryAuth") + } +) +@SecuritySchemes({ + @SecurityScheme( + name = "CookieAuth", + type = SecuritySchemeType.APIKEY, + in = SecuritySchemeIn.COOKIE, + paramName = "Authorization" + ), + @SecurityScheme( + name = "BearerAuth", + type = SecuritySchemeType.APIKEY, + in = SecuritySchemeIn.HEADER, + paramName = "Authorization", + description = "Bearer {key}" + ), + @SecurityScheme( + name = "QueryAuth", + type = SecuritySchemeType.APIKEY, + in = SecuritySchemeIn.QUERY, + paramName = "token" + )} +) +public interface ApiDefinition { + +} diff --git a/src/main/java/fr/lirmm/aren/ws/JerseyConfig.java b/src/main/java/fr/lirmm/aren/ws/JerseyConfig.java new file mode 100644 index 0000000..40927b0 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/JerseyConfig.java @@ -0,0 +1,39 @@ +package fr.lirmm.aren.ws; + +import io.swagger.v3.jaxrs2.SwaggerSerializers; +import io.swagger.v3.jaxrs2.integration.resources.AcceptHeaderOpenApiResource; +import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource; +import javax.ws.rs.ApplicationPath; + +import org.glassfish.jersey.media.multipart.MultiPartFeature; +import org.glassfish.jersey.server.ResourceConfig; + +/** + * Jersey configuration class. + * + * @author Florent Descroix {@literal } + */ +@ApplicationPath("ws") +public class JerseyConfig extends ResourceConfig { + + /** + * + */ + public JerseyConfig() { + + packages("fr.lirmm.aren.ws.rest"); + + packages("fr.lirmm.aren.ws.filter"); + + packages("fr.lirmm.aren.ws.exceptionmapper"); + + register(ObjectMapperProvider.class); + + register(MultiPartFeature.class); + + register(AcceptHeaderOpenApiResource.class); + register(OpenApiResource.class); + register(SwaggerSerializers.class); + } + +} diff --git a/src/main/java/fr/lirmm/aren/ws/ObjectMapperProvider.java b/src/main/java/fr/lirmm/aren/ws/ObjectMapperProvider.java new file mode 100644 index 0000000..e4e08e7 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/ObjectMapperProvider.java @@ -0,0 +1,64 @@ +package fr.lirmm.aren.ws; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.Provider; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; + +/** + * JAX-RS provider for {@link ObjectMapper}. + * + * @author Florent Descroix {@literal } + */ +@Provider +public class ObjectMapperProvider implements ContextResolver { + + private final ObjectMapper mapper; + + /** + * + */ + public ObjectMapperProvider() { + mapper = createObjectMapper(); + } + + /** + * + * @param type + * @return + */ + @Override + public ObjectMapper getContext(Class type) { + + return mapper; + } + + private static ObjectMapper createObjectMapper() { + + ObjectMapper mapper = new ObjectMapper(); + + mapper.registerModule(new Jdk8Module()); + mapper.registerModule(new JavaTimeModule()); + mapper.registerModule(new ParameterNamesModule()); + + mapper.registerModule(new Hibernate5Module()); + + mapper.enable(SerializationFeature.INDENT_OUTPUT); + mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); + + mapper.setSerializationInclusion(Include.NON_NULL); + + return mapper; + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/exceptionmapper/AbstractExceptionMapper.java b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/AbstractExceptionMapper.java new file mode 100644 index 0000000..f54f93c --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/AbstractExceptionMapper.java @@ -0,0 +1,53 @@ +package fr.lirmm.aren.ws.exceptionmapper; + +import fr.lirmm.aren.exception.AbstractException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import fr.lirmm.aren.exception.AccessDeniedException; +import fr.lirmm.aren.model.ws.ApiErrorDetails; + +/** + * Exception mapper for {@link AccessDeniedException}s. + * + * @author Florent Descroix {@literal } + */ +@Provider +abstract class AbstractExceptionMapper implements ExceptionMapper { + + @Context + private UriInfo uriInfo; + + protected abstract Status getStatus(); + + protected abstract String getTitle(); + + /** + * + * @param exception + * @return + */ + @Override + public Response toResponse(T exception) { + + ApiErrorDetails errorDetails = new ApiErrorDetails(); + + errorDetails.setPath(uriInfo.getAbsolutePath().getPath()); + + errorDetails.setStatus(this.getStatus().getStatusCode()); + errorDetails.setTitle(this.getTitle()); + + errorDetails.setMessage(exception.getMessage()); + + if (exception instanceof AbstractException) { + errorDetails.setDetails(((AbstractException) exception).getDetails()); + } + + return Response.status(this.getStatus().getStatusCode()).entity(errorDetails).type(MediaType.APPLICATION_JSON).build(); + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/exceptionmapper/AccessDeniedExceptionMapper.java b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/AccessDeniedExceptionMapper.java new file mode 100644 index 0000000..4405795 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/AccessDeniedExceptionMapper.java @@ -0,0 +1,33 @@ +package fr.lirmm.aren.ws.exceptionmapper; + +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.Provider; + +import fr.lirmm.aren.exception.AccessDeniedException; + +/** + * Exception mapper for {@link AccessDeniedException}s. + * + * @author Florent Descroix {@literal } + */ +@Provider +public class AccessDeniedExceptionMapper extends AbstractExceptionMapper { + + /** + * + * @return + */ + @Override + protected Status getStatus() { + return Status.FORBIDDEN; + } + + /** + * + * @return + */ + @Override + protected String getTitle() { + return "Access denied"; + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/exceptionmapper/AuthenticationExceptionMapper.java b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/AuthenticationExceptionMapper.java new file mode 100644 index 0000000..6bd4d9c --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/AuthenticationExceptionMapper.java @@ -0,0 +1,33 @@ +package fr.lirmm.aren.ws.exceptionmapper; + +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.Provider; + +import fr.lirmm.aren.exception.AuthenticationException; + +/** + * Exception mapper for {@link AuthenticationException}s. + * + * @author Florent Descroix {@literal } + */ +@Provider +public class AuthenticationExceptionMapper extends AbstractExceptionMapper { + + /** + * + * @return + */ + @Override + protected Status getStatus() { + return Status.UNAUTHORIZED; + } + + /** + * + * @return + */ + @Override + protected String getTitle() { + return "Authentication error"; + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/exceptionmapper/InsertEntityExceptionMapper.java b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/InsertEntityExceptionMapper.java new file mode 100644 index 0000000..c2a11d3 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/InsertEntityExceptionMapper.java @@ -0,0 +1,33 @@ +package fr.lirmm.aren.ws.exceptionmapper; + +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.Provider; + +import fr.lirmm.aren.exception.InsertEntityException; + +/** + * Exception mapper for {@link InsertEntityExceptionMapper}s. + * + * @author Florent Descroix {@literal } + */ +@Provider +public class InsertEntityExceptionMapper extends AbstractExceptionMapper { + + /** + * + * @return + */ + @Override + protected Status getStatus() { + return Status.BAD_REQUEST; + } + + /** + * + * @return + */ + @Override + protected String getTitle() { + return "Insertion error"; + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/exceptionmapper/InvalidAuthenticationTokenExceptionMapper.java b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/InvalidAuthenticationTokenExceptionMapper.java new file mode 100644 index 0000000..4424727 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/InvalidAuthenticationTokenExceptionMapper.java @@ -0,0 +1,33 @@ +package fr.lirmm.aren.ws.exceptionmapper; + +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.Provider; + +import fr.lirmm.aren.exception.InvalidAuthenticationTokenException; + +/** + * Exception mapper for {@link InvalidAuthenticationTokenExceptionMapper}s. + * + * @author Florent Descroix {@literal } + */ +@Provider +public class InvalidAuthenticationTokenExceptionMapper extends AbstractExceptionMapper { + + /** + * + * @return + */ + @Override + protected Status getStatus() { + return Status.UNAUTHORIZED; + } + + /** + * + * @return + */ + @Override + protected String getTitle() { + return "Invalid token"; + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/exceptionmapper/NotFoundExceptionMapper.java b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/NotFoundExceptionMapper.java new file mode 100644 index 0000000..029218c --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/exceptionmapper/NotFoundExceptionMapper.java @@ -0,0 +1,34 @@ +package fr.lirmm.aren.ws.exceptionmapper; + +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.Provider; + +import fr.lirmm.aren.exception.AccessDeniedException; +import javax.ws.rs.NotFoundException; + +/** + * Exception mapper for {@link AccessDeniedException}s. + * + * @author Florent Descroix {@literal } + */ +@Provider +public class NotFoundExceptionMapper extends AbstractExceptionMapper { + + /** + * + * @return + */ + @Override + protected Status getStatus() { + return Status.NOT_FOUND; + } + + /** + * + * @return + */ + @Override + protected String getTitle() { + return "Resource not found"; + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/filter/AuthenticationFilter.java b/src/main/java/fr/lirmm/aren/ws/filter/AuthenticationFilter.java new file mode 100644 index 0000000..e542952 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/filter/AuthenticationFilter.java @@ -0,0 +1,112 @@ +package fr.lirmm.aren.ws.filter; + +import java.io.IOException; +import java.util.List; + +import javax.annotation.Priority; +import javax.enterprise.context.Dependent; +import javax.inject.Inject; +import javax.ws.rs.Priorities; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.SecurityContext; +import javax.ws.rs.ext.Provider; + +import fr.lirmm.aren.exception.InvalidAuthenticationTokenException; +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.security.AuthenticatedUserDetails; +import fr.lirmm.aren.security.TokenBasedSecurityContext; +import fr.lirmm.aren.security.token.AuthenticationTokenDetails; +import fr.lirmm.aren.security.token.AuthenticationTokenService; +import fr.lirmm.aren.service.UserService; +import java.lang.reflect.Method; +import javax.annotation.security.PermitAll; +import javax.ws.rs.container.ResourceInfo; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Cookie; + +/** + * Authentication filter. Populate the Security Context with the right user + * + * @author Florent Descroix {@literal } + */ +@Provider +@Dependent +@Priority(Priorities.AUTHENTICATION) +public class AuthenticationFilter implements ContainerRequestFilter { + + @Inject + private UserService userService; + + @Inject + private AuthenticationTokenService authenticationTokenService; + + @Context + private ResourceInfo resourceInfo; + + /** + * + * @param requestContext + * @throws IOException + */ + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + + Method method = resourceInfo.getResourceMethod(); + if (!method.isAnnotationPresent(PermitAll.class)) { + + // Token parameter authentification + List authorizationPathParam = requestContext.getUriInfo().getQueryParameters().get("token"); + if (authorizationPathParam != null) { + String authenticationToken = authorizationPathParam.get(0); + handleTokenBasedAuthentication(authenticationToken, requestContext); + return; + } + + // Authorization header authentification + String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION); + if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { + String authenticationToken = authorizationHeader.substring(7); + handleTokenBasedAuthentication(authenticationToken, requestContext); + return; + } + + // Authorization cookie authentification + for (Cookie c : requestContext.getCookies().values()) { + if (c.getName().equals("Authorization")) { + handleTokenBasedAuthentication(c.getValue(), requestContext); + return; + } + } + + // Authentificate as guest + AuthenticatedUserDetails authenticatedUserDetails = new AuthenticatedUserDetails(new User()); + boolean isSecure = requestContext.getSecurityContext().isSecure(); + SecurityContext securityContext = new TokenBasedSecurityContext(authenticatedUserDetails, null, isSecure); + requestContext.setSecurityContext(securityContext); + + // CAS authentification + // Other authentication schemes (such as Basic) could be supported + } + } + + private void handleTokenBasedAuthentication(String authenticationToken, ContainerRequestContext requestContext) { + + AuthenticationTokenDetails authenticationTokenDetails = authenticationTokenService.parseToken(authenticationToken); + User user = userService.findByUsernameOrEmail(authenticationTokenDetails.getUsername()); + if (user == null) { + throw InvalidAuthenticationTokenException.INVALID_TOKEN(); + } + if (user.getTokenValidity().isAfter(authenticationTokenDetails.getIssuedDate())) { + throw InvalidAuthenticationTokenException.EXPIRED_TOKEN(); + } + + // userService.updateLastLogin(user); + AuthenticatedUserDetails authenticatedUserDetails = new AuthenticatedUserDetails(user); + + boolean isSecure = requestContext.getSecurityContext().isSecure(); + SecurityContext securityContext = new TokenBasedSecurityContext(authenticatedUserDetails, authenticationTokenDetails, isSecure); + requestContext.setSecurityContext(securityContext); + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/filter/AuthorizationFilter.java b/src/main/java/fr/lirmm/aren/ws/filter/AuthorizationFilter.java new file mode 100644 index 0000000..db2c23e --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/filter/AuthorizationFilter.java @@ -0,0 +1,111 @@ +package fr.lirmm.aren.ws.filter; + +import java.io.IOException; +import java.lang.reflect.Method; + +import javax.annotation.Priority; +import javax.annotation.security.DenyAll; +import javax.annotation.security.PermitAll; +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.Dependent; +import javax.ws.rs.Priorities; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ResourceInfo; +import javax.ws.rs.core.Context; +import javax.ws.rs.ext.Provider; + +import fr.lirmm.aren.exception.AccessDeniedException; +import fr.lirmm.aren.exception.AuthenticationException; + +/** + * Role authorization filter. Check if a function is accessible by User Role + * + * @author Florent Descroix {@literal } + */ +@Provider +@Dependent +@Priority(Priorities.AUTHORIZATION) +public class AuthorizationFilter implements ContainerRequestFilter { + + @Context + private ResourceInfo resourceInfo; + + /** + * + * @param requestContext + * @throws IOException + */ + @Override + public void filter(final ContainerRequestContext requestContext) throws IOException { + + Method method = resourceInfo.getResourceMethod(); + + // @DenyAll on the method takes precedence over @RolesAllowed and @PermitAll + if (method.isAnnotationPresent(DenyAll.class)) { + throw AccessDeniedException.PERMISSION_MISSING(); + } + + // @RolesAllowed on the method takes precedence over @PermitAll + RolesAllowed rolesAllowed = method.getAnnotation(RolesAllowed.class); + if (rolesAllowed != null) { + performAuthorization(rolesAllowed.value(), requestContext); + return; + } + + // @PermitAll on the method takes precedence over @RolesAllowed on the class + if (method.isAnnotationPresent(PermitAll.class)) { + // Do nothing + return; + } + + // @DenyAll can't be attached to classes + // @RolesAllowed on the class takes precedence over @PermitAll on the class + rolesAllowed = resourceInfo.getResourceClass().getAnnotation(RolesAllowed.class); + if (rolesAllowed != null) { + performAuthorization(rolesAllowed.value(), requestContext); + } + + // @PermitAll on the class + if (resourceInfo.getResourceClass().isAnnotationPresent(PermitAll.class)) { + // Do nothing + return; + } + + // Authentication is required for non-annotated methods + if (!isAuthenticated(requestContext)) { + throw AuthenticationException.AUTHENTIFICATION_REQUIRED(); + } + } + + /** + * Perform authorization based on roles. + * + * @param rolesAllowed + * @param requestContext + */ + private void performAuthorization(String[] rolesAllowed, ContainerRequestContext requestContext) { + + if (rolesAllowed.length > 0 && !isAuthenticated(requestContext)) { + throw AuthenticationException.AUTHENTIFICATION_REQUIRED(); + } + + for (final String role : rolesAllowed) { + if (requestContext.getSecurityContext().isUserInRole(role)) { + return; + } + } + + throw AccessDeniedException.PERMISSION_MISSING(); + } + + /** + * Check if the user is authenticated. + * + * @param requestContext + * @return + */ + private boolean isAuthenticated(final ContainerRequestContext requestContext) { + return requestContext.getSecurityContext().getUserPrincipal() != null; + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/ACalendarRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/ACalendarRESTFacade.java new file mode 100644 index 0000000..cf92b74 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/ACalendarRESTFacade.java @@ -0,0 +1,50 @@ +package fr.lirmm.aren.ws.rest; + +import fr.lirmm.aren.model.agenda.ACalendar; +import fr.lirmm.aren.service.agenda.ACalendarService; + +import javax.annotation.security.PermitAll; +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.Path; +import java.util.Set; + +@RequestScoped +@Path("agenda/calendars") +public class ACalendarRESTFacade extends AbstractRESTFacade{ + @Inject + private ACalendarService aCalendarService ; + @Override + protected ACalendarService getService(){return aCalendarService ;} + + @Override + //@RolesAllowed({"ADMIN"}) + @PermitAll + public ACalendar create(ACalendar aCalendar){return super.create(aCalendar);} + + @Override + @RolesAllowed({"ADMIN"}) + public ACalendar edit(Long id,ACalendar aCalendar){return super.edit(id,aCalendar);} + + @Override + @RolesAllowed({"ADMIN"}) + public void remove(Long id) { + super.remove(id); + } + + @Override + @PermitAll + //@RolesAllowed({"MODO"}) + public Set findAll() { + return aCalendarService.findAll(); + } + + @Override + //@RolesAllowed({"MODO"}) + @PermitAll + public ACalendar find(Long id) { + ACalendar aCalendar = aCalendarService.find(id); + return aCalendar; + } +} \ No newline at end of file diff --git a/src/main/java/fr/lirmm/aren/ws/rest/AafRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/AafRESTFacade.java new file mode 100644 index 0000000..6557739 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/AafRESTFacade.java @@ -0,0 +1,117 @@ +package fr.lirmm.aren.ws.rest; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; + +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.servlet.ServletContext; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.sse.Sse; +import javax.ws.rs.sse.SseEventSink; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.FormDataParam; + +import fr.lirmm.aren.service.AAFImportService; +import fr.lirmm.aren.ws.ObjectMapperProvider; +import javax.ws.rs.core.MediaType; + +/** + * JAX-RS resource class for AAF import + * + * @author Florent Descroix {@literal } + */ +@RequestScoped +@Path("aaf") +public class AafRESTFacade { + + @Inject + private AAFImportService aafService; + + @Context + private ServletContext servletContext; + + @Context + private ObjectMapperProvider mapperProvider; + + @Context + private Sse sse; + + /** + * Import datas from an AAF export file (FicAlimMENESR) Create Institutions, + * Teams and Users + * + * @param uploadedInputStream + * @param fileDetail + * @param eventSink + */ + @POST + @Path("import") + @RolesAllowed({"ADMIN"}) + @Produces(MediaType.SERVER_SENT_EVENTS) + public void importAaf( + @FormDataParam("file") InputStream uploadedInputStream, + @FormDataParam("file") FormDataContentDisposition fileDetail, + @Context SseEventSink eventSink) { + + String realPath = servletContext.getRealPath(""); + String uploadedFileLocation = realPath + "/WEB-INF/AafImport/" + fileDetail.getFileName(); + writeToFile(uploadedInputStream, uploadedFileLocation); + + aafService.setDispatcher((Float progress) -> { + eventSink.send(sse.newEvent(progress + "")); + }); + File file = new File(uploadedFileLocation); + List output = aafService.proceedImportation(file); + //eventSink.send(sse.newEvent(parseMessage(output))); + eventSink.send(sse.newEvent("1")); + eventSink.close(); + file.delete(); + } + + private String parseMessage(List arrayOfString) { + + ObjectMapper mapper = mapperProvider.getContext(null); + + String json = ""; + try { + json = mapper.writeValueAsString(arrayOfString); + } catch (JsonProcessingException ex) { + System.err.println("Message impossible to parse"); + } + return json; + } + + private void writeToFile(InputStream uploadedInputStream, + String uploadedFileLocation) { + + try { + OutputStream out = new FileOutputStream(new File(uploadedFileLocation)); + int read = 0; + byte[] bytes = new byte[1024]; + + out = new FileOutputStream(new File(uploadedFileLocation)); + while ((read = uploadedInputStream.read(bytes)) != -1) { + out.write(bytes, 0, read); + } + out.flush(); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/AbstractRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/AbstractRESTFacade.java new file mode 100644 index 0000000..b77a4f9 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/AbstractRESTFacade.java @@ -0,0 +1,203 @@ +package fr.lirmm.aren.ws.rest; + +import javax.annotation.security.RolesAllowed; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.SecurityContext; + +import fr.lirmm.aren.service.AbstractService; +import fr.lirmm.aren.exception.AccessDeniedException; +import fr.lirmm.aren.model.AbstractDatedEntity; +import fr.lirmm.aren.model.AbstractEntEntity; +import fr.lirmm.aren.model.AbstractEntity; +import fr.lirmm.aren.model.AbstractOwnedEntity; +import fr.lirmm.aren.model.Notification; +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.security.AuthenticatedUserDetails; + +import java.time.ZonedDateTime; +import java.util.Set; +import javax.servlet.http.HttpServletRequest; + +/** + * JAX-RS resource class for Abstract Model objects + * + * @author Florent Descroix {@literal } + * @param + */ + + +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public abstract class AbstractRESTFacade { + + /** + * + */ + @Context + protected SecurityContext securityContext; + + /** + * + */ + @Context + protected HttpServletRequest request; + + /** + * + */ + @QueryParam("overview") + protected String overview; + + /** + * + * @return + */ + protected abstract AbstractService getService(); + + /** + * + * @return the authentificated user + */ + protected User getUser() { + return ((AuthenticatedUserDetails) securityContext.getUserPrincipal()).getUser(); + } + + /** + * + * @param entity + */ + protected void safetyPreInsertion(T entity) { + if (entity instanceof AbstractOwnedEntity && !(entity instanceof Notification)) { + if (!getUser().is("SUPERADMIN") || ((AbstractOwnedEntity) entity).getOwner() == null) { + ((AbstractOwnedEntity) entity).setOwner(getUser()); + } + } + if (entity instanceof AbstractDatedEntity) { + if (!getUser().is("SUPERADMIN") || ((AbstractDatedEntity) entity).getCreated() == null) { + ((AbstractDatedEntity) entity).setCreated(ZonedDateTime.now()); + } + } + if (entity instanceof AbstractEntEntity) { + if (!getUser().is("SUPERADMIN") || ((AbstractEntEntity) entity).getEntId() == null) { + ((AbstractEntEntity) entity).setEntId(null); + } + } + } + + /** + * + * @param entity + * @param entityToEdit + */ + protected void safetyPreEdition(T entity, T entityToEdit) { + if (!getUser().is("SUPERADMIN")) { + if (!entityToEdit.isEditable()) { + throw AccessDeniedException.UNMUTABLE_OBJECT(entity.getClass(), entityToEdit.getId()); + } + if (entity instanceof AbstractOwnedEntity && !(entity instanceof Notification)) { + ((AbstractOwnedEntity) entity).setOwner(null); + } + if (entity instanceof AbstractDatedEntity) { + ((AbstractDatedEntity) entity).setCreated(null); + } + if (entity instanceof AbstractEntEntity) { + ((AbstractEntEntity) entity).setEntId(null); + } + } + } + + /** + * + * @param entity + */ + protected void safetyPreDeletion(T entity) { + if (!getUser().is("SUPERADMIN")) { + if (!entity.isRemovable()) { + throw AccessDeniedException.UNERASABLE_OBJECT(entity.getClass(), entity.getId()); + } + } + } + + /** + * Create a new Entity + * + * @param entity to create + * @return then create Entity + */ + @POST + @RolesAllowed({"SUPERADMIN"}) + public T create(T entity) { + safetyPreInsertion(entity); + getService().create(entity); + return entity; + } + + /** + * Edit the Entity fetch by the first parameter with the content of the + * second parameter. Null fields are ignored + * + * @param id of the Entity to update + * @param entity values to update + * @return the updated Entity + */ + @PUT + @Path("{id}") + @RolesAllowed({"SUPERADMIN"}) + public T edit(@PathParam("id") Long id, T entity) { + T entityToEdit = find(id); + safetyPreEdition(entity, entityToEdit); + entityToEdit.merge(entity); + getService().edit(entityToEdit); + return entityToEdit; + } + + /** + * Remove the Entity fetched by the first parameter + * + * @param id of the Entity to remove + */ + @DELETE + @Path("{id}") + @RolesAllowed({"SUPERADMIN"}) + public void remove(@PathParam("id") Long id) { + T entity = find(id); + safetyPreDeletion(entity); + getService().remove(entity); + } + + /** + * Fetch the Entity by id + * + * @param id of the Entity to fetch + * @return an Entity + */ + @GET + @Path("{id}") + @RolesAllowed({"SUPERADMIN"}) + public T find(@PathParam("id") Long id) { + + return getService().find(id); + } + + /** + * Fetch all the entity of the givent type + * + * @return a set of entity + */ + @GET + @RolesAllowed({"SUPERADMIN"}) + public Set findAll() { + + return getService().findAll(); + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/BroadcasterRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/BroadcasterRESTFacade.java new file mode 100644 index 0000000..1140a99 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/BroadcasterRESTFacade.java @@ -0,0 +1,92 @@ +package fr.lirmm.aren.ws.rest; + +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.SecurityContext; + +import fr.lirmm.aren.service.BroadcasterService; +import fr.lirmm.aren.model.Debate; +import fr.lirmm.aren.model.Notification; +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.security.AuthenticatedUserDetails; +import fr.lirmm.aren.service.DebateService; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.sse.SseEventSink; + +/** + * JAX-RS resource class for Server Sent Event + * + * @author Florent Descroix {@literal } + */ +@ApplicationScoped +@Path("events") +@Produces(MediaType.SERVER_SENT_EVENTS) +public class BroadcasterRESTFacade { + + @Inject + private DebateService debateService; + + @Inject + private BroadcasterService broadcasterService; + + /** + * + */ + @Context + protected SecurityContext securityContext; + + /** + * + * @return + */ + protected User getUser() { + return ((AuthenticatedUserDetails) securityContext.getUserPrincipal()).getUser(); + } + + /** + * Listen to all the new created Comments + * + * @param sseEventSink + */ + @GET + @Path("comments") + @RolesAllowed({"ADMIN"}) + public void openDebatesListener(@Context SseEventSink sseEventSink) { + + broadcasterService.openListener(-1L, Debate.class, sseEventSink); + } + + /** + * Listen to the new created Comments on a specific Debate + * + * @param debateId of the Debate to be listen to + * @param sseEventSink + */ + @GET + @Path("comments/{debateId}") + @RolesAllowed({"GUEST"}) + public void openDebateListener(@PathParam("debateId") Long debateId, @Context SseEventSink sseEventSink) { + + debateService.findByUser(debateId, getUser(), false, false, false, false, false); + broadcasterService.openListener(debateId, Debate.class, sseEventSink); + } + + /** + * Listen to the new created Notifications of the current User + * + * @param sseEventSink + */ + @GET + @Path("notifications") + @RolesAllowed({"USER"}) + public void openNotificationListener(@Context SseEventSink sseEventSink) { + + broadcasterService.openListener(getUser().getId(), Notification.class, sseEventSink); + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/CategoryRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/CategoryRESTFacade.java new file mode 100644 index 0000000..168fc81 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/CategoryRESTFacade.java @@ -0,0 +1,83 @@ +package fr.lirmm.aren.ws.rest; + +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.Path; + +import fr.lirmm.aren.service.CategoryService; +import fr.lirmm.aren.model.Category; +import java.util.HashSet; + +/** + * JAX-RS resource class for Categories managment + * + * @author Florent Descroix {@literal } + */ +@RequestScoped +@Path("categories") +public class CategoryRESTFacade extends AbstractRESTFacade { + + @Inject + private CategoryService categoryService; + + /** + * + * @return + */ + @Override + protected CategoryService getService() { + return categoryService; + } + + /** + * + * @param category + * @return + */ + @Override + @RolesAllowed({"MODO"}) + public Category create(Category category) { + return super.create(category); + } + + /** + * + * @param category + * @return + */ + @Override + @RolesAllowed({"MODO"}) + public Category edit(Long id, Category category) { + return super.edit(id, category); + } + + /** + * + * @return + */ + @Override + @RolesAllowed({"GUEST"}) + public HashSet findAll() { + boolean withDocument = false; + if (getUser().is("MODO")) { + withDocument = this.overview == null; + } + return categoryService.findAllByUser(getUser(), withDocument); + } + + /** + * + * @param id + * @return + */ + @Override + @RolesAllowed({"GUEST"}) + public Category find(Long id) { + boolean withDocument = false; + if (getUser().is("MODO")) { + withDocument = this.overview == null; + } + return categoryService.findByUser(id, getUser(), withDocument); + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/CommentRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/CommentRESTFacade.java new file mode 100644 index 0000000..bffdcdc --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/CommentRESTFacade.java @@ -0,0 +1,130 @@ +package fr.lirmm.aren.ws.rest; + +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +import fr.lirmm.aren.service.CommentService; +import fr.lirmm.aren.model.Comment; +import fr.lirmm.aren.model.TagSet; +import fr.lirmm.aren.service.BroadcasterService; +import fr.lirmm.aren.service.HttpRequestService; +import javax.ws.rs.PUT; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.sse.Sse; +import javax.ws.rs.sse.SseEventSink; + +/** + * JAX-RS resource class for Comments managment + * + * @author Florent Descroix {@literal } + */ +@RequestScoped +@Path("comments") +public class CommentRESTFacade extends AbstractRESTFacade { + + @Inject + private CommentService commentService; + + @Inject + private BroadcasterService broadcasterService; + + @Inject + private HttpRequestService httpRequestService; + + /** + * + * @return + */ + @Override + protected CommentService getService() { + return commentService; + } + + /** + * + * @param id + * @param comment + * @return + */ + @Override + @RolesAllowed({"USER"}) + public Comment edit(Long id, Comment comment) { + Comment toEdit = find(id); + safetyPreEdition(comment, toEdit); + + boolean sameProposedTags = comment.getProposedTags().equals(toEdit.getProposedTags()); + boolean sameText = comment.getReformulation().equals(toEdit.getReformulation()); + + if (!getUser().is("SUPERADMIN") && !sameProposedTags) { + toEdit.setProposedTags(comment.getProposedTags()); + } else if (getUser().is("SUPERADMIN")) { + toEdit.merge(comment); + } + + if (!sameProposedTags || !sameText) { + // Reinit tags + toEdit.setTags(new TagSet()); + } + commentService.edit(toEdit); + + if (!sameProposedTags || !sameText) { + broadcasterService.broadcastComment(toEdit); + commentService.updateTags(toEdit); + } + broadcasterService.broadcastComment(toEdit); + return toEdit; + } + + /** + * Get the scalar corespondance weight between the Comment's selection and + * the Comment's argumentation Use a remote service + * + * @param comment to proceed + * @return + */ + @POST + @Path("scalar") + @RolesAllowed({"GUEST"}) + public String getScalar(Comment comment) { + return httpRequestService.getScalar(comment); + } + + /** + * Update tags of all comments Use a remote service + * + */ + @PUT + @Path("updateTags") + @RolesAllowed({"ADMIN"}) + @Produces(MediaType.SERVER_SENT_EVENTS) + public void updateAllTags(@Context SseEventSink eventSink, @Context Sse sse) { + commentService.updateAllTags((Comment comment, Float progress) -> { + eventSink.send(sse.newEvent(progress + "")); + broadcasterService.broadcastComment(comment); + }); + eventSink.send(sse.newEvent("1")); + eventSink.close(); + } + + /** + * Update Tags of a single Comment Use a remote servie + * + * @param id of the Comment to update the Tags + * @return + */ + @PUT + @Path("{id}/updateTags") + @RolesAllowed({"ADMIN"}) + public TagSet updateTag(@PathParam("id") Long id) { + Comment comment = commentService.find(id); + commentService.updateTags(comment); + broadcasterService.broadcastComment(comment); + return comment.getTags(); + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/DebateRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/DebateRESTFacade.java new file mode 100644 index 0000000..04d0987 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/DebateRESTFacade.java @@ -0,0 +1,501 @@ +package fr.lirmm.aren.ws.rest; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.DELETE; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; + +import fr.lirmm.aren.service.BroadcasterService; +import fr.lirmm.aren.service.CommentService; +import fr.lirmm.aren.service.DebateService; +import fr.lirmm.aren.service.NotificationService; +import fr.lirmm.aren.service.TeamService; +import fr.lirmm.aren.service.UserService; +import fr.lirmm.aren.exception.InsertEntityException; +import fr.lirmm.aren.model.Comment; +import fr.lirmm.aren.model.Debate; +import fr.lirmm.aren.model.Notification; +import fr.lirmm.aren.model.Team; +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.model.ws.Scrap; +import fr.lirmm.aren.service.HttpRequestService; +import fr.lirmm.aren.service.ODFService; +import java.io.File; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +/** + * JAX-RS resource class for Debates managment + * + * @author Florent Descroix {@literal } + */ +@RequestScoped +@Path("debates") +public class DebateRESTFacade extends AbstractRESTFacade { + + @Inject + private DebateService debateService; + + @Inject + private NotificationService notificationService; + + @Inject + private CommentService commentService; + + @Inject + private CommentRESTFacade commentFacade; + + @Inject + private BroadcasterService broadcasterService; + + @Inject + private TeamService teamService; + + @Inject + private UserService userService; + + @Inject + private ODFService odfService; + + @Inject + private HttpRequestService httpRequestService; + + /** + * + */ + @QueryParam("category") + protected Long category; + + /** + * + * @return + */ + @Override + protected DebateService getService() { + return debateService; + } + + /** + * + * @return + */ + @Override + @RolesAllowed({"GUEST"}) + public Set findAll() { + boolean withComments = (this.overview == null); + boolean isModo = getUser().is("MODO"); + return debateService.findAllByUser(getUser(), category, true, withComments, isModo, isModo, false); + } + + /** + * + * @param id + * @return + */ + @Override + @RolesAllowed({"GUEST"}) + public Debate find(Long id) { + + boolean withComments = (this.overview == null); + return debateService.findByUser(id, getUser(), true, withComments, true, true, false); + } + + /** + * + * @param debate + * @return + */ + @Override + @RolesAllowed({"MODO"}) + public Debate create(Debate debate) { + Set teams = debate.getTeams(); + Set guests = debate.getGuests(); + super.create(debate); + debate.getTeams().addAll(teams); + debate.getGuests().addAll(guests); + debateService.edit(debate); + + Debate newDebate = debateService.find(debate.getId(), false, false, true, true, true); + + List notifications = new ArrayList(); + + newDebate.getTeams().forEach((Team team) -> { + team.getUsers().forEach((User user) -> { + notifications.add(Notification.TEAM_ADDED_TO_DEBATE(user, newDebate, team)); + }); + }); + + newDebate.getGuests().forEach((User user) -> { + notifications.add(Notification.INVITED_TO_DEBATE(user, newDebate)); + }); + + notificationService.create(notifications); + broadcasterService.broadcastNotification(notifications); + + return newDebate; + } + + /** + * + * @param id + */ + @Override + @RolesAllowed({"MODO"}) + public void remove(Long id) { + super.remove(id); + } + + /** + * Creates a new Comment onto a Debate + * + * @param id of the debate + * @param comment to add + * @return + */ + @POST + @Path("{id}/comments") + @RolesAllowed({"USER"}) + public Comment addComment(@PathParam("id") Long id, Comment comment) { + + Debate debate = debateService.findByUser(id, getUser(), false, false, false, false, false); + Comment parent = null; + + if (comment.getParent() != null) { + parent = commentService.getReference(comment.getParent().getId()); + if (!Objects.equals(debate, parent.getDebate())) { + throw InsertEntityException.INVALID_PARENT(); + } + } + + commentFacade.create(comment); + + List notifications = new ArrayList(); + List users = new ArrayList(); + while (parent != null) { + // Only one notification per user + // And not notify oneself + if (!users.contains(parent.getOwner()) && parent.getOwner() != getUser()) { + notifications.add(Notification.COMMENT_ANSWERED(parent.getOwner(), comment)); + users.add(parent.getOwner()); + } + parent = parent.getParent(); + } + + notificationService.create(notifications); + broadcasterService.broadcastNotification(notifications); + broadcasterService.broadcastComment(comment); + + commentService.updateTags(comment); // It is long + broadcasterService.broadcastComment(comment); + + return comment; + } + + /** + * Remove all the comment of a debate + * + * @param id + */ + @DELETE + @Path("{id}/comments") + @RolesAllowed({"ADMIN"}) + public void clear(@PathParam("id") Long id) { + + debateService.clearComments(id); + } + + /** + * Mark a Comment in a Debate as being signaled + * + * @param id of the debate holding the comment + * @param commentId of the comment to be signaled + * @return + */ + @PUT + @Path("{id}/signal/{commentId}") + @RolesAllowed({"USER"}) + public Comment signal(@PathParam("id") Long id, @PathParam("commentId") Long commentId) { + + Debate debate = debateService.findByUser(id, getUser(), false, false, false, false, false); + Comment comment = commentService.find(commentId); + + if (comment.getDebate().equals(debate)) { + + comment.setSignaled(!comment.isSignaled()); + commentService.edit(comment); + + Set guests = debate.getGuests(); + guests.size(); + + List notifications = new ArrayList(); + + guests.forEach((User user) -> { + if (user.is("MODO")) { + notifications.add(Notification.COMMENT_SINGNALED(user, comment)); + } + }); + + notificationService.create(notifications); + broadcasterService.broadcastNotification(notifications); + } + return comment; + } + + /** + * Mark a Comment in a Debate as being moderated + * + * @param id of the debate holding the comment + * @param commentId of the comment to be moderated + * @return + */ + @PUT + @Path("{id}/moderate/{commentId}") + @RolesAllowed({"MODO"}) + public Comment moderate(@PathParam("id") Long id, @PathParam("commentId") Long commentId) { + + debateService.findByUser(id, getUser(), false, false, false, false, false); + + Comment comment = commentService.find(id); + comment.setModerated(!comment.isModerated()); + commentService.edit(comment); + + Notification notif = Notification.COMMENT_MODERATED(comment); + notificationService.create(notif); + broadcasterService.broadcastNotification(notif); + + return comment; + } + + /** + * Add a Team to participate in a Debate + * + * @param id of the debate + * @param teamId of the team + */ + @PUT + @Path("{id}/teams/{teamId}") + @RolesAllowed({"MODO"}) + public void addTeam(@PathParam("id") Long id, @PathParam("teamId") Long teamId) { + + Debate debate = debateService.findByUser(id, getUser(), false, false, true, false, false); + + Team team = teamService.find(teamId); + debate.addTeam(team); + debateService.edit(debate); + + List notifications = new ArrayList(); + + team.getUsers().forEach((User user) -> { + notifications.add(Notification.TEAM_ADDED_TO_DEBATE(user, debate, team)); + }); + + notificationService.create(notifications); + broadcasterService.broadcastNotification(notifications); + + } + + /** + * Remove a Team to participate in a Debate + * + * @param id of the debate + * @param teamId of the team + */ + @DELETE + @Path("{id}/teams/{teamId}") + @RolesAllowed({"MODO"}) + public void removeTeam(@PathParam("id") Long id, @PathParam("teamId") Long teamId) { + + Debate debate = debateService.findByUser(id, getUser(), false, false, true, false, false); + + Team team = teamService.find(teamId); + debate.removeTeam(team); + debateService.edit(debate); + + } + + /** + * Add a User to participate in a Debate + * + * @param id of the debate + * @param userId of the user + */ + @PUT + @Path("{id}/users/{userId}") + @RolesAllowed({"ADMIN", "MODO"}) + public void addGuest(@PathParam("id") Long id, @PathParam("userId") Long userId) { + + Debate debate = debateService.findByUser(id, getUser(), false, false, false, true, false); + + User user = userService.find(userId); + debate.addGuest(user); + debateService.edit(debate); + + Notification notif = Notification.INVITED_TO_DEBATE(user, debate); + notificationService.create(notif); + broadcasterService.broadcastNotification(notif); + } + + /** + * Remove a User to participate in a Debate + * + * @param id of the debate + * @param userId of the user + */ + @DELETE + @Path("{id}/users/{userId}") + @RolesAllowed({"MODO"}) + public void removeGuest(@PathParam("id") Long id, @PathParam("userId") Long userId) { + + Debate debate = debateService.findByUser(id, getUser(), false, false, false, true, false); + + User user = userService.find(userId); + debate.removeGuest(user); + debateService.edit(debate); + } + + /** + * Calculate the intersections of the selections of the Comment of a Debate + * + * @param id of the Debate + * @return a list of Strings + */ + @GET + @Path("{id}/scraps") + @RolesAllowed({"GUEST"}) + public List getScraps(@PathParam("id") Long id) { + Debate debate = this.find(id); + ArrayList scraps = new ArrayList(); + + for (Comment comment : debate.getComments()) { + if (comment.getParent() == null) { + Scrap scrap = new Scrap(); + scrap.setStartContainer(comment.getStartContainer()); + scrap.setStartOffset(comment.getStartOffset()); + scrap.setEndContainer(comment.getEndContainer()); + scrap.setEndOffset(comment.getEndOffset()); + scrap.getComments().add(comment); + scraps.add(scrap); + } + } + + int firstsLen = scraps.size(); + int checkingStart = 0; + int checkingEnd = firstsLen; + // While there are new scraps, test to find new overlaps + while (checkingStart != checkingEnd) { + // For all initial scraps + for (int i = 0; i < firstsLen; i++) { + Scrap s1 = scraps.get(i); + // For all new scraps + for (int j = (checkingStart == 0 ? i + 1 : checkingStart); j < checkingEnd; j++) { + Scrap s2 = scraps.get(j); + int comparison = s1.compareTo(s2); + if (comparison != Scrap.ALL_BEFORE && comparison != Scrap.ALL_AFTER) { + Scrap start = s1; + Scrap end = s1; + // The higest start is the start of the ovelap + if (comparison == Scrap.OVER_BEFORE || comparison == Scrap.COVERS) { + start = s2; + } + // The smalest end is the end of the ovelap + if (comparison == Scrap.OVER_AFTER || comparison == Scrap.COVERS) { + end = s2; + } + // Create the scrap + Scrap scrap = new Scrap(); + scrap.setStartContainer(start.getStartContainer()); + scrap.setStartOffset(start.getStartOffset()); + scrap.setEndContainer(end.getEndContainer()); + scrap.setEndOffset(end.getEndOffset()); + + // Check if the scrap already exists + int k = 0; + while (k < scraps.size() && !scrap.equals(scraps.get(k))) { + k++; + } + + if (k < scraps.size()) { + scrap = scraps.get(k); + } else { + scraps.add(scrap); + } + // Add comments to the new scrap + scrap.getComments().addAll(s1.getComments()); + scrap.getComments().addAll(s2.getComments()); + } + } + } + // Only check scraps inserted in the last loop + checkingStart = checkingEnd; + checkingEnd = scraps.size(); + } + + scraps.sort((Scrap c1, Scrap c2) -> c2.getComments().size() - c1.getComments().size()); + + return scraps; + } + + /** + * Find the Comments of a Debate that match a theme + * + * @param id of the debate + * @param theme + * @return + */ + @GET + @Path("{id}/theme") + @RolesAllowed({"GUEST"}) + public String getTheme(@PathParam("id") Long id, @QueryParam("theme") String theme) { + this.find(id); + return httpRequestService.getTheme(id, theme); + } + + /** + * Update the Tags of all the Comments of a Debate Use a remote service + * + * @param id + */ + @PUT + @Path("{id}/updateTags") + @RolesAllowed({"SUPERADMIN"}) + public void updateTags(@PathParam("id") Long id) { + Debate debate = debateService.findByUser(id, getUser(), false, true, false, false, false); + + debate.getComments().forEach((Comment comment) -> { + commentService.updateTags(comment, true); + broadcasterService.broadcastComment(comment); + }); + } + + /** + * Export a Debate to an ODF file + * + * @param id of the debate + * @return an ODF file + * @throws Exception + */ + @GET + @Path("{id}/export") + @RolesAllowed({"GUEST"}) + @Produces("application/odt") + public Response export(@PathParam("id") Long id) throws Exception { + Debate debate = debateService.findByUser(id, getUser(), true, true, false, false, false); + File export = odfService.parseDebate(debate); + String fileName = debate.getDocument().getName().replaceAll("[^a-zA-Z0-9\\s]", "") + ".odt"; + return Response.ok(export) + .header("Content-disposition", "attachment; filename=\"" + fileName + "\"") + .header("Content-length", export.length()) + .build(); + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/DocumentRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/DocumentRESTFacade.java new file mode 100644 index 0000000..505f095 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/DocumentRESTFacade.java @@ -0,0 +1,84 @@ +package fr.lirmm.aren.ws.rest; + +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import fr.lirmm.aren.service.DocumentService; +import fr.lirmm.aren.model.Document; +import java.util.Set; + +/** + * JAX-RS resource class for Documents managment + * + * @author Florent Descroix {@literal } + */ +@RequestScoped +@Path("documents") +public class DocumentRESTFacade extends AbstractRESTFacade { + + @Inject + private DocumentService documentService; + + /** + * + * @return + */ + @Override + protected DocumentService getService() { + return documentService; + } + + /** + * + * @return + */ + @Override + @RolesAllowed({"MODO"}) + public Set findAll() { + boolean withDebates = this.overview == null; + return documentService.findAll(withDebates); + } + + /** + * + * @param id + * @return + */ + @Override + @RolesAllowed({"MODO"}) + public Document find(Long id) { + boolean withDebates = this.overview == null; + return documentService.find(id, withDebates); + } + + /** + * + * @param id + * @return + */ + @Override + @RolesAllowed({"MODO"}) + public Document create(Document doc) { + return super.create(doc); + } + + /** + * Ducplicate a Documents withe the the associaitons + * + * @param id of the Document to duplicate + * @return the duplicated Document + */ + @POST + @Path("{id}/duplicate") + @RolesAllowed({"MODO"}) + public Document duplicate(@PathParam("id") Long id) { + + Document document = find(id); + + return this.create(document); + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/FDChoiceRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/FDChoiceRESTFacade.java new file mode 100644 index 0000000..95e94c0 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/FDChoiceRESTFacade.java @@ -0,0 +1,63 @@ +package fr.lirmm.aren.ws.rest; + + +import fr.lirmm.aren.model.Category; +import fr.lirmm.aren.model.Institution; +import fr.lirmm.aren.model.framadate.FDChoice; +import fr.lirmm.aren.model.framadate.FDVote; +import fr.lirmm.aren.service.AbstractService; +import fr.lirmm.aren.service.framadate.FDChoiceService; +import fr.lirmm.aren.service.framadate.FDVoteService; + +import javax.annotation.security.PermitAll; +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.Path; +import java.util.HashSet; +import java.util.Set; + +@RequestScoped +@Path("choices") +public class FDChoiceRESTFacade extends AbstractRESTFacade{ + @Inject + private FDChoiceService fdChoiceService ; + + @Inject + private FDVoteService fdVoteService ; + + @Override + protected FDChoiceService getService(){return fdChoiceService ;} + + @Override + //@RolesAllowed({"ADMIN"}) + @PermitAll + public FDChoice create(FDChoice fdChoice){return super.create(fdChoice);} + + @Override + //@RolesAllowed({"ADMIN"}) + public FDChoice edit(Long id,FDChoice fdChoice){return super.edit(id,fdChoice);} + + @Override + @RolesAllowed({"ADMIN"}) + public void remove(Long id) { + super.remove(id); + } + + @Override + @PermitAll + //@RolesAllowed({"MODO"}) + public Set findAll() { + boolean withVotes = this.overview == null; + return fdChoiceService.findAll(withVotes); + } + + @Override + //@RolesAllowed({"MODO"}) + @PermitAll + public FDChoice find(Long id) { + boolean withVotes = this.overview == null; + FDChoice fdChoice = fdChoiceService.find(id,withVotes); + return fdChoice; + } +} \ No newline at end of file diff --git a/src/main/java/fr/lirmm/aren/ws/rest/FDThemeRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/FDThemeRESTFacade.java new file mode 100644 index 0000000..f25dce3 --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/FDThemeRESTFacade.java @@ -0,0 +1,68 @@ +package fr.lirmm.aren.ws.rest; + +import fr.lirmm.aren.model.framadate.FDTheme; +import fr.lirmm.aren.service.framadate.FDChoiceService; +import fr.lirmm.aren.service.framadate.FDThemeService; +import fr.lirmm.aren.service.framadate.FDVoteService; + +import javax.annotation.security.PermitAll; +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.Path; +import java.util.Set; + +@RequestScoped +@Path("themes") +public class FDThemeRESTFacade extends AbstractRESTFacade{ + @Inject + FDThemeService fdThemeService; + + @Inject + private FDChoiceService fdChoiceService ; + + @Inject + private FDVoteService fdVoteService ; + + + @Override + protected FDThemeService getService() { + return fdThemeService; + } + + @Override + //@RolesAllowed({"ADMIN"}) + @PermitAll + public FDTheme create(FDTheme fdTheme){ + return super.create(fdTheme); + } + + @Override + //@RolesAllowed({"ADMIN"}) + public FDTheme edit(Long id, FDTheme fdTheme){return super.edit(id, fdTheme);} + + @Override + @PermitAll + //@RolesAllowed({"MODO"}) + public Set findAll() { + boolean withChoices = this.overview == null; + System.out.println("WITH CHOICES : "+withChoices) ; + //System.out.println("USER : "+getUser().getFirstName()+" "+getUser().getLastName()) ; + return fdThemeService.findAll(withChoices, true); + } + + @Override + @RolesAllowed({"ADMIN"}) + public void remove(Long id) { + super.remove(id); + } + + @Override + //@RolesAllowed({"MODO"}) + @PermitAll + public FDTheme find(Long id) { + boolean withChoices = this.overview == null; + FDTheme fdTheme = fdThemeService.find(id,withChoices,true); + return fdTheme; + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/FDVoteRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/FDVoteRESTFacade.java new file mode 100644 index 0000000..679f97b --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/FDVoteRESTFacade.java @@ -0,0 +1,54 @@ +package fr.lirmm.aren.ws.rest; + +import fr.lirmm.aren.model.Institution; +import fr.lirmm.aren.model.framadate.FDVote; +import fr.lirmm.aren.service.AbstractService; +import fr.lirmm.aren.service.framadate.FDVoteService; + +import javax.annotation.security.PermitAll; +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.Path; +import java.util.Set; + +@RequestScoped +@Path("votes") +public class FDVoteRESTFacade extends AbstractRESTFacade{ + @Inject + private FDVoteService fdVoteService ; + + @Override + protected AbstractService getService() { + return fdVoteService; + } + + @Override + //@RolesAllowed({"USER"}) + @PermitAll + public FDVote create(FDVote fdVote) { + System.out.println(fdVote.toString()); + return super.create(fdVote); + } + + @Override + //@RolesAllowed({"USER"}) + @PermitAll + public FDVote find(Long id) { + FDVote fdVote = super.find(id); + return fdVote; + } + + @Override + @RolesAllowed({"ADMIN"}) + public void remove(Long id) { + super.remove(id); + } + + //@RolesAllowed({"USER"}) + @PermitAll + @Override + public Set findAll() { + return super.findAll(); + } +} \ No newline at end of file diff --git a/src/main/java/fr/lirmm/aren/ws/rest/InstitutionRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/InstitutionRESTFacade.java new file mode 100644 index 0000000..efc172a --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/InstitutionRESTFacade.java @@ -0,0 +1,108 @@ +package fr.lirmm.aren.ws.rest; + +import java.util.List; + +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +import fr.lirmm.aren.service.InstitutionService; +import fr.lirmm.aren.model.Institution; +import java.util.Set; + +/** + * JAX-RS resource class for Institutions managment + * + * @author Florent Descroix {@literal } + */ +@RequestScoped +@Path("institutions") +public class InstitutionRESTFacade extends AbstractRESTFacade { + + @Inject + private InstitutionService institutionService; + + /** + * + * @return + */ + @Override + protected InstitutionService getService() { + return institutionService; + } + + /** + * + * @param institution + * @return + */ + @Override + @RolesAllowed({"ADMIN"}) + public Institution create(Institution institution) { + + return super.create(institution); + } + + /** + * + * @param id + * @param institution + * @return + */ + @Override + @RolesAllowed({"ADMIN"}) + public Institution edit(Long id, Institution institution) { + + return super.edit(id, institution); + } + + /** + * + * @param id + */ + @Override + @RolesAllowed({"ADMIN"}) + public void remove(Long id) { + + super.remove(id); + } + + /** + * + * @return + */ + @Override + @RolesAllowed({"MODO"}) + public Institution find(Long id) { + Institution institution = super.find(id); + institution.getUsers().size(); + institution.getTeams().size(); + return institution; + } + + /** + * Find all Institution with associated Teams and associated Users + * + * @return + */ + @GET + @Path("/deep") + @RolesAllowed({"MODO"}) + public Set findAllDeep() { + return institutionService.findAll(true, true); + } + + /** + * Find all Institution with associated Teams and associated Users + * + * @return + */ + @RolesAllowed({"MODO"}) + @Override + public Set findAll() { + return super.findAll(); + } + +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/NotificationRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/NotificationRESTFacade.java new file mode 100644 index 0000000..6bf855c --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/NotificationRESTFacade.java @@ -0,0 +1,87 @@ +package fr.lirmm.aren.ws.rest; + +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; + +import fr.lirmm.aren.service.NotificationService; +import fr.lirmm.aren.model.Notification; +import java.util.Set; +import javax.ws.rs.QueryParam; + +/** + * JAX-RS resource class for Notifications managment + * + * @author Florent Descroix {@literal } + */ +@RequestScoped +@Path("notifications") +public class NotificationRESTFacade extends AbstractRESTFacade { + + @Inject + private NotificationService notificationService; + + /** + * + */ + @QueryParam("overview") + protected String overview; + + /** + * + * @return + */ + @Override + protected NotificationService getService() { + return notificationService; + } + + /** + * + * @return + */ + @Override + @RolesAllowed({"USER"}) + public Set findAll() { + if (overview == null) { + return notificationService.findAllByUser(this.getUser().getId()); + } else { + return notificationService.findAllFirstsByUser(this.getUser().getId(), 10); + } + } + + /** + * Mark all Notifications of the current User as read + * + * @return + */ + @PUT + @RolesAllowed({"USER"}) + public Set readAll() { + notificationService.readAllByUser(this.getUser().getId()); + return notificationService.findAllFirstsByUser(this.getUser().getId(), 10); + } + + /** + * + * @param id + * @param notification + */ + @Override + @RolesAllowed({"USER"}) + public Notification edit(Long id, Notification notification) { + Notification entityToUpdate; + if (this.getUser().is("SUPERADMIN")) { + notification.setContent(null); + entityToUpdate = super.edit(id, notification); + } else { + entityToUpdate = notificationService.find(id); + entityToUpdate.setUnread(notification.isUnread()); + notificationService.edit(entityToUpdate); + } + return entityToUpdate; + } + +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/TeamRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/TeamRESTFacade.java new file mode 100644 index 0000000..2bbb05b --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/TeamRESTFacade.java @@ -0,0 +1,146 @@ +package fr.lirmm.aren.ws.rest; + +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.DELETE; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; + +import fr.lirmm.aren.service.InstitutionService; +import fr.lirmm.aren.service.TeamService; +import fr.lirmm.aren.service.UserService; +import fr.lirmm.aren.model.Team; +import java.util.Set; + +/** + * JAX-RS resource class for Teams managment + * + * @author Florent Descroix {@literal } + */ +@RequestScoped +@Path("teams") +public class TeamRESTFacade extends AbstractRESTFacade { + + @Inject + private TeamService teamService; + + @Inject + private UserService userService; + + @Inject + private InstitutionService institutionService; + + /** + * + */ + @QueryParam("standalone") + protected String standalone; + + /** + * + * @return + */ + @Override + protected TeamService getService() { + return teamService; + } + + /** + * + * @param team + * @return + */ + @Override + @RolesAllowed({"MODO"}) + public Team create(Team team) { + + if (team.getInstitution() == null) { + team.setInstitution(institutionService.getReference(0L)); + } + + return super.create(team); + } + + /** + * + * @param id + */ + @Override + @RolesAllowed({"MODO"}) + public void remove(Long id) { + + super.remove(id); + } + + /** + * + * @param team + * @param id + * @return + */ + @Override + @RolesAllowed({"MODO"}) + public Team edit(Long id, Team team) { + + return super.edit(id, team); + } + + /** + * + * @return + */ + @RolesAllowed({"MODO"}) + @Override + public Team find(Long id) { + Team team = super.find(id); + team.getUsers().size(); + return team; + } + + /** + * + * @return + */ + @RolesAllowed({"MODO"}) + @Override + public Set findAll() { + + boolean standalone = this.standalone != null; + return teamService.findAll(standalone); + } + + /** + * Add a User to a Team + * + * @param id of the Team + * @param userId of the User + */ + @PUT + @Path("{id}/users/{userId}") + @RolesAllowed({"MODO"}) + public void addUser(@PathParam("id") Long id, @PathParam("userId") Long userId) { + + Team team = this.find(id); + team.addUser(userService.getReference(userId)); + teamService.edit(team); + } + + /** + * Remove a user from a Team + * + * @param id of the Team + * @param userId of teh User + */ + @DELETE + @Path("{id}/users/{userId}") + @RolesAllowed({"MODO"}) + public void removeUser(@PathParam("id") Long id, @PathParam("userId") Long userId) { + + Team team = this.find(id); + team.removeUser(userService.getReference(userId)); + teamService.edit(team); + } +} diff --git a/src/main/java/fr/lirmm/aren/ws/rest/UserRESTFacade.java b/src/main/java/fr/lirmm/aren/ws/rest/UserRESTFacade.java new file mode 100644 index 0000000..e20981f --- /dev/null +++ b/src/main/java/fr/lirmm/aren/ws/rest/UserRESTFacade.java @@ -0,0 +1,377 @@ +package fr.lirmm.aren.ws.rest; + +import javax.annotation.security.RolesAllowed; +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; + +import fr.lirmm.aren.service.InstitutionService; +import fr.lirmm.aren.service.UserService; +import fr.lirmm.aren.exception.AccessDeniedException; +import fr.lirmm.aren.model.User; +import fr.lirmm.aren.model.ws.ChangePassword; +import fr.lirmm.aren.model.ws.UserCredentials; +import fr.lirmm.aren.producer.Configurable; +import fr.lirmm.aren.security.token.AuthenticationTokenDetails; +import fr.lirmm.aren.security.token.AuthenticationTokenService; +import fr.lirmm.aren.service.AuthentificationService; +import fr.lirmm.aren.service.MailingService; +import fr.lirmm.aren.service.NotificationService; +import java.net.MalformedURLException; +import java.net.URL; +import java.text.MessageFormat; +import java.util.Locale; +import java.util.ResourceBundle; +import java.util.Set; +import javax.annotation.security.PermitAll; +import javax.mail.MessagingException; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.DELETE; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.NewCookie; +import javax.ws.rs.core.Response; + +/** + * JAX-RS resource class for Users managment + * + * @author Florent Descroix {@literal } + */ +@RequestScoped +@Path("users") +public class UserRESTFacade extends AbstractRESTFacade { + + @Inject + private UserService userService; + + @Inject + private InstitutionService institutionService; + + @Inject + private MailingService mailingService; + + @Inject + private AuthentificationService authentificationService; + + @Inject + private AuthenticationTokenService authenticationTokenService; + + @Inject + private NotificationService notificationService; + + @Inject + @Configurable("reverse-proxy") + private String reverseProxy; + + /** + * + */ + @QueryParam("standalone") + protected String standalone; + + /** + * + */ + @QueryParam("returnUrl") + protected String returnUrl; + + /** + * + * @return + */ + @Override + protected UserService getService() { + return userService; + } + + /** + * Create a token for the User matching the credentials + * + * @param credentials to fetch an User + * @return the token + */ + @POST + @PermitAll + @Path("auth") + public String authenticate(UserCredentials credentials) { + User user = authentificationService.validateCredentials(credentials.getUsername(), credentials.getPassword()); + return authenticationTokenService.issueToken(user); + } + + /** + * Create a token for the User matching the credentials and encapsulate it + * in a Cookie + * + * @param credentials to fetch an User + * @return a Cookie + */ + @POST + @PermitAll + @Path("login") + public Response login(UserCredentials credentials) { + if (credentials == null) { + throw new BadRequestException(); + } + + String token = authenticate(credentials); + + int maxAge = -1; + if (credentials.isRememberMe()) { + maxAge = 360 * 24 * 60 * 60; + } + + String domain; + Response response; + try { + domain = new URL(request.getRequestURL().toString()).getHost(); + NewCookie cookie = new NewCookie(HttpHeaders.AUTHORIZATION, token, "/", domain, "Authentification token for Aren platform", maxAge, false, true); + response = Response.ok(token).cookie(cookie).build(); + } catch (MalformedURLException ex) { + response = Response.ok(token).build(); + } + return response; + } + + /** + * Remove the Cookie that stored the previously created token + * + * @return + */ + @POST + @Path("logout") + @PermitAll + public Response logout() { + String domain; + Response response; + try { + domain = new URL(request.getRequestURL().toString()).getHost(); + NewCookie cookie = new NewCookie(HttpHeaders.AUTHORIZATION, "", "/", domain, "", 0, false, true); + response = Response.ok().cookie(cookie).build(); + } catch (MalformedURLException ex) { + response = Response.ok().build(); + } + return response; + } + + /** + * + * @param id + * @param entity + * @return + */ + @Override + @RolesAllowed({"USER"}) + public User edit(Long id, User entity) { + if (!(getUser().is("MODO") && getUser().hasSameOrMoreRightThan(entity) + || getUser().getId().equals(entity.getId()))) { + throw AccessDeniedException.PERMISSION_MISSING(); + } + + if (!getUser().is("SUPERADMIN")) { + User newUser = new User(); + // The only alterable fields in User + if (getUser().is("MODO") || getUser().getId().equals(entity.getId())) { + newUser.setFirstName(entity.getFirstName()); + newUser.setLastName(entity.getLastName()); + newUser.setEmail(entity.getEmail()); + } + if (getUser().is("MODO") && getUser().hasSameOrMoreRightThan(entity)) { + newUser.setAuthority(entity.getAuthority()); + } + entity = newUser; + } + return super.edit(id, entity); + } + + /** + * + * @param user + * @return + */ + @Override + @RolesAllowed({"GUEST"}) + public User create(User user) { + + if (user.getInstitution() == null || !getUser().is(User.Authority.SUPERADMIN)) { + user.setInstitution(institutionService.getReference(0L)); + } + if (getUser().getAuthority() == User.Authority.GUEST) { + user.setActive(false); + super.create(user); + try { + sendLink(user, "mail_new_user_subject", "mail_new_user_body"); + } catch (MessagingException ex) { + super.remove(user.getId()); + throw new RuntimeException(); + } + } else if (getUser().hasSameOrMoreRightThan(user)) { + super.create(user); + } else { + throw AccessDeniedException.PERMISSION_MISSING(); + } + return user; + } + + /** + * + * @param user + * @param subject + * @param body + * @param defautReturnUrl + */ + private void sendLink(User user, String subject, String body) throws MessagingException { + Locale currentLocale = request.getLocale(); + ResourceBundle messages = ResourceBundle.getBundle("messages", currentLocale); + + String token = authenticationTokenService.issueToken(user, 24L * 60 * 60); + System.out.println(authenticationTokenService.parseToken(token).getIssuedDate()); + String activationLink; + String localSubject; + String localBody; + + String serverRoot = this.reverseProxy; + if (serverRoot.length() == 0) { + serverRoot = request.getRequestURL().substring(0, request.getRequestURL().length() - "/ws/users".length()); + } + + if (returnUrl != null && !returnUrl.isEmpty()) { + activationLink = serverRoot + returnUrl.replace("{token}", token); + localSubject = messages.getString(subject); + localBody = MessageFormat.format(messages.getString(body), activationLink, activationLink); + } else { + localSubject = "AREN API token"; + localBody = token; + } + + mailingService.sendMail("noreply@aren.fr", user.getEmail(), localSubject, localBody); + } + + /** + * Mark a User as being activated after having clik in the mail link + * + */ + @GET + @Path("activate") + @RolesAllowed({"USER"}) + public void activateUser() { + getUser().setActive(true); + getService().edit(getUser()); + getService().invalidateToken(getUser()); + } + + /** + * Ask for a password reset for a User + * + * @param identifier of the User + */ + @POST + @Path("resetPasswd") + @RolesAllowed({"GUEST"}) + public void resetPasswd(String identifier) { + User user = getService().findByUsernameOrEmail(identifier); + if (user != null && user.isActive()) { + try { + sendLink(user, "mail_reset_password_subject", "mail_reset_password_body"); + } catch (MessagingException ex) { + throw new RuntimeException(); + } + } + // else nothing happend, it avoids someone to bruteforce user + } + + /** + * Mark a User as being removed without deleting its associated datas + * + * @param userId to remove + */ + @Override + public void remove(Long userId) { + User toDelete = getService().find(userId); + notificationService.removeAllByUser(userId); + getService().hide(userId); + super.edit(userId, toDelete); + } + + /** + * Remove an User with its associated datas + * + * @param userId to remove + */ + @DELETE + @Path("{id}/permanent") + @RolesAllowed({"SUPERADMIN"}) + public void permanentRemove(@PathParam("id") Long userId) { + User entity = find(userId); + safetyPreDeletion(entity); + notificationService.removeAllByUser(userId); + getService().remove(entity); + } + + /** + * Change User's password + * + * @param changePasswd + * @param token + */ + @PUT + @Path("passwd") + @RolesAllowed({"USER"}) + public void changePassword(ChangePassword changePasswd, @QueryParam("token") String token) { + // Mail token are 24h long, login token are 1 year long + // If this is a token from a mail, then it comes from a password reset requests + // so we do not check the old password + if (token != null && !token.isEmpty()) { + AuthenticationTokenDetails authToken = authenticationTokenService.parseToken(token); + if (authToken.getIssuedDate().plusSeconds(24 * 3600).isEqual(authToken.getExpirationDate())) { + userService.changePassword(getUser(), changePasswd.getNewPassword()); + getService().invalidateToken(getUser()); + return; + } + } + authentificationService.validateCredentials(getUser().getUsername(), changePasswd.getPassword()); + userService.changePassword(getUser(), changePasswd.getNewPassword()); + getService().invalidateToken(getUser()); + } + + /** + * + * @return + */ + @Override + @RolesAllowed({"ADMIN", "MODO"}) + public Set findAll() { + + boolean alone = this.standalone != null; + return getService().findAll(alone); + } + + /** + * Find the User the is currently authentificated + * + * @return + */ + @GET + @Path("me") + @RolesAllowed({"GUEST"}) + public User getAuthenticatedUser() { + + return getUser(); + } + + /** + * Check the existance of an User by its username or mail + * + * @param usernameOrMail + * @return + */ + @GET + @Path("test") + @RolesAllowed({"GUEST"}) + public boolean exists(@QueryParam("identifier") String usernameOrMail) { + return getService().findByUsernameOrEmail(usernameOrMail) != null; + } +} diff --git a/src/main/resources/META-INF/init.sql b/src/main/resources/META-INF/init.sql new file mode 100644 index 0000000..de52c3f --- /dev/null +++ b/src/main/resources/META-INF/init.sql @@ -0,0 +1,2 @@ +INSERT INTO institutions (id, created) VALUES (0, CURRENT_TIMESTAMP); +INSERT INTO users (id, first_name, last_name, email, username, password, is_active, last_login, token_validity, created, authority, institution_id) VALUES (0, 'Super', 'Admin', 'super.admin@lirmm.fr', 'admin', '$2a$10$sbbuW2wJ9FX.pgfsTRkZreFMAemTLwe6dXCPsxzZBnkd6P1dyY9kO', TRUE, NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'SUPERADMIN', 0); \ No newline at end of file diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000..76807d4 --- /dev/null +++ b/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,47 @@ + + + + org.hibernate.jpa.HibernatePersistenceProvider + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..41d96d0 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,59 @@ +# Change the production mode to alter some logging in the application +# On the client side, if set as true, the javascript and css loaded will be the minified ones +production = false + +# If you are behind a reverse proxy, write here the end user root url +# Example : http://aren.my_company.fr/app +reverse-proxy = + +# A unique identification of you web server. Used for remote requets +# Example : My_Institution +plateform.id = My_NewAren + +# Secret use for the creation of JWT token +authentication.jwt.secret = newarensecret + +# Issuer for the JWT token +# Example : my_domain.name +authentication.jwt.issuer = newaren.hn + +# Audience for the JWT token +# Example : my_domain.name +authentication.jwt.audience = newaren.hn + +# Validation time for the JWT tokens, in seconds +# Default is one year +authentication.jwt.validFor = 31536000 + +# Other configuration for JWT token, don't change if you don't know what you do +authentication.jwt.clockSkew = 10 +authentication.jwt.claimNames.authorities = authorities +authentication.jwt.claimNames.refreshCount = refreshCount +authentication.jwt.claimNames.refreshLimit = refreshLimit + +# SMTP configuration +# String +smtp.server = smtp.gmail.com +# Boolean +smtp.auth = true +# Int +smtp.port = 587 +# Boolean +smtp.tls = true +# String +smtp.username = dev.arenmg@gmail.com +# String +smtp.password = Aren123! + +# ENT conexion configuration +# Example : https://cas.mon-ent-occitanie.fr/login +cas.url = + +# AREN tools +# The Python scalar server +scalar.url = https://portail-aren.lirmm.fr/aren-vectors/scalar +# The python theme server +theme.url = https://portail-aren.lirmm.fr/aren-vectors/theme + +# Remote tool configuration +idefix.url = http://www.jeuxdemots.org/intern_extract.php diff --git a/src/main/resources/logging.properties b/src/main/resources/logging.properties new file mode 100644 index 0000000..15f59b8 --- /dev/null +++ b/src/main/resources/logging.properties @@ -0,0 +1,11 @@ +org.apache.catalina.startup.ContextConfig.level = FINE +org.apache.catalina.startup.HostConfig.level = FINE +org.apache.catalina.startup.TldConfig.level = WARNING +org.apache.catalina.core.StandardContext.level = WARNING +org.apache.catalina.core.ApplicationContext.level = WARNING +org.apache.catalina.level = WARNING +org.apache.coyote.AbstractProtocol = WARNING + +# c3p0 specific properties. +com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL = WARNING +com.mchange.v2.log.MLog = com.mchange.v2.log.FallbackMLog \ No newline at end of file diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties new file mode 100644 index 0000000..dc40f99 --- /dev/null +++ b/src/main/resources/messages.properties @@ -0,0 +1,25 @@ +inactive_user: inactive_user:{username} +bad_credentials: bad_credentials +mandatory_property: mandatory_property:{propertyName} +duplicate_key: duplicate_key:{keyName},{keyValue} +invalid_token: invalid_token +invalid_claim: invalid_claim:{claimName} +invalid_cas_ticket: invalid_cas_ticket +invalid_cas_ticket_detailed: invalid_cas_ticket:{code} +unmutable_object: unmutable_object:{className},{id} +permission_missing: permission_missing +invalid_parent: invalid_parent +cannot_refresh_token: cannot_refresh_token +authentification_required: authentification_required + +team_added_to_debate: team_added_to_debate:{teamName},{debateName} +invited_to_debate: invited_to_debate:{debateName} +comment_answered: comment_answered_by:{firstName},{lastName} +comment_moderated: comment_moderated:{debateName} +comment_signaled: comment_signaled:{debateName} + +mail_new_user_subject: Activation utilisateur +mail_new_user_body:

Bonjour,

Pour poursuivre l''activation de votre compte sur la plateforme AREN veuillez cliquer ici

Si le lien ne fonctionne pas, veuillez copier-coller l''url suivante dans la barre d''adresse de votre navigateur :
{0}


Attention ce lien n''est valable que pendant 24h.


PS : Veuillez ne pas répondre à ce mail qui est envoyé automatiquement par l''application de gestion de comptes informatiques.

+ +mail_reset_password_subject: Réinitialisation du mot de passe +mail_reset_password_body:

Bonjour,

Une demande de réinitialisation de mot de passe à été faite en votre nom pour la plateforme AREN.

Si vous êtes l''auteur\u22c5e de cette demande, pour réinitialiser votre mot de passe, cliquer ici

Si le lien ne fonctionne pas, veuillez copier-coller l''url suivante dans la barre d''adresse de votre navigateur :
{0}


Attention ce lien n''est valable que pendant 24h.


Si vous n''êtes pas l''auteur\u22c5e de cette demande, vous pouvez ignorer cet e-mail.


PS : Veuillez ne pas répondre à ce mail qui est envoyé automatiquement par l''application de gestion de comptes informatiques.

\ No newline at end of file diff --git a/src/main/webapp/META-INF/context.xml b/src/main/webapp/META-INF/context.xml new file mode 100644 index 0000000..a048525 --- /dev/null +++ b/src/main/webapp/META-INF/context.xml @@ -0,0 +1,2 @@ + + diff --git a/src/main/webapp/WEB-INF/AafImport/ficAlimMENESR.dtd b/src/main/webapp/WEB-INF/AafImport/ficAlimMENESR.dtd new file mode 100644 index 0000000..2107383 --- /dev/null +++ b/src/main/webapp/WEB-INF/AafImport/ficAlimMENESR.dtd @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/src/main/webapp/WEB-INF/beans.xml b/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000..25825aa --- /dev/null +++ b/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/src/main/webapp/WEB-INF/sass/_components.scss b/src/main/webapp/WEB-INF/sass/_components.scss new file mode 100644 index 0000000..f57cf77 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/_components.scss @@ -0,0 +1,520 @@ +.material-icons { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + white-space: nowrap; + word-wrap: normal; + direction: ltr; + -webkit-font-feature-settings: 'liga'; + -webkit-font-smoothing: antialiased; +} + +.btn.disabled { + pointer-events: auto; +} + +.grid { + grid-auto-rows: min-content; + display: inline-grid; + width: 100%; + .ghead, .gbody, .gfoot, .gr { + display: contents; + } + .gd, .gh { + display: grid; + grid-auto-columns: 1fr; + justify-content: center; + align-content: center; + text-align: center; + padding: 15px; + } + .gh { + align-content: baseline; + .card { + position: sticky; + top: 15px; + bottom: 15px; + } + } + .ghead { + color: $font-color-light; + .gh { + z-index: 8; + border-bottom: 1px solid $grey-color; + max-height: 40px; + line-height: 1em; + } + } + .gbody { + .gr.spacer { + grid-column: 1 / -1; + } + .separator { + grid-column: 1 / -1; + border-top: 1px solid $grey-color; + } + } + .pagination { + grid-column: 1 / -1; + } + + .gbody > .gr { + > .gd { + min-height: 70px; + } + } + + &.striped { + .gbody > .gr { + &:nth-child(odd) .gd { + background-color: $primary-color-light; + } + &:nth-child(odd):hover .gd { + background-color: mix($primary-color-light, $secondary-color-light); + } + &:nth-child(even):hover .gd { + background-color: $secondary-color-light; + } + } + } + + .gbody > .gr { + .gd.action { + grid-auto-flow: column; + grid-gap: 5px; + &.side { + .btn { + width: min-content; + } + } + } + + > .gr.extendable > .gd.action { + padding-top: 0; + padding-bottom: 0; + transition: padding .3s, max-height .3s; + .btn { + max-height: 0; + transition: max-height 0.3s; + } + } + + &:focus-within { + .gd { + background-color: $selection-color !important; + } + > .gr.extendable > .gd.action { + padding-bottom: 15px; + .btn { + max-height: 36px; + } + } + } + } +} + +#tooltip { + opacity: .75; + transition: opacity .3s, margin-top .3s; + &.v-enter, &.v-leave-to { + margin-top: 3px; + opacity: 0; + } + position: fixed; + pointer-events: none; + transform: translate(-50%, -100%); + max-width: 120px; + width: 120px; + background-color: black; + color: #fff; + text-align: center; + padding: 5px; + border-radius: 6px; + margin-top: -7px; + font-size: 11px; + line-height: 13px; + z-index: 1005; + &::after { + content: " "; + position: absolute; + left: 50%; + bottom: -10px; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: black transparent transparent transparent; + } +} + +#documentation { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + z-index: 2000; + pointer-events: none; + opacity: 1; + transition: opacity .3s; + + &.v-enter, &.v-leave-to { + opacity: 0; + .overlay { + width: 0 !important; + height: 0 !important; + } + } + + .overlay { + position: fixed; + border-radius: 10050px; + border: 10000px solid rgba(0,0,0,0.66); + box-sizing: content-box; + transform: translate(-50%, -50%); + transition: all .3s; + } + &.first .overlay{ + transition: opacity .3s, height .3s, width .3s; + } + + .content { + position: absolute; + font-size: 1.5em; + color: white; + max-height: 75%; + max-width: 75%; + h1 { + text-align: center; + } + * { + color: white; + } + > *:first-child { + margin-top: 0; + } + > *:last-child { + margin-bottom: 0; + } + } + + svg { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + stroke-width: 5px; + fill: none; + stroke: white; + } + + .next, .close { + user-select: none; + pointer-events: all !important; + } + + .close { + top: 16px; + right: 6px; + padding-top: 0; + } +} + +.dropdown-button { + position: relative; + display: block; + overflow: visible; + margin: 12px 5px; + line-height: 1; + &:focus, &:focus-within { + .dropdown-content { + display: block; + opacity: 1; + } + } + .dropdown-content { + overflow: visible; + top: calc(100% + 12px); + left: auto; + right: 0; + min-width: 250px; + width: min-content; + &::before { + content: ""; + position: absolute; + top: -20px; + right: 10px; + border-width: 10px; + border-style: solid; + border-color: transparent transparent white transparent; + } + .dropdown-title { + margin: 0; + padding: 8px; + font-weight: bold; + border-bottom: 1px solid $grey-color-light; + .option { + position: absolute; + right: 8px; + font-weight: normal; + cursor: pointer; + &:hover { + text-decoration: underline; + } + } + } + li:hover { + background-color: initial; + } + } +} + +.tabs { + display: grid; + background: initial; + .tab:not(.disabled) a { + cursor: pointer; + position: relative; + &::after { + position: absolute; + content: ""; + background: $primary-color; + width: 0; + height: 2px; + bottom: 0; + left: 50%; + transform: translateX(-50%); + transition: width 0.3s; + } + &:hover, &.active { + &::after { + width: 100%; + } + } + } + .tab.disabled a { + pointer: default; + } +} + +.arrow { + border: solid black; + border-width: 0 2px 2px 0; + border-top-left-radius: 10px; + display: inline-block; + padding: 3px; + transition: transform .3s; + &.to-right { + transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); + } + &.to-left { + transform: rotate(135deg); + -webkit-transform: rotate(135deg); + } + &.to-up { + transform: rotate(-135deg); + -webkit-transform: rotate(-135deg); + } + &.to-down { + transform: rotate(45deg); + -webkit-transform: rotate(45deg); + } +} + +.modal-wrapper { + &.v-enter-active, &.v-leave-active { + transition: all .3s; + } + &.v-enter, &.v-leave-to { + .modal { + opacity: 0; + transform: scale(0.5); + + .modal-overlay { + opacity: 0; + } + } + } + .modal { + opacity: 1; + transform: none; + display: block; + top: 10%; + z-index: 1003; + min-width: 900px; + max-height: 80vh; + transition: opacity .3s ease-in, transform .3s ease-out; + .dragger { + cursor: move; + position: absolute; + height: 24px; + width: 24px; + &:before { + content: '.'; + color: #aaa; + position: absolute; + left: 4.5px; + top: 1.5px; + font-size: 20px; + line-height: 0; + text-shadow: 0 5px, 0 10px, 5px 0, 5px 5px, 5px 10px, 10px 0, 10px 5px, 10px 10px; + } + } + &.modal-fixed-footer { + height: auto; + padding-bottom: 56px; + overflow: hidden; + .modal-content { + position: initial; + max-height: calc(80vh - 56px); + } + } + + .modal-overlay { + top: 0; + z-index: 1002; + display: block; + opacity: 0.5; + transition: opacity .3s ease-in; + } + } + &#confirmDialog .modal { + top: 15%; + z-index: 1005; + width: 50vw; + min-width: 500px; + + .modal-overlay { + z-index: 1004; + } + } +} + +.input-field:focus-within > label { + color: $secondary-color; + transform: translateY(-14px) scale(0.8); + transform-origin: 0 0; +} + +.input-field .helper-text.flash { + animation: blinker 1s linear infinite; +} + +@keyframes blinker { + 50% { + opacity: 0; + } +} + +.chips { + padding-top: 7px; + &:focus-within { + border-bottom: 1px solid $secondary-color; + box-shadow: 0 1px 0 0 $secondary-color; + } + &:empty ~ label { + font-size: inherit; + transform: none; + } + .input { + height: 32px; + vertical-align: middle; + &[disabled="disabled"] { + border: none; + } + } +} +.chip { + cursor: pointer; + user-select: none; + color: white; + background-color: $grey-color; + &.negative { + background-color: $primary-color; + } + &.positive { + background-color: $secondary-color; + } + &.valid { + background-color: $success-color; + } + .close { + height: 24px; + width: 24px; + margin: 4px -7px 4px 4px; + line-height: 24px !important; + border-radius: 20px; + text-align: center; + padding: 0; + transition: background .3s; + &:hover { + background: rgba(0,0,0,.3); + } + } +} + +.toast { + transition: margin-top .3s, opacity .3s; + &.v-enter { + margin-top: 58px; + opacity: 0 !important; + } + &.v-leave-to { + margin-top: -48px; + opacity: 0 !important; + } +} + +.materialize-textarea { + line-height: normal; + padding: .8rem 0 .8rem 0; + min-height: 3rem; + border-bottom: 1px solid $grey-color; + border-radius: 0; + outline: none; + width: 100%; + font-size: 16px; + transition: box-shadow .3s, border .3s; +} + +.materialize-textarea:focus { + outline: none; + border-bottom: 1px solid $secondary-color; + box-shadow: 0 1px 0 0 $secondary-color; +} + +/** alternative modals +.modal { + position: fixed; + top: 0; + left: 0; + background-color: rgba(0, 0, 0, 0.5); + height: 100vh; + width: 100vw; + overflow-y: scroll; +} + +.modal::before, .modal::after { + content: ""; + display: block; + height: 20px; + width: 100%; +} + + +.modal .modal-content { + background: #fafafa; + width: 60%; + margin: auto; +} + +.modal .modal-footer { + position: sticky; + bottom: 20px; + left: 0; + right: 0; + text-align: center; +} +**/ diff --git a/src/main/webapp/WEB-INF/sass/_materialize.scss b/src/main/webapp/WEB-INF/sass/_materialize.scss new file mode 100644 index 0000000..08fcf30 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/_materialize.scss @@ -0,0 +1,41 @@ +@charset "UTF-8"; + +// Color +@import "components/color-variables"; +@import "components/color-classes"; + +// Variables; +@import "components/variables"; + +// Reset +@import "components/normalize"; + +// components +@import "components/global"; +@import "components/badges"; +@import "components/icons-material-design"; +@import "components/grid"; +@import "components/navbar"; +@import "components/typography"; +@import "components/transitions"; +@import "components/cards"; +@import "components/toast"; +@import "components/tabs"; +@import "components/tooltip"; +@import "components/buttons"; +@import "components/dropdown"; +@import "components/waves"; +@import "components/modal"; +@import "components/collapsible"; +@import "components/chips"; +@import "components/materialbox"; +@import "components/forms/forms"; +@import "components/table_of_contents"; +@import "components/sidenav"; +@import "components/preloader"; +@import "components/slider"; +@import "components/carousel"; +@import "components/tapTarget"; +@import "components/pulse"; +@import "components/datepicker"; +@import "components/timepicker"; \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/sass/_variables.scss b/src/main/webapp/WEB-INF/sass/_variables.scss new file mode 100644 index 0000000..5c5a78e --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/_variables.scss @@ -0,0 +1,66 @@ +// VARIBLES +@font-face { + font-family: "Seravek"; + src: url("../font/seravek-light-webfont.woff") format('woff'); + font-weight: 100; +} + +@font-face { + font-family: "Seravek"; + src: url("../font/seravek-regular-webfont.woff") format('woff'); + font-weight: 400; +} + +@font-face { + font-family: "Seravek"; + src: url("../font/seravek-medium-webfont.woff") format('woff'); + font-weight: 700; +} + +@font-face { + font-family: "Seravek"; + src: url("../font/seravek-bold-webfont.woff") format('woff'); + font-weight: 900; +} + +@font-face { + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: url("../font/material-icons.woff") format('woff2'); +} + +$background-color: white; +$primary-color: #B84000 !default; +$secondary-color: #4D9999 !default; +$primary-color-light: change-color($primary-color, $lightness: 95%); +$secondary-color-light: change-color($secondary-color, $lightness: 95%); +$selection-color: change-color($secondary-color, $saturation: 60%, $lightness: 60%) !default; + +$text-select-color: #C6E4E3; + +$success-color: #26A96C !default; +/*$error-color: color("red", "base") !default;*/ +$link-color: #336362 !default; +$font-color-light: #B2B2B2 !default; +$font-stack: Seravek, Helvetica, Roboto, Arial, sans-serif; + +$h1-fontsize: 1.4em !default; +$h2-fontsize: 1.2em !default; +$h3-fontsize: 1em !default; +$h4-fontsize: 0.8em !default; +$h5-fontsize: 0.8em !default; + +$blue-color: #4D9999; +$red-color: #BA4100; +$green-color: #26A96C; +$grey-color: #B2B2B2; +$grey-color-light: #DDDFE2; +$grey-color-dark: #808080; + +:root { + --blue-color: #{$blue-color}; + --red-color: #{$red-color}; + --green-color: #{$green-color}; + --grey-color: #{$grey-color}; +} \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/sass/app.scss b/src/main/webapp/WEB-INF/sass/app.scss new file mode 100644 index 0000000..d92c284 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/app.scss @@ -0,0 +1,1500 @@ +@import "variables"; +@import "materialize"; +@import "components"; + +::-webkit-scrollbar { + width: 12px; + height: 12px; + border-radius: 3px; +} + +::-webkit-scrollbar-track { + background-color: #cecece; + border-left: 1px solid #cdc7c2; +} +::-webkit-scrollbar-thumb { + background-color: #7e8182; + border: 3px solid #cecece; + border-radius: 6px; + min-height: 40px; +} +::-webkit-scrollbar-thumb:hover { + background-color: #565b5c; +} +::-webkit-scrollbar-thumb:active { + background-color: #1b6acb; +} + +h1 { color: $primary-color } +h2 { color: $primary-color } +h3 { color: #000000 } +h4 { color: $primary-color } +h5 { color: #000000 } +td, th { border-radius: 0; } +strong { font-weight: bold; } +textarea { display: block; } +.btn { + text-overflow: ellipsis; + white-space: nowrap; + &.primary-color:hover { + background-color: $primary-color; + } +} +.container { + width: 85% !important; +} + +img { + overflow: hidden; + max-width: 100%; + max-height: 100%; +} +.clickable:hover { + cursor: pointer; + text-decoration: underline; +} +.input-field .materialize-textarea { + min-width: 50px; + font-size: inherit; + &:not([contenteditable]), &[contenteditable="false"] { + border-color: transparent; + } + &[placeholder]:empty::before { + content: attr(placeholder); + color: black; + opacity: 0.25; + } +} + +[tabindex] { + &:focus { + outline: none; + cursor: initial; + } +} + +[v-cloak] { + display: none; +} + +[unselectable="on"] { + -moz-user-select: -moz-none; + -khtml-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.search-box { + > input { + margin-bottom: 0; + } +} + +$navigation-height: 64px; +$header-height: 60px; + +html { + body { + min-width: 900px; + overflow-y: scroll; + overflow-x: auto; + #app { + --primary-color-hover: var(--primary-color)10; + --secondary-color-hover: var(--secondary-color)10; + display: flex; + min-height: 100vh; + flex-direction: column; + #help { + margin: 0 10px; + cursor: pointer; + } + &.help { + cursor: help; + :not(.documented) { + pointer-events: none; + } + .documented { + pointer-events: all; + } + } + > nav { + height: $navigation-height; + position: sticky; + min-width: 900px; + width: 100%; + top: 0; + left: 0; + z-index: 10; + } + #loading { + position: fixed; + margin: auto; + top: $navigation-height; + border-radius: none; + z-index: 5; + } + .current-view-wrapper { + display: flex; + flex-direction: column; + min-height: calc(100vh - #{$navigation-height}); + padding-bottom: 30px; + .current-view { + display: flex; + flex-direction: column; + flex: 1; + > .container { + display: flex; + flex-direction: column; + flex: 1; + width: 85%; + > #header { + position: sticky; + padding: 0 17px; + top: $navigation-height; + background: $background-color; + display: grid; + grid-template-columns: 1fr max-content; + height: $header-height; + align-items: center; + z-index: 4; + > div { + display: grid; + grid-column-gap: 0.25em; + grid-template-columns: max-content 1fr max-content max-content; + align-items: center; + margin-right: 15px; + width: fit-content; + > h1 { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + margin: 0; + } + .author { + color: $primary-color; + font-size: 14px; + } + .details { + margin: 0; + line-height: 1em; + p { + margin: 0; + } + } + } + #backTo { + position: absolute; + top: 18px; + left: 0; + } + } + > .grid { + flex: 1; + > .ghead .gh { + position: sticky; + top: ($navigation-height + $header-height); + background: $background-color; + z-index: 8; + } + .gh > .card { + top: 179px; + } + } + } + } + } + .page-footer { + .contributors a { + display: flex; + height: 70px; + align-items: center; + justify-content: center; + float: left; + margin-right: 50px; + img { + max-width: 180px; + max-height: 100%; + } + } + } + } + } +} + +@media only print { + html body #app { + > nav { + display: none; + } + .current-view { + padding-top: 0; + > .container { + width: 100%; + > #header { + top: 0; + } + } + } + } +} + +.switch label { + position: relative; +} + +.card { + display: block; + @media #{$small-and-down} { + max-width: 120px; + } + @media #{$medium-and-up} { + max-width: 160px; + } + @media #{$large-and-up} { + max-width: 200px; + } + @media #{$extra-large-and-up} { + max-width: 240px; + } + h2 { + max-height: 43px; + min-height: 43px; + overflow-y: auto; + } +} + +.card-image { + @media #{$small-and-down} { + width: 120px; + height: calc(120px / 3 * 2); + } + @media #{$medium-and-up} { + width: 160px; + height: calc(160px / 3 * 2); + } + @media #{$large-and-up} { + width: 200px; + height: calc(200px / 3 * 2); + } + @media #{$extra-large-and-up} { + width: 240px; + height: calc(240px / 3 * 2); + } + width: 100%; + margin: auto; + img { + height: auto !important; + width:auto !important; + margin: auto; + } +} + +.light-color { + background: $secondary-color-light; +} + +.primary-color { + background: $primary-color; + color: white; +} + +nav { + #logoContainer { + z-index: 1; + float: left; + img { + vertical-align: middle; + margin-bottom: 5px; + } + } + + .menu { + a { + position: relative; + &::after { + position: absolute; + content: ""; + background: $background-color; + width: 0; + height: 2px; + bottom: 0; + left: 50%; + transform: translateX(-50%); + transition: width 0.3s; + } + &:hover, &.active { + &::after { + width: 100%; + } + } + } + } + + #userSettings { + .dropdown-content { + a.btn { + background: $grey-color; + color: white; + width: calc(100% - 30px); + margin: 10px 15px; + } + #changePasswd { + margin: 5px; + .input-field { + input:not(:focus) { + border-bottom: 1px solid; + } + } + } + } + } + + #notifications { + position: relative; + #notificationCount { + position: absolute; + cursor: pointer; + top: 15px; + right: 17px; + border-radius: 2px; + padding: 1px 3px; + line-height: 1.3; + min-height: 1.3em; + min-width: 0; + font-size: 10px; + background-color: $error-color; + } + .dropdown-button { + width: 40px; + height: 40px; + padding: 0; + border-radius: 100px; + i { + cursor: pointer; + text-align: center; + line-height: 40px; + height: 40px; + } + &:focus, &:focus-within { + background-color: rgba(0, 0, 0, 0.1); + } + } + .dropdown-content { + width: 460px; + ul { + height: calc(100vh - 112px); + max-height: 600px; + overflow: auto; + li { + position: relative; + margin-right: 25px; + border-bottom: 1px solid $grey-color-light; + &.unread { + background-color: $primary-color-light; + .read-toggle { + border-width: 3px; + } + &:hover { + background-color: mix($primary-color-light, $secondary-color-light); + } + } + &:hover { + background-color: $secondary-color-light; + .read-toggle { + opacity: 1; + } + } + a { + padding: 5px 16px; + font-size: 14px; + .arg { + font-weight: bold; + } + &:hover { + background-color: initial; + } + } + .read-toggle { + position: absolute; + opacity: 0; + right: 10px; + top: 10px; + width: 10px; + height: 10px; + padding: 0; + border: 5px solid $grey-color; + &:hover { + border-color: $grey-color-dark; + } + border-radius: 10px; + transition: opacity .3s; + } + } + } + } + } +} + +#login { + > div { + justify-content: center; + #loginForm { + width: 500px; + } + } +} + +#aafImport { + .progress { + width: 490px; + } +} + +#home { + #welcomeCallout { + margin: 0; + color: $primary-color; + img { + @media #{$large-and-up} { + margin-left: 50px; + } + @media #{$small-and-down} { + display: none; + } + max-height: 100px; + } + } + + #categoriesList { + .col { + display: inline-block; + float: none; + } + } +} + +#debates { + .opinion { + height: 16px; + width: 100%; + background-color: $grey-color; + .for { + height: 100%; + float: left; + background-color: $blue-color; + } + .against { + height: 100%; + float: right; + background-color: $red-color; + + } + } +} + +#debate, .comment { + .comment-mark { + display: inline; + } +} + +@media only print { + #debate { + height: auto !important; + .selection { + > div { + max-height: none !important; + } + &::before, &::after { + content: none; + } + } + #documentContainer, #commentsContainer { + height: auto !important; + } + } +} + +#debate { + .row { + margin: 0; + } + + #options { + position: sticky; + padding: 0 17px; + top: ($navigation-height + $header-height); + background: $background-color; + z-index: 2; + text-align: right; + .col { + padding: 0; + } + #sortCommentsBy, #leftDisplay { + position: absolute; + bottom: 0; + input { + + i { + font-style: normal; + } + &:checked + i { + font-weight: bold; + } + } + } + .search-box { + margin: 0; + > input { + margin-bottom: 5px; + margin-top: -5px; + } + } + } + + #mainContainer { + height: calc(100vh - #{($navigation-height + $header-height) + 46px}); + } + + #documentContainer, #commentsContainer { + width: 50%; + height: 100%; + float: left; + .scroll-area { + height: 100%; + overflow-y: scroll; + } + } + + #commentsContainer.loading { + position: relative; + overflow-x: hidden; + + &::before, &::after { + content: ""; + display: block; + top:0; + left:0; + width: 100%; + height: 100%; + position: absolute; + } + + &::before { + background: rgb(224, 224, 224); + z-index: 1; + } + + &::after { + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); + transform: translateX(-100%); + animation: loading 1.5s infinite; + z-index: 1; + } + + @keyframes loading { + 100% { + transform: translateX(100%); + } + } + } + + // Display scrollabr on the left + #documentContainer { + .scroll-area { + direction: rtl; + > * { + direction: ltr; + } + } + } + + #documentContainer { + z-index: 1; + .scroll-area { + padding-left: 5px; + .wrap { + display: flex; + min-height: 100%; + #documentDisplay { + text-align: justify; + font-size: 13px; + line-height: 1.42; + width: calc(100% - 60px); + float: left; + &::selection, ::selection { + background-color: $text-select-color; + } + } + .bullets-container { + float: left; + } + } + } + } + .selection_popup { + position: absolute; + cursor: pointer; + background: $secondary-color; + color: white; + border-radius: 5px; + padding: 0 5px; + &::before { + content: ""; + position: absolute; + border-width: 8px 5px; + border-style: solid; + } + &.top { + margin-top: -7px; + margin-left: -15px; + transform: translateY(-100%); + &::before { + bottom: -16px; + left: 10px; + border-color: $secondary-color transparent transparent transparent; + } + } + &.bottom { + margin-top: 7px; + margin-left: 15px; + transform: translateX(-100%); + &::before { + top: -16px; + right: 10px; + border-color: transparent transparent $secondary-color transparent; + } + } + } + + .comment-container { + &.moderated::after { + content: ""; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + background-color: $error-color; + opacity: 50%; + } + } + .answers-container { + overflow: hidden; + .answers { + overflow-y: hidden; + padding: 0 5px 0 10px; + transition: margin-top .3s; + &.v-enter-active { + transition: all 0s; + } + } + } + .comment-body, .spaghetti-data { + .selection { + cursor: pointer; + &:hover, &.active { + background: lighten($grey-color-light, 5%); + border-left-color: $grey-color-dark; + border-right-color: $grey-color-dark; + &::before { + background-image: linear-gradient(#{lighten($grey-color-light, 5%)}, transparent); + } + &::after { + background-image: linear-gradient(transparent, #{lighten($grey-color-light, 5%)}); + } + } + } + } + + .bullets-container { + position: relative; + width: 50px; + margin: 0 5px; + .bullets-box { + position: absolute; + height: 1em; + width: 100%; + display: flex; + align-items: center; + justify-content: space-evenly; + .bullet { + height: 10px; + width: 10px; + &::before { + content: ""; + display: block; + width: 100%; + height: 100%; + box-sizing: border-box; + border-radius: 10px; + } + &.for::before { + background: $blue-color; + } + &.neutral::before { + background: $grey-color; + } + &.against::before { + background: $red-color; + } + &:hover { + cursor: pointer; + z-index: 2; + width: 8px; + height: 8px; + margin: 1px; + } + + } + .bullets-drop-down { + &.for { + background: $blue-color; + } + &.against { + background: $red-color; + } + &.neutral { + background: $grey-color; + } + min-width: 10px; + padding: 5px; + border-radius: 10px; + box-sizing: content-box; + line-height: 10px; + font-size: 10px; + text-align: center; + z-index: 1; + font-weight: bold; + color: white; + transition: box-shadow .3s; + > .label { + overflow: hidden; + height: 10px; + transition: height .3s; + } + > .body { + transition: height .3s; + overflow: hidden; + } + } + &:not(:hover) .bullets-drop-down { + box-shadow: 4px 0 0 -1px #ddd, 4px 0 1px -1px black, + 8px 0 0 -2px #bbb, 8px 0 1px -2px black, + 12px 0 0 -3px #aaa, 12px 0 1px -3px black; + > .body { + height: 0 !important; + } + + } + &:hover .bullets-drop-down { + z-index: 9999; + background: $background-color !important; + width: 10px; + > .label { + height: 0; + } + } + } + } + + .spaghetti-data { + width: 50%; + float: left; + > .theme { + display: grid; + grid-template-columns: min-content 1fr; + align-items: center; + .close { + cursor: pointer; + margin-bottom: 10px; + } + } + } + + svg.spaghettis { + position: fixed; + pointer-events: none; + top: 0; + left: 0; + width: 100%; + height: 100%; + stroke-width: 3px; + use { + fill: none; + stroke-width: 6px; + cursor: pointer; + pointer-events: initial; + } + path { + fill: none; + stroke-width: inherit; + pointer-events: initial; + &.trigger { + stroke-width: 20px; + } + } + > g { + transition: opacity .3s; + } + &.hover > g { + opacity: 0.25; + } + } + +} + +.comment { + position: relative; + font-size: 13px; + padding: 3px 5px; + margin-bottom: 5px; + box-sizing: border-box; + border-left: 3px solid; + outline-width: 3px; + outline-offset: -3px; + .close { + position: absolute; + cursor: pointer; + top: 0; + right: .5em; + } + &.for { + border-color: $blue-color; + outline-color: $blue-color; + .comment-header * { + color: $blue-color; + } + } + &.neutral { + border-color: $grey-color; + outline-color: $grey-color; + .comment-header * { + color: $grey-color; + } + } + &.against { + border-color: $red-color; + outline-color: $red-color; + .comment-header * { + color: $red-color; + } + } + &:focus-within { + outline-style: solid; + outline-width: 3px; + + } + .comment-header { + .username { + display: inline-block; + margin-right: 10px; + margin-top: 0; + } + .comment-count { + cursor: pointer; + } + } + .comment-body { + .reformulation-wrapper, .argumentation-wrapper { + display: grid; + grid-template-columns: 20px 1fr 60px; + > i, > .tags > i { + font-size: 18px; + margin-top: 1px; + } + } + .reformulation-wrapper { + .reformulation { + white-space: pre-wrap; + } + .tags { + margin: 0 20px; + i { + cursor: pointer; + text-shadow: 0 0 1px black, 0 0 1px black, 0 0 1px black, 0 0 1px black; + color: white; + } + &.disabled i { + cursor: default; + opacity: .5; + } + } + } + .argumentation-wrapper { + .argumentation { + white-space: pre-wrap; + &::selection { + background-color: $text-select-color; + } + } + } + } +} + +.selection { + overflow: hidden; + position: relative; + background: $grey-color-light; + border-left: 3px solid $grey-color; + border-right: 3px solid $grey-color; + border-radius: 5px; + transition: background .3s, border-color .3s; + text-align: justify; + font-size: 13px; + line-height: 1.42; + margin-bottom: 10px; + > div > *:nth-last-child(1) { + margin-bottom: 0; + } + &::after, &::before { + position: absolute; + content: ""; + width: 100%; + height: 10px; + background-image: linear-gradient(transparent, $grey-color-light); + left: 0; + bottom: 0; + } + &::before { + background-image: linear-gradient($grey-color-light, transparent); + top: 0; + } + > div { + max-height: 100px; + overflow: auto; + padding: 5px; + *:nth-child(1) { + margin-top: 0; + } + *:nth-last-child(1) { + margin-bottom: 0; + } + } +} + +#commentModal { + .modal { + resize: horizontal; + min-width: 500px; + } + #argumentation { + .materialize-textarea { + min-height: 6em; + } + } + .input-field:focus-within > #reformulationCheck { + svg .line { + stroke: $secondary-color; + stroke-width: 2px; + } + } + #reformulationCheck { + display: flex; + align-items: center; + background: #fafafa; + position: absolute; + right: 0; + bottom: -19px; + + &.loading { + @keyframes spin { + from { + transform: rotate(0deg) + translate(-3px) + rotate(0deg); + } + to { + transform: rotate(360deg) + translate(-3px) + rotate(-360deg); + } + } + svg .pupil { + animation: spin 2s linear infinite; + } + } + + svg { + fill: none; + stroke: none; + .eye { + stroke: #e5e5e5; + } + .eyelid { + fill: #e5e5e5; + } + .pupil { + fill: #666666; + } + .line, .mouth { + stroke: #9e9e9e; + transition: stroke .3s, stroke-width .3s; + } + + span { + font-size: 10px; + border: 1px solid #9e9e9e; + margin-left: 7px; + margin-bottom: 5px; + padding: 0 5px; + &::before { + content: ""; + position: absolute; + top: 10px; + left: 36px; + border: solid #9e9e9e; + border-width: 0 1px 1px 0; + padding: 3px; + background: #fafafa; + transform: rotate(135deg); + } + } + } + } + #opinion { + padding-bottom: 1rem; + input + span { + padding-left: 16px; + &::before { + display: none; + } + &::after { + display: none; + } + } + input:checked + span { + box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.14) inset, + 0 1px 7px 0 rgba(0, 0, 0, 0.12) inset, + 0 3px 1px -1px rgba(0, 0, 0, 0.2) inset; + } + input:not(:checked) + span:not(:hover) { + opacity: 0.5; + } + label { + &> .against { + background-color: $red-color; + } + &> .neutral { + background-color: $grey-color; + } + &> .for { + background-color: $blue-color; + } + } + } + #hypostase { + .list{ + display: grid; + width: 100%; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr; + transition: height .3s; + height: 27px; + &.expert { + height: 219px; + } + input[type="checkbox"] { + display: none; + } + > div { + > .btn { + display: block; + height: auto; + line-height: initial; + text-align: center; + padding: 0; + cursor: pointer; + margin: 3px; + padding: 2px 5px !important; + text-transform: none; + &:first-of-type { + font-weight: bold; + } + &:not(:hover) { + opacity: 0.75; + } + } + input:checked + .btn { + background: $secondary-color linear-gradient(0deg, $secondary-color 0%, $secondary-color 100%); + box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.14) inset, 0 1px 7px 0 rgba(0, 0, 0, 0.12) inset, 0 3px 1px -1px rgba(0, 0, 0, 0.2) inset; + opacity: 1; + } + } + } + } +} + +#documents { + .grid { + .gr.header { + .gh:hover { + background-color: $secondary-color-light; + } + .card-action { + line-height: 0; + padding-top: 0; + padding-bottom: 0; + border: none; + transition: all .3s; + .btn { + max-height: 0; + } + } + &:focus-within { + .gh { + background-color: $selection-color !important; + } + .card-action { + padding-bottom: 15px; + .btn { + max-height: 36px; + } + } + } + } + } +} + +#document { + .input-field.inline { + margin: 0; + } + .input-field { + margin-bottom: 1px; + } + .ql-toolbar { + position: sticky; + top: ($navigation-height + $header-height); + background: $background-color; + z-index: 10; + height: 42px; + overflow: hidden; + transition: height .3s, padding .3s; + } + .ql-container { + margin-top: -1px; + background: $background-color; + border-top: 1px solid #ccc; + transition: margin-top .3s; + .ql-editor { + margin-bottom: 10px; + text-align: justify; + transition: height .3s; + } + } + #documentDisplay:not(.in-edition) { + .ql-toolbar { + height: 0; + padding-top: 0; + padding-bottom: 0; + border-bottom-width: 0; + } + } +} + +#createDebate { + .steps { + > .tabs { + position: sticky; + top: 75px; + z-index: 9; + display: block; + margin-top: -50px; + text-align: center; + border: none; + height: auto; + background: $background-color; + .tab { + height: auto; + a { + text-transform: capitalize; + line-height: 1em; + &::after { + content: none; + } + } + &:not(.disabled) a { + &.active, &:hover { + img { + border: 1px solid $selection-color; + border-radius: 200px; + margin: 0 -1px; + } + } + } + &.disabled a img { + filter: grayscale(100%); + } + } + } + .grid { + > .ghead .gh { + position: sticky; + top: 202px; + background: $background-color; + z-index: 8; + } + .gh { + .card { + top: 242px; + } + } + } + #contributors { + > div > .tabs { + position: sticky; + top: 202px; + background: $background-color; + z-index: 8; + } + .grid > .ghead .gh { + position: sticky; + top: 250px; + background: $background-color; + z-index: 8; + } + } + .collection-item { + > span { + display: inline-block; + max-width: calc(100% - 40px); + } + .close { + cursor: pointer; + } + } + } + #advancedOptions { + > li { + cursor: pointer; + .arrow { + right: 20px; + position: absolute; + } + } + #advancedOptionsBody { + overflow: hidden; + > ul { + transition: margin-top .3s; + } + } + } +} + +#contributors { + .search-box { + width: 20em; + margin: 0; + } +} + +#sort-options { + height: 46px; + select { + width: 50%; + float: left; + margin: 0; + } + .input-field { + width: 20em; + max-width: 50%; + float: right; + margin: 0; + } +} + +#teams { + #header > div > select { + text-overflow: ellipsis; + color: $primary-color; + } + .search-box { + margin: 0; + } +} + +#restitution { + .detail { + background: $background-color; + margin-right: 10px; + margin-bottom: 10px; + .document { + padding: 1px 10px; + text-align: justify; + font-size: 13px; + line-height: 1.42; + } + } + + .D3_tree { + width: 100%; + overflow: auto; + height: calc(100vh - 172px); + position: relative; + .detail { + background: $background-color; + position: sticky; + height: min-content; + width: 50%; + top: 10px; + left: calc(50% - 10px); + } + svg { + position: absolute; + pointer-events: all; + .nodes { + text { + font: 12px sans-serif; + } + .bullet { + cursor: pointer; + &:hover { + r: 4px; + } + } + .with-children { + text { + cursor: pointer; + } + .bullet { + &:hover { + r: 3px; + } + } + } + } + .links { + fill: none; + stroke: black; + stroke-width: 0.5px; + stroke-opacity: 0.5; + } + } + } + + .D3_pie { + width: 100%; + height: calc(100vh - 172px); + position: relative; + display: grid; + grid-template-rows: 40px 1fr; + grid-template-columns: 50% 50%; + svg { + pointer-events: all; + .detailsCircle { + fill-opacity: 0.35; + fill: none; + } + .detailsText { + text-anchor: middle; + } + } + } + + .D3_sunburst { + width: 100%; + height: calc(100vh - 172px); + overflow: auto; + display: grid; + grid-template-rows: 40px 1fr; + grid-template-columns: 50% 50%; + svg { + position: sticky; + top: 40px; + pointer-events: all; + .slices { + path { + stroke: none; + cursor: pointer; + } + } + } + } + + .D3_pie, .D3_sunburst { + .switch { + padding: 9px 0; + align-self: center; + background: $background-color; + position: sticky; + top: 0; + } + .legend { + height: 100%; + overflow: auto; + display: flex; + flex-flow: column wrap; + align-content: flex-start; + > div { + cursor: default; + padding-right: 10px; + height: 1.4em; + overflow: hidden; + transition: height .3s ease, opacity .3s ease; + &.v-enter, &.v-leave-to { + opacity: 0; + height: 0; + } + &:hover, &.active { + background: $secondary-color-light; + } + .square { + display: inline-block; + vertical-align: middle; + width: 1em; + height: 1em; + border: 1px solid black; + margin-right: 5px; + } + } + } + } + + #tagsRestitution { + margin: 0; + height: calc(100vh - 194px); + > .col { + height: 100%; + margin: 0; + padding: 15px 0; + overflow: auto; + .chip { + opacity: 0.5; + padding-left: 5px; + &.active { + opacity: 1; + } + transition: opacity 0.3s; + [type="checkbox"] { + display: none; + + span { + font-size: inherit; + padding-left: 25px; + &::before, &::after { + content: ''; + position: absolute; + left: 0; + top: 0; + margin: 4px; + width: 16px; + height: 16px; + z-index: 0; + -webkit-transition: .28s ease; + transition: .28s ease; + border-radius: 50%; + } + } + &:checked + span { + &::before { + border-color: white; + transform: none; + } + &::after { + transform: scale(0.5); + background-color: white; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/sass/components/_badges.scss b/src/main/webapp/WEB-INF/sass/components/_badges.scss new file mode 100644 index 0000000..ffed87d --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_badges.scss @@ -0,0 +1,55 @@ +// Badges +span.badge { + min-width: 3rem; + padding: 0 6px; + margin-left: 14px; + text-align: center; + font-size: 1rem; + line-height: $badge-height; + height: $badge-height; + color: color('grey', 'darken-1'); + float: right; + box-sizing: border-box; + + &.new { + font-weight: 300; + font-size: 0.8rem; + color: #fff; + background-color: $badge-bg-color; + border-radius: 2px; + } + &.new:after { + content: " new"; + } + + &[data-badge-caption]::after { + content: " " attr(data-badge-caption); + } +} + +// Special cases +nav ul a span.badge { + display: inline-block; + float: none; + margin-left: 4px; + line-height: $badge-height; + height: $badge-height; + -webkit-font-smoothing: auto; +} + +// Line height centering +.collection-item span.badge { + margin-top: calc(#{$collection-line-height / 2} - #{$badge-height / 2}); +} +.collapsible span.badge { + margin-left: auto; +} +.sidenav span.badge { + margin-top: calc(#{$sidenav-line-height / 2} - #{$badge-height / 2}); +} + +table span.badge { + display: inline-block; + float: none; + margin-left: auto; +} diff --git a/src/main/webapp/WEB-INF/sass/components/_buttons.scss b/src/main/webapp/WEB-INF/sass/components/_buttons.scss new file mode 100644 index 0000000..44b80c8 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_buttons.scss @@ -0,0 +1,322 @@ +// shared styles +.btn, +.btn-flat { + border: $button-border; + border-radius: $button-radius; + display: inline-block; + height: $button-height; + line-height: $button-height; + padding: $button-padding; + text-transform: uppercase; + vertical-align: middle; + -webkit-tap-highlight-color: transparent; // Gets rid of tap active state +} + +// Disabled shared style +.btn.disabled, +.btn-floating.disabled, +.btn-large.disabled, +.btn-small.disabled, +.btn-flat.disabled, +.btn:disabled, +.btn-floating:disabled, +.btn-large:disabled, +.btn-small:disabled, +.btn-flat:disabled, +.btn[disabled], +.btn-floating[disabled], +.btn-large[disabled], +.btn-small[disabled], +.btn-flat[disabled] { + pointer-events: none; + background-color: $button-disabled-background !important; + box-shadow: none; + color: $button-disabled-color !important; + cursor: default; + &:hover { + background-color: $button-disabled-background !important; + color: $button-disabled-color !important; + } +} + +// Shared icon styles +.btn, +.btn-floating, +.btn-large, +.btn-small, +.btn-flat { + font-size: $button-font-size; + outline: 0; + i { + font-size: $button-icon-font-size; + line-height: inherit; + } +} + +// Shared focus button style +.btn, +.btn-floating { + &:focus { + background-color: darken($button-raised-background, 10%); + } +} + +// Raised Button +.btn { + text-decoration: none; + color: $button-raised-color; + background-color: $button-raised-background; + text-align: center; + letter-spacing: .5px; + @extend .z-depth-1; + transition: background-color .2s ease-out; + cursor: pointer; + &:hover { + background-color: $button-raised-background-hover; + @extend .z-depth-1-half; + } +} + +// Floating button +.btn-floating { + &:hover { + background-color: $button-floating-background-hover; + @extend .z-depth-1-half; + } + &:before { + border-radius: 0; + } + &.btn-large { + &.halfway-fab { + bottom: -$button-floating-large-size / 2; + } + width: $button-floating-large-size; + height: $button-floating-large-size; + padding: 0; + i { + line-height: $button-floating-large-size; + } + } + + &.btn-small { + &.halfway-fab { + bottom: -$button-floating-small-size / 2; + } + width: $button-floating-small-size; + height: $button-floating-small-size; + i { + line-height: $button-floating-small-size; + } + } + + &.halfway-fab { + &.left { + right: auto; + left: 24px; + } + position: absolute; + right: 24px; + bottom: -$button-floating-size / 2; + } + display: inline-block; + color: $button-floating-color; + position: relative; + overflow: hidden; + z-index: 1; + width: $button-floating-size; + height: $button-floating-size; + line-height: $button-floating-size; + padding: 0; + background-color: $button-floating-background; + border-radius: $button-floating-radius; + @extend .z-depth-1; + transition: background-color .3s; + cursor: pointer; + vertical-align: middle; + i { + width: inherit; + display: inline-block; + text-align: center; + color: $button-floating-color; + font-size: $button-large-icon-font-size; + line-height: $button-floating-size; + } +} + +// button fix +button.btn-floating { + border: $button-border; +} + +// Fixed Action Button +.fixed-action-btn { + &.active { + ul { + visibility: visible; + } + } + + // Directions + &.direction-left, + &.direction-right { + padding: 0 0 0 15px; + ul { + text-align: right; + right: 64px; + top: 50%; + transform: translateY(-50%); + height: 100%; + left: auto; + /*width 100% only goes to width of button container */ + width: 500px; + li { + display: inline-block; + margin: 7.5px 15px 0 0; + } + } + } + &.direction-right { + padding: 0 15px 0 0; + ul { + text-align: left; + direction: rtl; + left: 64px; + right: auto; + li { + margin: 7.5px 0 0 15px; + } + } + } + &.direction-bottom { + padding: 0 0 15px 0; + ul { + top: 64px; + bottom: auto; + display: flex; + flex-direction: column-reverse; + li { + margin: 15px 0 0 0; + } + } + } + &.toolbar { + &.active { + &>a i { + opacity: 0; + } + } + padding: 0; + height: $button-floating-large-size; + ul { + display: flex; + top: 0; + bottom: 0; + z-index: 1; + li { + flex: 1; + display: inline-block; + margin: 0; + height: 100%; + transition: none; + a { + display: block; + overflow: hidden; + position: relative; + width: 100%; + height: 100%; + background-color: transparent; + box-shadow: none; + color: #fff; + line-height: $button-floating-large-size; + z-index: 1; + i { + line-height: inherit; + } + } + } + } + } + position: fixed; + right: 23px; + bottom: 23px; + padding-top: 15px; + margin-bottom: 0; + z-index: 997; + ul { + left: 0; + right: 0; + text-align: center; + position: absolute; + bottom: 64px; + margin: 0; + visibility: hidden; + li { + margin-bottom: 15px; + } + a.btn-floating { + opacity: 0; + } + } + .fab-backdrop { + position: absolute; + top: 0; + left: 0; + z-index: -1; + width: $button-floating-size; + height: $button-floating-size; + background-color: $button-floating-background; + border-radius: $button-floating-radius; + transform: scale(0); + } +} + +// Flat button +.btn-flat { + box-shadow: none; + background-color: transparent; + color: $button-flat-color; + cursor: pointer; + transition: background-color .2s; + &:focus, + &:hover { + box-shadow: none; + } + &:focus { + background-color: rgba(0, 0, 0, .1); + } + &.disabled, + &.btn-flat[disabled] { + background-color: transparent !important; + color: $button-flat-disabled-color !important; + cursor: default; + } +} + +// Large button +.btn-large { + @extend .btn; + height: $button-large-height; + line-height: $button-large-height; + font-size: $button-large-font-size; + padding: 0 28px; + + i { + font-size: $button-large-icon-font-size; + } +} + +// Small button +.btn-small { + @extend .btn; + height: $button-small-height; + line-height: $button-small-height; + font-size: $button-small-font-size; + i { + font-size: $button-small-icon-font-size; + } +} + +// Block button +.btn-block { + display: block; +} diff --git a/src/main/webapp/WEB-INF/sass/components/_cards.scss b/src/main/webapp/WEB-INF/sass/components/_cards.scss new file mode 100644 index 0000000..fcbf28e --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_cards.scss @@ -0,0 +1,195 @@ + + +.card-panel { + transition: box-shadow .25s; + padding: $card-padding; + margin: $element-top-margin 0 $element-bottom-margin 0; + border-radius: 2px; + @extend .z-depth-1; + background-color: $card-bg-color; +} + +.card { + position: relative; + margin: $element-top-margin 0 $element-bottom-margin 0; + background-color: $card-bg-color; + transition: box-shadow .25s; + border-radius: 2px; + @extend .z-depth-1; + + + .card-title { + font-size: 24px; + font-weight: 300; + &.activator { + cursor: pointer; + } + } + + // Card Sizes + &.small, &.medium, &.large { + position: relative; + + .card-image { + max-height: 60%; + overflow: hidden; + } + .card-image + .card-content { + max-height: 40%; + } + .card-content { + max-height: 100%; + overflow: hidden; + } + .card-action { + position: absolute; + bottom: 0; + left: 0; + right: 0; + } + } + + &.small { + height: 300px; + } + + &.medium { + height: 400px; + } + + &.large { + height: 500px; + } + + // Horizontal Cards + &.horizontal { + &.small, &.medium, &.large { + .card-image { + height: 100%; + max-height: none; + overflow: visible; + + img { + height: 100%; + } + } + } + + display: flex; + + .card-image { + max-width: 50%; + img { + border-radius: 2px 0 0 2px; + max-width: 100%; + width: auto; + } + } + + .card-stacked { + display: flex; + flex-direction: column; + flex: 1; + position: relative; + + .card-content { + flex-grow: 1; + } + } + } + + // Sticky Action Section + &.sticky-action { + .card-action { + z-index: 2; + } + + .card-reveal { + z-index: 1; + padding-bottom: 64px; + } + } + + + + + .card-image { + position: relative; + + // Image background for content + img { + display: block; + border-radius: 2px 2px 0 0; + position: relative; + left: 0; + right: 0; + top: 0; + bottom: 0; + width: 100%; + } + + .card-title { + color: $card-bg-color; + position: absolute; + bottom: 0; + left: 0; + max-width: 100%; + padding: $card-padding; + } + } + + .card-content { + padding: $card-padding; + border-radius: 0 0 2px 2px; + + p { + margin: 0; + } + .card-title { + display: block; + line-height: 32px; + margin-bottom: 8px; + + i { + line-height: 32px; + } + } + } + + .card-action { + &:last-child { + border-radius: 0 0 2px 2px; + } + background-color: inherit; // Use inherit to inherit color classes + border-top: 1px solid rgba(160,160,160,.2); + position: relative; + padding: 16px $card-padding; + + a:not(.btn):not(.btn-large):not(.btn-floating) { + color: $card-link-color; + margin-right: $card-padding; + transition: color .3s ease; + text-transform: uppercase; + + &:hover { color: $card-link-color-light; } + } + } + + .card-reveal { + padding: $card-padding; + position: absolute; + background-color: $card-bg-color; + width: 100%; + overflow-y: auto; + left: 0; + top: 100%; + height: 100%; + z-index: 3; + display: none; + + .card-title { + cursor: pointer; + display: block; + } + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_carousel.scss b/src/main/webapp/WEB-INF/sass/components/_carousel.scss new file mode 100644 index 0000000..cc36d4b --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_carousel.scss @@ -0,0 +1,90 @@ +.carousel { + &.carousel-slider { + top: 0; + left: 0; + + .carousel-fixed-item { + &.with-indicators { + bottom: 68px; + } + + position: absolute; + left: 0; + right: 0; + bottom: 20px; + z-index: 1; + } + + .carousel-item { + width: 100%; + height: 100%; + min-height: $carousel-height; + position: absolute; + top: 0; + left: 0; + + h2 { + font-size: 24px; + font-weight: 500; + line-height: 32px; + } + + p { + font-size: 15px; + } + } + } + + overflow: hidden; + position: relative; + width: 100%; + height: $carousel-height; + perspective: 500px; + transform-style: preserve-3d; + transform-origin: 0% 50%; + + .carousel-item { + visibility: hidden; + width: $carousel-item-width; + height: $carousel-item-height; + position: absolute; + top: 0; + left: 0; + + & > img { + width: 100%; + } + } + + .indicators { + position: absolute; + text-align: center; + left: 0; + right: 0; + bottom: 0; + margin: 0; + + .indicator-item { + &.active { + background-color: #fff; + } + + display: inline-block; + position: relative; + cursor: pointer; + height: 8px; + width: 8px; + margin: 24px 4px; + background-color: rgba(255,255,255,.5); + + transition: background-color .3s; + border-radius: 50%; + } + } + + // Materialbox compatibility + &.scrolling .carousel-item .materialboxed, + .carousel-item:not(.active) .materialboxed { + pointer-events: none; + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_chips.scss b/src/main/webapp/WEB-INF/sass/components/_chips.scss new file mode 100644 index 0000000..27744a8 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_chips.scss @@ -0,0 +1,90 @@ +.chip { + &:focus { + outline: none; + background-color: $chip-selected-color; + color: #fff; + } + + display: inline-block; + height: 32px; + font-size: 13px; + font-weight: 500; + color: rgba(0,0,0,.6); + line-height: 32px; + padding: 0 12px; + border-radius: 16px; + background-color: $chip-bg-color; + margin-bottom: $chip-margin; + margin-right: $chip-margin; + + > img { + float: left; + margin: 0 8px 0 -12px; + height: 32px; + width: 32px; + border-radius: 50%; + } + + .close { + cursor: pointer; + float: right; + font-size: 16px; + line-height: 32px; + padding-left: 8px; + } +} + +.chips { + border: none; + border-bottom: 1px solid $chip-border-color; + box-shadow: none; + margin: $input-margin; + min-height: 45px; + outline: none; + transition: all .3s; + + &.focus { + border-bottom: 1px solid $chip-selected-color; + box-shadow: 0 1px 0 0 $chip-selected-color; + } + + &:hover { + cursor: text; + } + + .input { + background: none; + border: 0; + color: rgba(0,0,0,.6); + display: inline-block; + font-size: $input-font-size; + height: $input-height; + line-height: 32px; + outline: 0; + margin: 0; + padding: 0 !important; + width: 120px !important; + } + + .input:focus { + border: 0 !important; + box-shadow: none !important; + } + + // Autocomplete + .autocomplete-content { + margin-top: 0; + margin-bottom: 0; + } +} + +// Form prefix +.prefix ~ .chips { + margin-left: 3rem; + width: 92%; + width: calc(100% - 3rem); +} +.chips:empty ~ label { + font-size: 0.8rem; + transform: translateY(-140%); +} diff --git a/src/main/webapp/WEB-INF/sass/components/_collapsible.scss b/src/main/webapp/WEB-INF/sass/components/_collapsible.scss new file mode 100644 index 0000000..024324f --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_collapsible.scss @@ -0,0 +1,91 @@ +.collapsible { + border-top: 1px solid $collapsible-border-color; + border-right: 1px solid $collapsible-border-color; + border-left: 1px solid $collapsible-border-color; + margin: $element-top-margin 0 $element-bottom-margin 0; + @extend .z-depth-1; +} + +.collapsible-header { + &:focus { + outline: 0 + } + + display: flex; + cursor: pointer; + -webkit-tap-highlight-color: transparent; + line-height: 1.5; + padding: 1rem; + background-color: $collapsible-header-color; + border-bottom: 1px solid $collapsible-border-color; + + i { + width: 2rem; + font-size: 1.6rem; + display: inline-block; + text-align: center; + margin-right: 1rem; + } +} +.keyboard-focused .collapsible-header:focus { + background-color: #eee; +} + +.collapsible-body { + display: none; + border-bottom: 1px solid $collapsible-border-color; + box-sizing: border-box; + padding: 2rem; +} + +// Sidenav collapsible styling +.sidenav, +.sidenav.fixed { + + .collapsible { + border: none; + box-shadow: none; + + li { padding: 0; } + } + + .collapsible-header { + background-color: transparent; + border: none; + line-height: inherit; + height: inherit; + padding: 0 $sidenav-padding; + + &:hover { background-color: rgba(0,0,0,.05); } + i { line-height: inherit; } + } + + .collapsible-body { + border: 0; + background-color: $collapsible-header-color; + + li a { + padding: 0 (7.5px + $sidenav-padding) + 0 (15px + $sidenav-padding); + } + } + +} + +// Popout Collapsible + +.collapsible.popout { + border: none; + box-shadow: none; + > li { + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + // transform: scaleX(.92); + margin: 0 24px; + transition: margin .35s cubic-bezier(0.250, 0.460, 0.450, 0.940); + } + > li.active { + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, 0.18), 0 4px 15px 0 rgba(0, 0, 0, 0.15); + margin: 16px 0; + // transform: scaleX(1); + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_color-classes.scss b/src/main/webapp/WEB-INF/sass/components/_color-classes.scss new file mode 100644 index 0000000..155cecd --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_color-classes.scss @@ -0,0 +1,32 @@ +// Color Classes + +@each $color_name, $color in $colors { + @each $color_type, $color_value in $color { + @if $color_type == "base" { + .#{$color_name} { + background-color: $color_value !important; + } + .#{$color_name}-text { + color: $color_value !important; + } + } + @else if $color_name != "shades" { + .#{$color_name}.#{$color_type} { + background-color: $color_value !important; + } + .#{$color_name}-text.text-#{$color_type} { + color: $color_value !important; + } + } + } +} + +// Shade classes +@each $color, $color_value in $shades { + .#{$color} { + background-color: $color_value !important; + } + .#{$color}-text { + color: $color_value !important; + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_color-variables.scss b/src/main/webapp/WEB-INF/sass/components/_color-variables.scss new file mode 100644 index 0000000..062f6a5 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_color-variables.scss @@ -0,0 +1,370 @@ +// Google Color Palette defined: http://www.google.com/design/spec/style/color.html + +$materialize-red: ( + "base": #e51c23, + "lighten-5": #fdeaeb, + "lighten-4": #f8c1c3, + "lighten-3": #f3989b, + "lighten-2": #ee6e73, + "lighten-1": #ea454b, + "darken-1": #d0181e, + "darken-2": #b9151b, + "darken-3": #a21318, + "darken-4": #8b1014, +); + +$red: ( + "base": #F44336, + "lighten-5": #FFEBEE, + "lighten-4": #FFCDD2, + "lighten-3": #EF9A9A, + "lighten-2": #E57373, + "lighten-1": #EF5350, + "darken-1": #E53935, + "darken-2": #D32F2F, + "darken-3": #C62828, + "darken-4": #B71C1C, + "accent-1": #FF8A80, + "accent-2": #FF5252, + "accent-3": #FF1744, + "accent-4": #D50000 +); + +$pink: ( + "base": #e91e63, + "lighten-5": #fce4ec, + "lighten-4": #f8bbd0, + "lighten-3": #f48fb1, + "lighten-2": #f06292, + "lighten-1": #ec407a, + "darken-1": #d81b60, + "darken-2": #c2185b, + "darken-3": #ad1457, + "darken-4": #880e4f, + "accent-1": #ff80ab, + "accent-2": #ff4081, + "accent-3": #f50057, + "accent-4": #c51162 +); + +$purple: ( + "base": #9c27b0, + "lighten-5": #f3e5f5, + "lighten-4": #e1bee7, + "lighten-3": #ce93d8, + "lighten-2": #ba68c8, + "lighten-1": #ab47bc, + "darken-1": #8e24aa, + "darken-2": #7b1fa2, + "darken-3": #6a1b9a, + "darken-4": #4a148c, + "accent-1": #ea80fc, + "accent-2": #e040fb, + "accent-3": #d500f9, + "accent-4": #aa00ff +); + +$deep-purple: ( + "base": #673ab7, + "lighten-5": #ede7f6, + "lighten-4": #d1c4e9, + "lighten-3": #b39ddb, + "lighten-2": #9575cd, + "lighten-1": #7e57c2, + "darken-1": #5e35b1, + "darken-2": #512da8, + "darken-3": #4527a0, + "darken-4": #311b92, + "accent-1": #b388ff, + "accent-2": #7c4dff, + "accent-3": #651fff, + "accent-4": #6200ea +); + +$indigo: ( + "base": #3f51b5, + "lighten-5": #e8eaf6, + "lighten-4": #c5cae9, + "lighten-3": #9fa8da, + "lighten-2": #7986cb, + "lighten-1": #5c6bc0, + "darken-1": #3949ab, + "darken-2": #303f9f, + "darken-3": #283593, + "darken-4": #1a237e, + "accent-1": #8c9eff, + "accent-2": #536dfe, + "accent-3": #3d5afe, + "accent-4": #304ffe +); + +$blue: ( + "base": #2196F3, + "lighten-5": #E3F2FD, + "lighten-4": #BBDEFB, + "lighten-3": #90CAF9, + "lighten-2": #64B5F6, + "lighten-1": #42A5F5, + "darken-1": #1E88E5, + "darken-2": #1976D2, + "darken-3": #1565C0, + "darken-4": #0D47A1, + "accent-1": #82B1FF, + "accent-2": #448AFF, + "accent-3": #2979FF, + "accent-4": #2962FF +); + +$light-blue: ( + "base": #03a9f4, + "lighten-5": #e1f5fe, + "lighten-4": #b3e5fc, + "lighten-3": #81d4fa, + "lighten-2": #4fc3f7, + "lighten-1": #29b6f6, + "darken-1": #039be5, + "darken-2": #0288d1, + "darken-3": #0277bd, + "darken-4": #01579b, + "accent-1": #80d8ff, + "accent-2": #40c4ff, + "accent-3": #00b0ff, + "accent-4": #0091ea +); + +$cyan: ( + "base": #00bcd4, + "lighten-5": #e0f7fa, + "lighten-4": #b2ebf2, + "lighten-3": #80deea, + "lighten-2": #4dd0e1, + "lighten-1": #26c6da, + "darken-1": #00acc1, + "darken-2": #0097a7, + "darken-3": #00838f, + "darken-4": #006064, + "accent-1": #84ffff, + "accent-2": #18ffff, + "accent-3": #00e5ff, + "accent-4": #00b8d4 +); + +$teal: ( + "base": #009688, + "lighten-5": #e0f2f1, + "lighten-4": #b2dfdb, + "lighten-3": #80cbc4, + "lighten-2": #4db6ac, + "lighten-1": #26a69a, + "darken-1": #00897b, + "darken-2": #00796b, + "darken-3": #00695c, + "darken-4": #004d40, + "accent-1": #a7ffeb, + "accent-2": #64ffda, + "accent-3": #1de9b6, + "accent-4": #00bfa5 +); + +$green: ( + "base": #4CAF50, + "lighten-5": #E8F5E9, + "lighten-4": #C8E6C9, + "lighten-3": #A5D6A7, + "lighten-2": #81C784, + "lighten-1": #66BB6A, + "darken-1": #43A047, + "darken-2": #388E3C, + "darken-3": #2E7D32, + "darken-4": #1B5E20, + "accent-1": #B9F6CA, + "accent-2": #69F0AE, + "accent-3": #00E676, + "accent-4": #00C853 +); + +$light-green: ( + "base": #8bc34a, + "lighten-5": #f1f8e9, + "lighten-4": #dcedc8, + "lighten-3": #c5e1a5, + "lighten-2": #aed581, + "lighten-1": #9ccc65, + "darken-1": #7cb342, + "darken-2": #689f38, + "darken-3": #558b2f, + "darken-4": #33691e, + "accent-1": #ccff90, + "accent-2": #b2ff59, + "accent-3": #76ff03, + "accent-4": #64dd17 +); + +$lime: ( + "base": #cddc39, + "lighten-5": #f9fbe7, + "lighten-4": #f0f4c3, + "lighten-3": #e6ee9c, + "lighten-2": #dce775, + "lighten-1": #d4e157, + "darken-1": #c0ca33, + "darken-2": #afb42b, + "darken-3": #9e9d24, + "darken-4": #827717, + "accent-1": #f4ff81, + "accent-2": #eeff41, + "accent-3": #c6ff00, + "accent-4": #aeea00 +); + +$yellow: ( + "base": #ffeb3b, + "lighten-5": #fffde7, + "lighten-4": #fff9c4, + "lighten-3": #fff59d, + "lighten-2": #fff176, + "lighten-1": #ffee58, + "darken-1": #fdd835, + "darken-2": #fbc02d, + "darken-3": #f9a825, + "darken-4": #f57f17, + "accent-1": #ffff8d, + "accent-2": #ffff00, + "accent-3": #ffea00, + "accent-4": #ffd600 +); + +$amber: ( + "base": #ffc107, + "lighten-5": #fff8e1, + "lighten-4": #ffecb3, + "lighten-3": #ffe082, + "lighten-2": #ffd54f, + "lighten-1": #ffca28, + "darken-1": #ffb300, + "darken-2": #ffa000, + "darken-3": #ff8f00, + "darken-4": #ff6f00, + "accent-1": #ffe57f, + "accent-2": #ffd740, + "accent-3": #ffc400, + "accent-4": #ffab00 +); + +$orange: ( + "base": #ff9800, + "lighten-5": #fff3e0, + "lighten-4": #ffe0b2, + "lighten-3": #ffcc80, + "lighten-2": #ffb74d, + "lighten-1": #ffa726, + "darken-1": #fb8c00, + "darken-2": #f57c00, + "darken-3": #ef6c00, + "darken-4": #e65100, + "accent-1": #ffd180, + "accent-2": #ffab40, + "accent-3": #ff9100, + "accent-4": #ff6d00 +); + +$deep-orange: ( + "base": #ff5722, + "lighten-5": #fbe9e7, + "lighten-4": #ffccbc, + "lighten-3": #ffab91, + "lighten-2": #ff8a65, + "lighten-1": #ff7043, + "darken-1": #f4511e, + "darken-2": #e64a19, + "darken-3": #d84315, + "darken-4": #bf360c, + "accent-1": #ff9e80, + "accent-2": #ff6e40, + "accent-3": #ff3d00, + "accent-4": #dd2c00 +); + +$brown: ( + "base": #795548, + "lighten-5": #efebe9, + "lighten-4": #d7ccc8, + "lighten-3": #bcaaa4, + "lighten-2": #a1887f, + "lighten-1": #8d6e63, + "darken-1": #6d4c41, + "darken-2": #5d4037, + "darken-3": #4e342e, + "darken-4": #3e2723 +); + +$blue-grey: ( + "base": #607d8b, + "lighten-5": #eceff1, + "lighten-4": #cfd8dc, + "lighten-3": #b0bec5, + "lighten-2": #90a4ae, + "lighten-1": #78909c, + "darken-1": #546e7a, + "darken-2": #455a64, + "darken-3": #37474f, + "darken-4": #263238 +); + +$grey: ( + "base": #9e9e9e, + "lighten-5": #fafafa, + "lighten-4": #f5f5f5, + "lighten-3": #eeeeee, + "lighten-2": #e0e0e0, + "lighten-1": #bdbdbd, + "darken-1": #757575, + "darken-2": #616161, + "darken-3": #424242, + "darken-4": #212121 +); + +$shades: ( + "black": #000000, + "white": #FFFFFF, + "transparent": transparent +); + +$colors: ( + "materialize-red": $materialize-red, + "red": $red, + "pink": $pink, + "purple": $purple, + "deep-purple": $deep-purple, + "indigo": $indigo, + "blue": $blue, + "light-blue": $light-blue, + "cyan": $cyan, + "teal": $teal, + "green": $green, + "light-green": $light-green, + "lime": $lime, + "yellow": $yellow, + "amber": $amber, + "orange": $orange, + "deep-orange": $deep-orange, + "brown": $brown, + "blue-grey": $blue-grey, + "grey": $grey, + "shades": $shades +) !default; + + +// usage: color("name_of_color", "type_of_color") +// to avoid to repeating map-get($colors, ...) + +@function color($color, $type) { + @if map-has-key($colors, $color) { + $curr_color: map-get($colors, $color); + @if map-has-key($curr_color, $type) { + @return map-get($curr_color, $type); + } + } + @warn "Unknown `#{$color}` - `#{$type}` in $colors."; + @return null; +} diff --git a/src/main/webapp/WEB-INF/sass/components/_datepicker.scss b/src/main/webapp/WEB-INF/sass/components/_datepicker.scss new file mode 100644 index 0000000..d2c920b --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_datepicker.scss @@ -0,0 +1,191 @@ +/* Modal */ +.datepicker-modal { + max-width: 325px; + min-width: 300px; + max-height: none; +} + +.datepicker-container.modal-content { + display: flex; + flex-direction: column; + padding: 0; +} + +.datepicker-controls { + display: flex; + justify-content: space-between; + width: 280px; + margin: 0 auto; + + .selects-container { + display: flex; + } + + .select-wrapper { + input { + &:focus { + border-bottom: none; + } + border-bottom: none; + text-align: center; + margin: 0; + } + + .caret { + display: none; + } + } + + .select-year input { + width: 50px; + } + + .select-month input { + width: 70px; + } +} + +.month-prev, .month-next { + margin-top: 4px; + cursor: pointer; + background-color: transparent; + border: none; +} + + +/* Date Display */ +.datepicker-date-display { + flex: 1 auto; + background-color: $secondary-color; + color: #fff; + padding: 20px 22px; + font-weight: 500; + + .year-text { + display: block; + font-size: 1.5rem; + line-height: 25px; + color: $datepicker-year; + } + + .date-text { + display: block; + font-size: 2.8rem; + line-height: 47px; + font-weight: 500; + } +} + + +/* Calendar */ +.datepicker-calendar-container { + flex: 2.5 auto; +} + +.datepicker-table { + width: 280px; + font-size: 1rem; + margin: 0 auto; + + thead { + border-bottom: none; + } + + th { + padding: 10px 5px; + text-align: center; + } + + tr { + border: none; + } + + abbr { + text-decoration: none; + color: $datepicker-calendar-header-color; + } + + td { + &.is-today { + color: $secondary-color; + } + + &.is-selected { + background-color: $secondary-color; + color: #fff; + } + + &.is-outside-current-month, + &.is-disabled { + color: $datepicker-disabled-day-color; + pointer-events: none; + } + + border-radius: 50%; + padding: 0; + } +} + +.datepicker-day-button { + &:focus { + background-color: $datepicker-day-focus; + } + + background-color: transparent; + border: none; + line-height: 38px; + display: block; + width: 100%; + border-radius: 50%; + padding: 0 5px; + cursor: pointer; + color: inherit; +} + + +/* Footer */ +.datepicker-footer { + width: 280px; + margin: 0 auto; + padding-bottom: 5px; + display: flex; + justify-content: space-between; +} + +.datepicker-cancel, +.datepicker-clear, +.datepicker-today, +.datepicker-done { + color: $secondary-color; + padding: 0 1rem; +} + +.datepicker-clear { + color: $error-color; +} + + +/* Media Queries */ +@media #{$medium-and-up} { + .datepicker-modal { + max-width: 625px; + } + + .datepicker-container.modal-content { + flex-direction: row; + } + + .datepicker-date-display { + flex: 0 1 270px; + } + + .datepicker-controls, + .datepicker-table, + .datepicker-footer { + width: 320px; + } + + .datepicker-day-button { + line-height: 44px; + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_dropdown.scss b/src/main/webapp/WEB-INF/sass/components/_dropdown.scss new file mode 100644 index 0000000..0caae65 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_dropdown.scss @@ -0,0 +1,85 @@ +.dropdown-content { + &:focus { + outline: 0; + } + + + @extend .z-depth-1; + background-color: $dropdown-bg-color; + margin: 0; + display: none; + min-width: 100px; + overflow-y: auto; + opacity: 0; + position: absolute; + left: 0; + top: 0; + z-index: 9999; // TODO: Check if this doesn't break other things + transform-origin: 0 0; + + + li { + &:hover, &.active { + background-color: $dropdown-hover-bg-color; + } + + &:focus { + outline: none; + } + + &.divider { + min-height: 0; + height: 1px; + } + + & > a, & > span { + font-size: 16px; + color: $dropdown-color; + display: block; + line-height: 22px; + padding: (($dropdown-item-height - 22) / 2) 16px; + } + + & > span > label { + top: 1px; + left: 0; + height: 18px; + } + + // Icon alignment override + & > a > i { + height: inherit; + line-height: inherit; + float: left; + margin: 0 24px 0 0; + width: 24px; + } + + + clear: both; + color: $off-black; + cursor: pointer; + min-height: $dropdown-item-height; + line-height: 1.5rem; + width: 100%; + text-align: left; + } +} + +body.keyboard-focused { + .dropdown-content li:focus { + background-color: darken($dropdown-hover-bg-color, 8%); + } +} + +// Input field specificity bugfix +.input-field.col .dropdown-content [type="checkbox"] + label { + top: 1px; + left: 0; + height: 18px; + transform: none; +} + +.dropdown-trigger { + cursor: pointer; +} \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/sass/components/_global.scss b/src/main/webapp/WEB-INF/sass/components/_global.scss new file mode 100644 index 0000000..39f33db --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_global.scss @@ -0,0 +1,769 @@ +//Default styles + +html { + box-sizing: border-box; +} +*, *:before, *:after { + box-sizing: inherit; +} + +body { + // display: flex; + // min-height: 100vh; + // flex-direction: column; +} + +main { + // flex: 1 0 auto; +} + +button, +input, +optgroup, +select, +textarea { + font-family: $font-stack; +} + +ul { + &:not(.browser-default) { + padding-left: 0; + list-style-type: none; + + & > li { + list-style-type: none; + } + } +} + +a { + color: $link-color; + text-decoration: none; + + // Gets rid of tap active state + -webkit-tap-highlight-color: transparent; +} + + +// Positioning +.valign-wrapper { + display: flex; + align-items: center; +} + + +// classic clearfix +.clearfix { + clear: both; +} + + +// Z-levels +.z-depth-0 { + box-shadow: none !important; +} + +/* 2dp elevation modified*/ +.z-depth-1 { + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), + 0 3px 1px -2px rgba(0,0,0,0.12), + 0 1px 5px 0 rgba(0,0,0,0.2); +} +.z-depth-1-half { + box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.14), 0 1px 7px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -1px rgba(0, 0, 0, 0.2); +} + +/* 6dp elevation modified*/ +.z-depth-2 { + box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14), + 0 1px 10px 0 rgba(0,0,0,0.12), + 0 2px 4px -1px rgba(0,0,0,0.3); +} + +/* 12dp elevation modified*/ +.z-depth-3 { + box-shadow: 0 8px 17px 2px rgba(0,0,0,0.14), + 0 3px 14px 2px rgba(0,0,0,0.12), + 0 5px 5px -3px rgba(0, 0, 0, 0.2); +} + +/* 16dp elevation */ +.z-depth-4 { + box-shadow: 0 16px 24px 2px rgba(0,0,0,0.14), + 0 6px 30px 5px rgba(0,0,0,0.12), + 0 8px 10px -7px rgba(0,0,0,0.2); +} + +/* 24dp elevation */ +.z-depth-5 { + box-shadow: 0 24px 38px 3px rgba(0,0,0,0.14), + 0 9px 46px 8px rgba(0,0,0,0.12), + 0 11px 15px -7px rgba(0,0,0,0.2); +} + +.hoverable { + transition: box-shadow .25s; + + &:hover { + box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); + } +} + +// Dividers + +.divider { + height: 1px; + overflow: hidden; + background-color: color("grey", "lighten-2"); +} + + +// Blockquote + +blockquote { + margin: 20px 0; + padding-left: 1.5rem; + border-left: 5px solid $primary-color; +} + +// Icon Styles + +i { + line-height: inherit; + + &.left { + float: left; + margin-right: 15px; + } + &.right { + float: right; + margin-left: 15px; + } + &.tiny { + font-size: 1rem; + } + &.small { + font-size: 2rem; + } + &.medium { + font-size: 4rem; + } + &.large { + font-size: 6rem; + } +} + +// Images +img.responsive-img, +video.responsive-video { + max-width: 100%; + height: auto; +} + + +// Pagination + +.pagination { + + li { + display: inline-block; + border-radius: 2px; + text-align: center; + vertical-align: top; + height: 30px; + + a { + color: #444; + display: inline-block; + font-size: 1.2rem; + padding: 0 10px; + line-height: 30px; + } + + &.active a { color: #fff; } + + &.active { background-color: $primary-color; } + + &.disabled a { + cursor: default; + color: #999; + } + + i { + font-size: 2rem; + } + } + + + li.pages ul li { + display: inline-block; + float: none; + } +} +@media #{$medium-and-down} { + .pagination { + width: 100%; + + li.prev, + li.next { + width: 10%; + } + + li.pages { + width: 80%; + overflow: hidden; + white-space: nowrap; + } + } +} + +// Breadcrumbs +.breadcrumb { + font-size: 18px; + color: rgba(255,255,255, .7); + + i, + [class^="mdi-"], [class*="mdi-"], + i.material-icons { + display: inline-block; + float: left; + font-size: 24px; + } + + &:before { + content: '\E5CC'; + color: rgba(255,255,255, .7); + vertical-align: top; + display: inline-block; + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 25px; + margin: 0 10px 0 8px; + -webkit-font-smoothing: antialiased; + } + + &:first-child:before { + display: none; + } + + &:last-child { + color: #fff; + } +} + +// Parallax +.parallax-container { + position: relative; + overflow: hidden; + height: 500px; + + .parallax { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: -1; + + img { + opacity: 0; + position: absolute; + left: 50%; + bottom: 0; + min-width: 100%; + min-height: 100%; + transform: translate3d(0,0,0); + transform: translateX(-50%); + } + } +} + +// Pushpin +.pin-top, .pin-bottom { + position: relative; +} +.pinned { + position: fixed !important; +} + +/********************* + Transition Classes +**********************/ + +ul.staggered-list li { + opacity: 0; +} + +.fade-in { + opacity: 0; + transform-origin: 0 50%; +} + + +/********************* + Media Query Classes +**********************/ +.hide-on-small-only, .hide-on-small-and-down { + @media #{$small-and-down} { + display: none !important; + } +} +.hide-on-med-and-down { + @media #{$medium-and-down} { + display: none !important; + } +} +.hide-on-med-and-up { + @media #{$medium-and-up} { + display: none !important; + } +} +.hide-on-med-only { + @media only screen and (min-width: $small-screen) and (max-width: $medium-screen) { + display: none !important; + } +} +.hide-on-large-only { + @media #{$large-and-up} { + display: none !important; + } +} +.hide-on-extra-large-only { + @media #{$extra-large-and-up} { + display: none !important; + } +} +.show-on-extra-large { + @media #{$extra-large-and-up} { + display: block !important; + } +} +.show-on-large { + @media #{$large-and-up} { + display: block !important; + } +} +.show-on-medium { + @media only screen and (min-width: $small-screen) and (max-width: $medium-screen) { + display: block !important; + } +} +.show-on-small { + @media #{$small-and-down} { + display: block !important; + } +} +.show-on-medium-and-up { + @media #{$medium-and-up} { + display: block !important; + } +} +.show-on-medium-and-down { + @media #{$medium-and-down} { + display: block !important; + } +} + + +// Center text on mobile +.center-on-small-only { + @media #{$small-and-down} { + text-align: center; + } +} + +// Footer +.page-footer { + padding-top: 20px; + color: $footer-font-color; + background-color: $footer-bg-color; + + .footer-copyright { + overflow: hidden; + min-height: 50px; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0px; + color: $footer-copyright-font-color; + background-color: $footer-copyright-bg-color; + } +} + +// Tables +table, th, td { + border: none; +} + +table { + width:100%; + display: table; + border-collapse: collapse; + border-spacing: 0; + + &.striped { + tr { + border-bottom: none; + } + + > tbody { + > tr:nth-child(odd) { + background-color: $table-striped-color; + } + + > tr > td { + border-radius: 0; + } + } + } + + &.highlight > tbody > tr { + transition: background-color .25s ease; + &:hover { + background-color: $table-striped-color; + } + } + + &.centered { + thead tr th, tbody tr td { + text-align: center; + } + } +} + +tr { + border-bottom: 1px solid $table-border-color; +} + +td, th{ + padding: 15px 5px; + display: table-cell; + text-align: left; + vertical-align: middle; + border-radius: 2px; +} + +// Responsive Table +@media #{$medium-and-down} { + + table.responsive-table { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + display: block; + position: relative; + + td:empty:before { + content: '\00a0'; + } + + th, + td { + margin: 0; + vertical-align: top; + } + + th { text-align: left; } + thead { + display: block; + float: left; + + tr { + display: block; + padding: 0 10px 0 0; + + th::before { + content: "\00a0"; + } + } + } + tbody { + display: block; + width: auto; + position: relative; + overflow-x: auto; + white-space: nowrap; + + tr { + display: inline-block; + vertical-align: top; + } + } + th { + display: block; + text-align: right; + } + td { + display: block; + min-height: 1.25em; + text-align: left; + } + tr { + border-bottom: none; + padding: 0 10px; + } + + /* sort out borders */ + thead { + border: 0; + border-right: 1px solid $table-border-color; + } + } + +} + + +// Collections +.collection { + margin: $element-top-margin 0 $element-bottom-margin 0; + border: 1px solid $collection-border-color; + border-radius: 2px; + overflow: hidden; + position: relative; + + .collection-item { + background-color: $collection-bg-color; + line-height: $collection-line-height; + padding: 10px 20px; + margin: 0; + border-bottom: 1px solid $collection-border-color; + + // Avatar Collection + &.avatar { + min-height: 84px; + padding-left: 72px; + position: relative; + + // Don't style circles inside preloader classes. + &:not(.circle-clipper) > .circle, + :not(.circle-clipper) > .circle { + position: absolute; + width: 42px; + height: 42px; + overflow: hidden; + left: 15px; + display: inline-block; + vertical-align: middle; + } + i.circle { + font-size: 18px; + line-height: 42px; + color: #fff; + background-color: #999; + text-align: center; + } + + + .title { + font-size: 16px; + } + + p { + margin: 0; + } + + .secondary-content { + position: absolute; + top: 16px; + right: 16px; + } + + } + + + &:last-child { + border-bottom: none; + } + + &.active { + background-color: $collection-active-bg-color; + color: $collection-active-color; + + .secondary-content { + color: #fff; + } + } + } + a.collection-item{ + display: block; + transition: .25s; + color: $collection-link-color; + &:not(.active) { + &:hover { + background-color: $collection-hover-bg-color; + } + } + } + + &.with-header { + .collection-header { + background-color: $collection-bg-color; + border-bottom: 1px solid $collection-border-color; + padding: 10px 20px; + } + .collection-item { + padding-left: 30px; + } + .collection-item.avatar { + padding-left: 72px; + } + } + +} +// Made less specific to allow easier overriding +.secondary-content { + float: right; + color: $secondary-color; +} +.collapsible .collection { + margin: 0; + border: none; +} + + + +// Responsive Videos +.video-container { + position: relative; + padding-bottom: 56.25%; + height: 0; + overflow: hidden; + + iframe, object, embed { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } +} + +// Progress Bar +.progress { + position: relative; + height: 4px; + display: block; + width: 100%; + background-color: lighten($progress-bar-color, 40%); + border-radius: 2px; + margin: $element-top-margin 0 $element-bottom-margin 0; + overflow: hidden; + .determinate { + position: absolute; + top: 0; + left: 0; + bottom: 0; + background-color: $progress-bar-color; + transition: width .3s linear; + } + .indeterminate { + background-color: $progress-bar-color; + &:before { + content: ''; + position: absolute; + background-color: inherit; + top: 0; + left:0; + bottom: 0; + will-change: left, right; + // Custom bezier + animation: indeterminate 2.1s cubic-bezier(0.650, 0.815, 0.735, 0.395) infinite; + + } + &:after { + content: ''; + position: absolute; + background-color: inherit; + top: 0; + left:0; + bottom: 0; + will-change: left, right; + // Custom bezier + animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.840, 0.440, 1.000) infinite; + animation-delay: 1.15s; + } + } +} +@keyframes indeterminate { + 0% { + left: -35%; + right:100%; + } + 60% { + left: 100%; + right: -90%; + } + 100% { + left: 100%; + right: -90%; + } +} + +@keyframes indeterminate-short { + 0% { + left: -200%; + right: 100%; + } + 60% { + left: 107%; + right: -8%; + } + 100% { + left: 107%; + right: -8%; + } +} + + +/******************* + Utility Classes +*******************/ + +.hide { + display: none !important; +} + +// Text Align +.left-align { + text-align: left; +} +.right-align { + text-align: right +} +.center, .center-align { + text-align: center; +} + +.left { + float: left !important; +} +.right { + float: right !important; +} + +// No Text Select +.no-select { + user-select: none; +} + +.circle { + border-radius: 50%; +} + +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} + +.truncate { + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.no-padding { + padding: 0 !important; +} diff --git a/src/main/webapp/WEB-INF/sass/components/_grid.scss b/src/main/webapp/WEB-INF/sass/components/_grid.scss new file mode 100644 index 0000000..8892f05 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_grid.scss @@ -0,0 +1,156 @@ +.container { + margin: 0 auto; + max-width: 1280px; + width: 90%; +} +@media #{$medium-and-up} { + .container { + width: 85%; + } +} +@media #{$large-and-up} { + .container { + width: 70%; + } +} +.col .row { + margin-left: (-1 * $gutter-width / 2); + margin-right: (-1 * $gutter-width / 2); +} + +.section { + padding-top: 1rem; + padding-bottom: 1rem; + + &.no-pad { + padding: 0; + } + &.no-pad-bot { + padding-bottom: 0; + } + &.no-pad-top { + padding-top: 0; + } +} + + +// Mixins to eliminate code repitition +@mixin reset-offset { + margin-left: auto; + left: auto; + right: auto; +} +@mixin grid-classes($size, $i, $perc) { + &.offset-#{$size}#{$i} { + margin-left: $perc; + } + &.pull-#{$size}#{$i} { + right: $perc; + } + &.push-#{$size}#{$i} { + left: $perc; + } +} + + +.row { + margin-left: auto; + margin-right: auto; + margin-bottom: 20px; + + // Clear floating children + &:after { + content: ""; + display: table; + clear: both; + } + + .col { + float: left; + box-sizing: border-box; + padding: 0 $gutter-width / 2; + min-height: 1px; + + &[class*="push-"], + &[class*="pull-"] { + position: relative; + } + + $i: 1; + @while $i <= $num-cols { + $perc: unquote((100 / ($num-cols / $i)) + "%"); + &.s#{$i} { + width: $perc; + @include reset-offset; + } + $i: $i + 1; + } + + $i: 1; + @while $i <= $num-cols { + $perc: unquote((100 / ($num-cols / $i)) + "%"); + @include grid-classes("s", $i, $perc); + $i: $i + 1; + } + + @media #{$medium-and-up} { + + $i: 1; + @while $i <= $num-cols { + $perc: unquote((100 / ($num-cols / $i)) + "%"); + &.m#{$i} { + width: $perc; + @include reset-offset; + } + $i: $i + 1 + } + + $i: 1; + @while $i <= $num-cols { + $perc: unquote((100 / ($num-cols / $i)) + "%"); + @include grid-classes("m", $i, $perc); + $i: $i + 1; + } + } + + @media #{$large-and-up} { + + $i: 1; + @while $i <= $num-cols { + $perc: unquote((100 / ($num-cols / $i)) + "%"); + &.l#{$i} { + width: $perc; + @include reset-offset; + } + $i: $i + 1; + } + + $i: 1; + @while $i <= $num-cols { + $perc: unquote((100 / ($num-cols / $i)) + "%"); + @include grid-classes("l", $i, $perc); + $i: $i + 1; + } + } + + @media #{$extra-large-and-up} { + + $i: 1; + @while $i <= $num-cols { + $perc: unquote((100 / ($num-cols / $i)) + "%"); + &.xl#{$i} { + width: $perc; + @include reset-offset; + } + $i: $i + 1; + } + + $i: 1; + @while $i <= $num-cols { + $perc: unquote((100 / ($num-cols / $i)) + "%"); + @include grid-classes("xl", $i, $perc); + $i: $i + 1; + } + } + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_icons-material-design.scss b/src/main/webapp/WEB-INF/sass/components/_icons-material-design.scss new file mode 100644 index 0000000..d8d91c1 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_icons-material-design.scss @@ -0,0 +1,5 @@ +/* This is needed for some mobile phones to display the Google Icon font properly */ +.material-icons { + text-rendering: optimizeLegibility; + font-feature-settings: 'liga'; +} diff --git a/src/main/webapp/WEB-INF/sass/components/_materialbox.scss b/src/main/webapp/WEB-INF/sass/components/_materialbox.scss new file mode 100644 index 0000000..0ebd63f --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_materialbox.scss @@ -0,0 +1,43 @@ +.materialboxed { + &:hover { + &:not(.active) { + opacity: .8; + } + } + + display: block; + cursor: zoom-in; + position: relative; + transition: opacity .4s; + -webkit-backface-visibility: hidden; + + &.active { + cursor: zoom-out; + } +} + +#materialbox-overlay { + position:fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: #292929; + z-index: 1000; + will-change: opacity; +} + +.materialbox-caption { + position: fixed; + display: none; + color: #fff; + line-height: 50px; + bottom: 0; + left: 0; + width: 100%; + text-align: center; + padding: 0% 15%; + height: 50px; + z-index: 1000; + -webkit-font-smoothing: antialiased; +} \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/sass/components/_modal.scss b/src/main/webapp/WEB-INF/sass/components/_modal.scss new file mode 100644 index 0000000..38cf3ce --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_modal.scss @@ -0,0 +1,94 @@ +.modal { + &:focus { + outline: none; + } + + @extend .z-depth-5; + + display: none; + position: fixed; + left: 0; + right: 0; + background-color: #fafafa; + padding: 0; + max-height: 70%; + width: 55%; + margin: auto; + overflow-y: auto; + + border-radius: 2px; + will-change: top, opacity; + + @media #{$medium-and-down} { + width: 80%; + } + + h1,h2,h3,h4 { + margin-top: 0; + } + + .modal-content { + padding: 24px; + } + .modal-close { + cursor: pointer; + } + + .modal-footer { + border-radius: 0 0 2px 2px; + background-color: #fafafa; + padding: 4px 6px; + height: 56px; + width: 100%; + text-align: right; + + .btn, .btn-flat { + margin: 6px 0; + } + } +} +.modal-overlay { + position: fixed; + z-index: 999; + top: -25%; + left: 0; + bottom: 0; + right: 0; + height: 125%; + width: 100%; + background: #000; + display: none; + + will-change: opacity; +} + +// Modal with fixed action footer +.modal.modal-fixed-footer { + padding: 0; + height: 70%; + + .modal-content { + position: absolute; + height: calc(100% - 56px); + max-height: 100%; + width: 100%; + overflow-y: auto; + } + + .modal-footer { + border-top: 1px solid rgba(0,0,0,.1); + position: absolute; + bottom: 0; + } +} + +// Modal Bottom Sheet Style +.modal.bottom-sheet { + top: auto; + bottom: -100%; + margin: 0; + width: 100%; + max-height: 45%; + border-radius: 0; + will-change: bottom, opacity; +} diff --git a/src/main/webapp/WEB-INF/sass/components/_navbar.scss b/src/main/webapp/WEB-INF/sass/components/_navbar.scss new file mode 100644 index 0000000..0317bb2 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_navbar.scss @@ -0,0 +1,208 @@ +nav { + &.nav-extended { + height: auto; + + .nav-wrapper { + min-height: $navbar-height-mobile; + height: auto; + } + + .nav-content { + position: relative; + line-height: normal; + } + } + + color: $navbar-font-color; + @extend .z-depth-1; + background-color: $primary-color; + width: 100%; + height: $navbar-height-mobile; + line-height: $navbar-line-height-mobile; + + a { color: $navbar-font-color; } + + i, + [class^="mdi-"], [class*="mdi-"], + i.material-icons { + display: block; + font-size: 24px; + height: $navbar-height-mobile; + line-height: $navbar-line-height-mobile; + } + + .nav-wrapper { + position: relative; + height: 100%; + } + + @media #{$large-and-up} { + a.sidenav-trigger { display: none; } + } + + + // Collapse button + .sidenav-trigger { + float: left; + position: relative; + z-index: 1; + height: $navbar-height-mobile; + margin: 0 18px; + + i { + height: $navbar-height-mobile; + line-height: $navbar-line-height-mobile; + } + } + + + // Logo + .brand-logo { + position: absolute; + color: $navbar-font-color; + display: inline-block; + font-size: $navbar-brand-font-size; + padding: 0; + + &.center { + left: 50%; + transform: translateX(-50%); + } + + @media #{$medium-and-down} { + left: 50%; + transform: translateX(-50%); + + &.left, &.right { + padding: 0; + transform: none; + } + + &.left { left: 0.5rem; } + &.right { + right: 0.5rem; + left: auto; + } + } + + &.right { + right: 0.5rem; + padding: 0; + } + + i, + [class^="mdi-"], [class*="mdi-"], + i.material-icons { + float: left; + margin-right: 15px; + } + } + + + // Title + .nav-title { + display: inline-block; + font-size: 32px; + padding: 28px 0; + } + + + // Navbar Links + ul { + margin: 0; + + li { + transition: background-color .3s; + float: left; + padding: 0; + + &.active { + background-color: rgba(0,0,0,.1); + } + } + a { + transition: background-color .3s; + font-size: $navbar-font-size; + color: $navbar-font-color; + display: block; + padding: 0 15px; + cursor: pointer; + + &.btn, &.btn-large, &.btn-flat, &.btn-floating { + margin-top: -2px; + margin-left: 15px; + margin-right: 15px; + + & > .material-icons { + height: inherit; + line-height: inherit; + } + } + + &:hover { + background-color: rgba(0,0,0,.1); + } + } + + &.left { + float: left; + } + } + + // Navbar Search Form + form { + height: 100%; + } + + .input-field { + margin: 0; + height: 100%; + + input { + height: 100%; + font-size: 1.2rem; + border: none; + padding-left: 2rem; + + &:focus, &[type=text]:valid, &[type=password]:valid, + &[type=email]:valid, &[type=url]:valid, &[type=date]:valid { + border: none; + box-shadow: none; + } + } + + label { + top: 0; + left: 0; + + i { + color: rgba(255,255,255,.7); + transition: color .3s; + } + &.active i { color: $navbar-font-color; } + } + } +} + +// Fixed Navbar +.navbar-fixed { + position: relative; + height: $navbar-height-mobile; + z-index: 997; + + nav { + position: fixed; + } +} +@media #{$medium-and-up} { + nav.nav-extended .nav-wrapper { + min-height: $navbar-height; + } + nav, nav .nav-wrapper i, nav a.sidenav-trigger, nav a.sidenav-trigger i { + height: $navbar-height; + line-height: $navbar-line-height; + } + .navbar-fixed { + height: $navbar-height; + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_normalize.scss b/src/main/webapp/WEB-INF/sass/components/_normalize.scss new file mode 100644 index 0000000..fa4e73d --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_normalize.scss @@ -0,0 +1,447 @@ +/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in + * IE on Windows Phone and in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers (opinionated). + */ + +body { + margin: 0; +} + +/** + * Add the correct display in IE 9-. + */ + +article, +aside, +footer, +header, +nav, +section { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in IE. + */ + +figcaption, +figure, +main { /* 1 */ + display: block; +} + +/** + * Add the correct margin in IE 8. + */ + +figure { + margin: 1em 40px; +} + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * 1. Remove the gray background on active links in IE 10. + * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. + */ + +a { + background-color: transparent; /* 1 */ + -webkit-text-decoration-skip: objects; /* 2 */ +} + +/** + * 1. Remove the bottom border in Chrome 57- and Firefox 39-. + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Prevent the duplicate application of `bolder` by the next rule in Safari 6. + */ + +b, +strong { + font-weight: inherit; +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font style in Android 4.3-. + */ + +dfn { + font-style: italic; +} + +/** + * Add the correct background and color in IE 9-. + */ + +mark { + background-color: #ff0; + color: #000; +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +audio, +video { + display: inline-block; +} + +/** + * Add the correct display in iOS 4-7. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Remove the border on images inside links in IE 10-. + */ + +img { + border-style: none; +} + +/** + * Hide the overflow in IE. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: sans-serif; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` + * controls in Android 4. + * 2. Correct the inability to style clickable types in iOS and Safari. + */ + +button, +html [type="button"], /* 1 */ +[type="reset"], +[type="submit"] { + -webkit-appearance: button; /* 2 */ +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * 1. Add the correct display in IE 9-. + * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Remove the default vertical scrollbar in IE. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10-. + * 2. Remove the padding in IE 10-. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. + */ + +details, /* 1 */ +menu { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Scripting + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +canvas { + display: inline-block; +} + +/** + * Add the correct display in IE. + */ + +template { + display: none; +} + +/* Hidden + ========================================================================== */ + +/** + * Add the correct display in IE 10-. + */ + +[hidden] { + display: none; +} diff --git a/src/main/webapp/WEB-INF/sass/components/_preloader.scss b/src/main/webapp/WEB-INF/sass/components/_preloader.scss new file mode 100644 index 0000000..fbe862d --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_preloader.scss @@ -0,0 +1,334 @@ +/* + @license + Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt + */ + +/**************************/ +/* STYLES FOR THE SPINNER */ +/**************************/ + +/* + * Constants: + * STROKEWIDTH = 3px + * ARCSIZE = 270 degrees (amount of circle the arc takes up) + * ARCTIME = 1333ms (time it takes to expand and contract arc) + * ARCSTARTROT = 216 degrees (how much the start location of the arc + * should rotate each time, 216 gives us a + * 5 pointed star shape (it's 360/5 * 3). + * For a 7 pointed star, we might do + * 360/7 * 3 = 154.286) + * CONTAINERWIDTH = 28px + * SHRINK_TIME = 400ms + */ + + +.preloader-wrapper { + display: inline-block; + position: relative; + width: 50px; + height: 50px; + + &.small { + width: 36px; + height: 36px; + } + + &.big { + width: 64px; + height: 64px; + } + + &.active { + /* duration: 360 * ARCTIME / (ARCSTARTROT + (360-ARCSIZE)) */ + -webkit-animation: container-rotate 1568ms linear infinite; + animation: container-rotate 1568ms linear infinite; + } +} + +@-webkit-keyframes container-rotate { + to { -webkit-transform: rotate(360deg) } +} + +@keyframes container-rotate { + to { transform: rotate(360deg) } +} + +.spinner-layer { + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + border-color: $spinner-default-color; +} + +.spinner-blue, +.spinner-blue-only { + border-color: #4285f4; +} + +.spinner-red, +.spinner-red-only { + border-color: #db4437; +} + +.spinner-yellow, +.spinner-yellow-only { + border-color: #f4b400; +} + +.spinner-green, +.spinner-green-only { + border-color: #0f9d58; +} + +/** + * IMPORTANT NOTE ABOUT CSS ANIMATION PROPERTIES (keanulee): + * + * iOS Safari (tested on iOS 8.1) does not handle animation-delay very well - it doesn't + * guarantee that the animation will start _exactly_ after that value. So we avoid using + * animation-delay and instead set custom keyframes for each color (as redundant as it + * seems). + * + * We write out each animation in full (instead of separating animation-name, + * animation-duration, etc.) because under the polyfill, Safari does not recognize those + * specific properties properly, treats them as -webkit-animation, and overrides the + * other animation rules. See https://github.com/Polymer/platform/issues/53. + */ +.active .spinner-layer.spinner-blue { + /* durations: 4 * ARCTIME */ + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, blue-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, blue-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; +} + +.active .spinner-layer.spinner-red { + /* durations: 4 * ARCTIME */ + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, red-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, red-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; +} + +.active .spinner-layer.spinner-yellow { + /* durations: 4 * ARCTIME */ + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, yellow-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, yellow-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; +} + +.active .spinner-layer.spinner-green { + /* durations: 4 * ARCTIME */ + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, green-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, green-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; +} + +.active .spinner-layer, +.active .spinner-layer.spinner-blue-only, +.active .spinner-layer.spinner-red-only, +.active .spinner-layer.spinner-yellow-only, +.active .spinner-layer.spinner-green-only { + /* durations: 4 * ARCTIME */ + opacity: 1; + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; +} + +@-webkit-keyframes fill-unfill-rotate { + 12.5% { -webkit-transform: rotate(135deg); } /* 0.5 * ARCSIZE */ + 25% { -webkit-transform: rotate(270deg); } /* 1 * ARCSIZE */ + 37.5% { -webkit-transform: rotate(405deg); } /* 1.5 * ARCSIZE */ + 50% { -webkit-transform: rotate(540deg); } /* 2 * ARCSIZE */ + 62.5% { -webkit-transform: rotate(675deg); } /* 2.5 * ARCSIZE */ + 75% { -webkit-transform: rotate(810deg); } /* 3 * ARCSIZE */ + 87.5% { -webkit-transform: rotate(945deg); } /* 3.5 * ARCSIZE */ + to { -webkit-transform: rotate(1080deg); } /* 4 * ARCSIZE */ +} + +@keyframes fill-unfill-rotate { + 12.5% { transform: rotate(135deg); } /* 0.5 * ARCSIZE */ + 25% { transform: rotate(270deg); } /* 1 * ARCSIZE */ + 37.5% { transform: rotate(405deg); } /* 1.5 * ARCSIZE */ + 50% { transform: rotate(540deg); } /* 2 * ARCSIZE */ + 62.5% { transform: rotate(675deg); } /* 2.5 * ARCSIZE */ + 75% { transform: rotate(810deg); } /* 3 * ARCSIZE */ + 87.5% { transform: rotate(945deg); } /* 3.5 * ARCSIZE */ + to { transform: rotate(1080deg); } /* 4 * ARCSIZE */ +} + +@-webkit-keyframes blue-fade-in-out { + from { opacity: 1; } + 25% { opacity: 1; } + 26% { opacity: 0; } + 89% { opacity: 0; } + 90% { opacity: 1; } + 100% { opacity: 1; } +} + +@keyframes blue-fade-in-out { + from { opacity: 1; } + 25% { opacity: 1; } + 26% { opacity: 0; } + 89% { opacity: 0; } + 90% { opacity: 1; } + 100% { opacity: 1; } +} + +@-webkit-keyframes red-fade-in-out { + from { opacity: 0; } + 15% { opacity: 0; } + 25% { opacity: 1; } + 50% { opacity: 1; } + 51% { opacity: 0; } +} + +@keyframes red-fade-in-out { + from { opacity: 0; } + 15% { opacity: 0; } + 25% { opacity: 1; } + 50% { opacity: 1; } + 51% { opacity: 0; } +} + +@-webkit-keyframes yellow-fade-in-out { + from { opacity: 0; } + 40% { opacity: 0; } + 50% { opacity: 1; } + 75% { opacity: 1; } + 76% { opacity: 0; } +} + +@keyframes yellow-fade-in-out { + from { opacity: 0; } + 40% { opacity: 0; } + 50% { opacity: 1; } + 75% { opacity: 1; } + 76% { opacity: 0; } +} + +@-webkit-keyframes green-fade-in-out { + from { opacity: 0; } + 65% { opacity: 0; } + 75% { opacity: 1; } + 90% { opacity: 1; } + 100% { opacity: 0; } +} + +@keyframes green-fade-in-out { + from { opacity: 0; } + 65% { opacity: 0; } + 75% { opacity: 1; } + 90% { opacity: 1; } + 100% { opacity: 0; } +} + +/** + * Patch the gap that appear between the two adjacent div.circle-clipper while the + * spinner is rotating (appears on Chrome 38, Safari 7.1, and IE 11). + */ +.gap-patch { + position: absolute; + top: 0; + left: 45%; + width: 10%; + height: 100%; + overflow: hidden; + border-color: inherit; +} + +.gap-patch .circle { + width: 1000%; + left: -450%; +} + +.circle-clipper { + display: inline-block; + position: relative; + width: 50%; + height: 100%; + overflow: hidden; + border-color: inherit; + + .circle { + width: 200%; + height: 100%; + border-width: 3px; /* STROKEWIDTH */ + border-style: solid; + border-color: inherit; + border-bottom-color: transparent !important; + border-radius: 50%; + -webkit-animation: none; + animation: none; + position: absolute; + top: 0; + right: 0; + bottom: 0; + } + + &.left .circle { + left: 0; + border-right-color: transparent !important; + -webkit-transform: rotate(129deg); + transform: rotate(129deg); + } + &.right .circle { + left: -100%; + border-left-color: transparent !important; + -webkit-transform: rotate(-129deg); + transform: rotate(-129deg); + } +} + + + +.active .circle-clipper.left .circle { + /* duration: ARCTIME */ + -webkit-animation: left-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; + animation: left-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; +} + +.active .circle-clipper.right .circle { + /* duration: ARCTIME */ + -webkit-animation: right-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; + animation: right-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both; +} + +@-webkit-keyframes left-spin { + from { -webkit-transform: rotate(130deg); } + 50% { -webkit-transform: rotate(-5deg); } + to { -webkit-transform: rotate(130deg); } +} + +@keyframes left-spin { + from { transform: rotate(130deg); } + 50% { transform: rotate(-5deg); } + to { transform: rotate(130deg); } +} + +@-webkit-keyframes right-spin { + from { -webkit-transform: rotate(-130deg); } + 50% { -webkit-transform: rotate(5deg); } + to { -webkit-transform: rotate(-130deg); } +} + +@keyframes right-spin { + from { transform: rotate(-130deg); } + 50% { transform: rotate(5deg); } + to { transform: rotate(-130deg); } +} + +#spinnerContainer.cooldown { + /* duration: SHRINK_TIME */ + -webkit-animation: container-rotate 1568ms linear infinite, fade-out 400ms cubic-bezier(0.4, 0.0, 0.2, 1); + animation: container-rotate 1568ms linear infinite, fade-out 400ms cubic-bezier(0.4, 0.0, 0.2, 1); +} + +@-webkit-keyframes fade-out { + from { opacity: 1; } + to { opacity: 0; } +} + +@keyframes fade-out { + from { opacity: 1; } + to { opacity: 0; } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_pulse.scss b/src/main/webapp/WEB-INF/sass/components/_pulse.scss new file mode 100644 index 0000000..a690f36 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_pulse.scss @@ -0,0 +1,34 @@ +.pulse { + &::before { + content: ''; + display: block; + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + background-color: inherit; + border-radius: inherit; + transition: opacity .3s, transform .3s; + animation: pulse-animation 1s cubic-bezier(0.24, 0, 0.38, 1) infinite; + z-index: -1; + } + + overflow: visible; + position: relative; +} + +@keyframes pulse-animation { + 0% { + opacity: 1; + transform: scale(1); + } + 50% { + opacity: 0; + transform: scale(1.5); + } + 100% { + opacity: 0; + transform: scale(1.5); + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_sidenav.scss b/src/main/webapp/WEB-INF/sass/components/_sidenav.scss new file mode 100644 index 0000000..98a71d8 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_sidenav.scss @@ -0,0 +1,216 @@ +.sidenav { + position: fixed; + width: $sidenav-width; + left: 0; + top: 0; + margin: 0; + transform: translateX(-100%); + height: 100%; + height: calc(100% + 60px); + height: -moz-calc(100%); //Temporary Firefox Fix + padding-bottom: 60px; + background-color: $sidenav-bg-color; + z-index: 999; + overflow-y: auto; + will-change: transform; + backface-visibility: hidden; + transform: translateX(-105%); + + @extend .z-depth-1; + + // Right Align + &.right-aligned { + right: 0; + transform: translateX(105%); + left: auto; + transform: translateX(100%); + } + + .collapsible { + margin: 0; + } + + + li { + float: none; + line-height: $sidenav-line-height; + + &.active { background-color: rgba(0,0,0,.05); } + } + + li > a { + color: $sidenav-font-color; + display: block; + font-size: $sidenav-font-size; + font-weight: 500; + height: $sidenav-item-height; + line-height: $sidenav-line-height; + padding: 0 ($sidenav-padding * 2); + + &:hover { background-color: rgba(0,0,0,.05);} + + &.btn, &.btn-large, &.btn-flat, &.btn-floating { + margin: 10px 15px; + } + + &.btn, + &.btn-large, + &.btn-floating { color: $button-raised-color; } + &.btn-flat { color: $button-flat-color; } + + &.btn:hover, + &.btn-large:hover { background-color: lighten($button-raised-background, 5%); } + &.btn-floating:hover { background-color: $button-raised-background; } + + & > i, + & > [class^="mdi-"], li > a > [class*="mdi-"], + & > i.material-icons { + float: left; + height: $sidenav-item-height; + line-height: $sidenav-line-height; + margin: 0 ($sidenav-padding * 2) 0 0; + width: $sidenav-item-height / 2; + color: rgba(0,0,0,.54); + } + } + + + .divider { + margin: ($sidenav-padding / 2) 0 0 0; + } + + .subheader { + &:hover { + background-color: transparent; + } + + cursor: initial; + pointer-events: none; + color: rgba(0,0,0,.54); + font-size: $sidenav-font-size; + font-weight: 500; + line-height: $sidenav-line-height; + } + + .user-view { + position: relative; + padding: ($sidenav-padding * 2) ($sidenav-padding * 2) 0; + margin-bottom: $sidenav-padding / 2; + + & > a { + &:hover { background-color: transparent; } + height: auto; + padding: 0; + } + + .background { + overflow: hidden; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: -1; + } + + .circle, .name, .email { + display: block; + } + + .circle { + height: 64px; + width: 64px; + } + + .name, + .email { + font-size: $sidenav-font-size; + line-height: $sidenav-line-height / 2; + } + + .name { + margin-top: 16px; + font-weight: 500; + } + + .email { + padding-bottom: 16px; + font-weight: 400; + } + } +} + + +// Touch interaction +.drag-target { + // Right Align + &.right-aligned { + right: 0; + } + + height: 100%; + width: 10px; + position: fixed; + top: 0; + z-index: 998; +} + + +// Fixed Sidenav shown +.sidenav.sidenav-fixed { + // Right Align + &.right-aligned { + right: 0; + left: auto; + } + + left: 0; + transform: translateX(0); + position: fixed; +} + +// Fixed Sidenav hide on smaller +@media #{$medium-and-down} { + .sidenav { + &.sidenav-fixed { + transform: translateX(-105%); + + &.right-aligned { + transform: translateX(105%); + } + } + + > a { + padding: 0 $sidenav-padding; + } + + .user-view { + padding: $sidenav-padding $sidenav-padding 0; + } + } +} + + +.sidenav .collapsible-body > ul:not(.collapsible) > li.active, +.sidenav.sidenav-fixed .collapsible-body > ul:not(.collapsible) > li.active { + background-color: $primary-color; + a { + color: $sidenav-bg-color; + } +} +.sidenav .collapsible-body { + padding: 0; +} + + +.sidenav-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + opacity: 0; + height: 120vh; + background-color: rgba(0,0,0,.5); + z-index: 997; + display: none; +} diff --git a/src/main/webapp/WEB-INF/sass/components/_slider.scss b/src/main/webapp/WEB-INF/sass/components/_slider.scss new file mode 100644 index 0000000..2265cdb --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_slider.scss @@ -0,0 +1,92 @@ +.slider { + position: relative; + height: 400px; + width: 100%; + + // Fullscreen slider + &.fullscreen { + height: 100%; + width: 100%; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + + ul.slides { + height: 100%; + } + + ul.indicators { + z-index: 2; + bottom: 30px; + } + } + + .slides { + background-color: $slider-bg-color; + margin: 0; + height: 400px; + + li { + opacity: 0; + position: absolute; + top: 0; + left: 0; + z-index: 1; + width: 100%; + height: inherit; + overflow: hidden; + + img { + height: 100%; + width: 100%; + background-size: cover; + background-position: center; + } + + .caption { + color: #fff; + position: absolute; + top: 15%; + left: 15%; + width: 70%; + opacity: 0; + + p { color: $slider-bg-color-light; } + } + + &.active { + z-index: 2; + } + } + } + + + .indicators { + position: absolute; + text-align: center; + left: 0; + right: 0; + bottom: 0; + margin: 0; + + .indicator-item { + display: inline-block; + position: relative; + cursor: pointer; + height: 16px; + width: 16px; + margin: 0 12px; + background-color: $slider-bg-color-light; + + transition: background-color .3s; + border-radius: 50%; + + &.active { + background-color: $slider-indicator-color; + } + } + } + +} \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/sass/components/_table_of_contents.scss b/src/main/webapp/WEB-INF/sass/components/_table_of_contents.scss new file mode 100644 index 0000000..638009d --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_table_of_contents.scss @@ -0,0 +1,33 @@ +/*************** + Nav List +***************/ +.table-of-contents { + &.fixed { + position: fixed; + } + + li { + padding: 2px 0; + } + a { + display: inline-block; + font-weight: 300; + color: #757575; + padding-left: 16px; + height: 1.5rem; + line-height: 1.5rem; + letter-spacing: .4; + display: inline-block; + + &:hover { + color: lighten(#757575, 20%); + padding-left: 15px; + border-left: 1px solid $primary-color; + } + &.active { + font-weight: 500; + padding-left: 14px; + border-left: 2px solid $primary-color; + } + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_tabs.scss b/src/main/webapp/WEB-INF/sass/components/_tabs.scss new file mode 100644 index 0000000..072d4b6 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_tabs.scss @@ -0,0 +1,99 @@ +.tabs { + &.tabs-transparent { + background-color: transparent; + + .tab a, + .tab.disabled a, + .tab.disabled a:hover { + color: rgba(255,255,255,0.7); + } + + .tab a:hover, + .tab a.active { + color: #fff; + } + + .indicator { + background-color: #fff; + } + } + + &.tabs-fixed-width { + display: flex; + + .tab { + flex-grow: 1; + } + } + + position: relative; + overflow-x: auto; + overflow-y: hidden; + height: 48px; + width: 100%; + background-color: $tabs-bg-color; + margin: 0 auto; + white-space: nowrap; + + .tab { + display: inline-block; + text-align: center; + line-height: 48px; + height: 48px; + padding: 0; + margin: 0; + text-transform: uppercase; + + a { + &:focus, + &:focus.active { + background-color: transparentize($tabs-underline-color, .8); + outline: none; + } + + &:hover, + &.active { + background-color: transparent; + color: $tabs-text-color; + } + + color: rgba($tabs-text-color, .7); + display: block; + width: 100%; + height: 100%; + padding: 0 24px; + font-size: 14px; + text-overflow: ellipsis; + overflow: hidden; + transition: color .28s ease, background-color .28s ease; + } + + &.disabled a, + &.disabled a:hover { + color: rgba($tabs-text-color, .4); + cursor: default; + } + } + .indicator { + position: absolute; + bottom: 0; + height: 2px; + background-color: $tabs-underline-color; + will-change: left, right; + } +} + +// Fixed Sidenav hide on smaller +@media #{$medium-and-down} { + .tabs { + display: flex; + + .tab { + flex-grow: 1; + + a { + padding: 0 12px; + } + } + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_tapTarget.scss b/src/main/webapp/WEB-INF/sass/components/_tapTarget.scss new file mode 100644 index 0000000..c015f34 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_tapTarget.scss @@ -0,0 +1,103 @@ +.tap-target-wrapper { + width: 800px; + height: 800px; + position: fixed; + z-index: 1000; + visibility: hidden; + transition: visibility 0s .3s; +} + +.tap-target-wrapper.open { + visibility: visible; + transition: visibility 0s; + + .tap-target { + transform: scale(1); + opacity: .95; + transition: + transform .3s cubic-bezier(.42,0,.58,1), + opacity .3s cubic-bezier(.42,0,.58,1); + } + + .tap-target-wave::before { + transform: scale(1); + } + .tap-target-wave::after { + visibility: visible; + animation: pulse-animation 1s cubic-bezier(0.24, 0, 0.38, 1) infinite; + transition: + opacity .3s, + transform .3s, + visibility 0s 1s; + } +} + +.tap-target { + position: absolute; + font-size: 1rem; + border-radius: 50%; + background-color: $primary-color; + box-shadow: 0 20px 20px 0 rgba(0,0,0,0.14), 0 10px 50px 0 rgba(0,0,0,0.12), 0 30px 10px -20px rgba(0,0,0,0.2); + width: 100%; + height: 100%; + opacity: 0; + transform: scale(0); + transition: + transform .3s cubic-bezier(.42,0,.58,1), + opacity .3s cubic-bezier(.42,0,.58,1); +} + +.tap-target-content { + position: relative; + display: table-cell; +} + +.tap-target-wave { + &::before, + &::after { + content: ''; + display: block; + position: absolute; + width: 100%; + height: 100%; + border-radius: 50%; + background-color: #ffffff; + } + &::before { + transform: scale(0); + transition: transform .3s; + } + &::after { + visibility: hidden; + transition: + opacity .3s, + transform .3s, + visibility 0s; + z-index: -1; + } + + position: absolute; + border-radius: 50%; + z-index: 10001; +} + +.tap-target-origin { + &:not(.btn), + &:not(.btn):hover { + background: none; + } + + top: 50%; + left: 50%; + transform: translate(-50%,-50%); + + z-index: 10002; + position: absolute !important; +} + +@media only screen and (max-width: 600px) { + .tap-target, .tap-target-wrapper { + width: 600px; + height: 600px; + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_timepicker.scss b/src/main/webapp/WEB-INF/sass/components/_timepicker.scss new file mode 100644 index 0000000..fa602fb --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_timepicker.scss @@ -0,0 +1,183 @@ +/* Timepicker Containers */ +.timepicker-modal { + max-width: 325px; + max-height: none; +} + +.timepicker-container.modal-content { + display: flex; + flex-direction: column; + padding: 0; +} + +.text-primary { + color: rgba(255, 255, 255, 1); +} + + +/* Clock Digital Display */ +.timepicker-digital-display { + flex: 1 auto; + background-color: $secondary-color; + padding: 10px; + font-weight: 300; +} + +.timepicker-text-container { + font-size: 4rem; + font-weight: bold; + text-align: center; + color: rgba(255, 255, 255, 0.6); + font-weight: 400; + position: relative; + user-select: none; +} + +.timepicker-span-hours, +.timepicker-span-minutes, +.timepicker-span-am-pm div { + cursor: pointer; +} + +.timepicker-span-hours { + margin-right: 3px; +} + +.timepicker-span-minutes { + margin-left: 3px; +} + +.timepicker-display-am-pm { + font-size: 1.3rem; + position: absolute; + right: 1rem; + bottom: 1rem; + font-weight: 400; +} + + +/* Analog Clock Display */ +.timepicker-analog-display { + flex: 2.5 auto; +} + +.timepicker-plate { + background-color: $timepicker-clock-plate-bg; + border-radius: 50%; + width: 270px; + height: 270px; + overflow: visible; + position: relative; + margin: auto; + margin-top: 25px; + margin-bottom: 5px; + user-select: none; +} + +.timepicker-canvas, +.timepicker-dial { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; +} +.timepicker-minutes { + visibility: hidden; +} + +.timepicker-tick { + border-radius: 50%; + color: $timepicker-clock-color; + line-height: 40px; + text-align: center; + width: 40px; + height: 40px; + position: absolute; + cursor: pointer; + font-size: 15px; +} + +.timepicker-tick.active, +.timepicker-tick:hover { + background-color: transparentize($secondary-color, .75); +} +.timepicker-dial { + transition: transform 350ms, opacity 350ms; +} +.timepicker-dial-out { + &.timepicker-hours { + transform: scale(1.1, 1.1); + } + + &.timepicker-minutes { + transform: scale(.8, .8); + } + + opacity: 0; +} +.timepicker-canvas { + transition: opacity 175ms; + + line { + stroke: $secondary-color; + stroke-width: 4; + stroke-linecap: round; + } +} +.timepicker-canvas-out { + opacity: 0.25; +} +.timepicker-canvas-bearing { + stroke: none; + fill: $secondary-color; +} +.timepicker-canvas-bg { + stroke: none; + fill: $secondary-color; +} + + +/* Footer */ +.timepicker-footer { + margin: 0 auto; + padding: 5px 1rem; + display: flex; + justify-content: space-between; +} + +.timepicker-clear { + color: $error-color; +} + +.timepicker-close { + color: $secondary-color; +} + +.timepicker-clear, +.timepicker-close { + padding: 0 20px; +} + +/* Media Queries */ +@media #{$medium-and-up} { + .timepicker-modal { + max-width: 600px; + } + + .timepicker-container.modal-content { + flex-direction: row; + } + + .timepicker-text-container { + top: 32%; + } + + .timepicker-display-am-pm { + position: relative; + right: auto; + bottom: auto; + text-align: center; + margin-top: 1.2rem; + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_toast.scss b/src/main/webapp/WEB-INF/sass/components/_toast.scss new file mode 100644 index 0000000..412400f --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_toast.scss @@ -0,0 +1,58 @@ +#toast-container { + display:block; + position: fixed; + z-index: 10000; + + @media #{$small-and-down} { + min-width: 100%; + bottom: 0%; + } + @media #{$medium-only} { + left: 5%; + bottom: 7%; + max-width: 90%; + } + @media #{$large-and-up} { + top: 10%; + right: 7%; + max-width: 86%; + } +} + +.toast { + @extend .z-depth-1; + border-radius: 2px; + top: 35px; + width: auto; + margin-top: 10px; + position: relative; + max-width:100%; + height: auto; + min-height: $toast-height; + line-height: 1.5em; + background-color: $toast-color; + padding: 10px 25px; + font-size: 1.1rem; + font-weight: 300; + color: $toast-text-color; + display: flex; + align-items: center; + justify-content: space-between; + cursor: default; + + .toast-action { + color: $toast-action-color; + font-weight: 500; + margin-right: -25px; + margin-left: 3rem; + } + + &.rounded{ + border-radius: 24px; + } + + @media #{$small-and-down} { + width: 100%; + border-radius: 0; + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_tooltip.scss b/src/main/webapp/WEB-INF/sass/components/_tooltip.scss new file mode 100644 index 0000000..5ec4299 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_tooltip.scss @@ -0,0 +1,32 @@ +.material-tooltip { + padding: 10px 8px; + font-size: 1rem; + z-index: 2000; + background-color: transparent; + border-radius: 2px; + color: #fff; + min-height: 36px; + line-height: 120%; + opacity: 0; + position: absolute; + text-align: center; + max-width: calc(100% - 4px); + overflow: hidden; + left: 0; + top: 0; + pointer-events: none; + visibility: hidden; + background-color: #323232; +} + +.backdrop { + position: absolute; + opacity: 0; + height: 7px; + width: 14px; + border-radius: 0 0 50% 50%; + background-color: #323232; + z-index: -1; + transform-origin: 50% 0%; + visibility: hidden; +} diff --git a/src/main/webapp/WEB-INF/sass/components/_transitions.scss b/src/main/webapp/WEB-INF/sass/components/_transitions.scss new file mode 100644 index 0000000..9c3660a --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_transitions.scss @@ -0,0 +1,13 @@ +// Scale transition +.scale-transition { + &.scale-out { + transform: scale(0); + transition: transform .2s !important; + } + + &.scale-in { + transform: scale(1); + } + + transition: transform .3s cubic-bezier(0.53, 0.01, 0.36, 1.63) !important; +} \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/sass/components/_typography.scss b/src/main/webapp/WEB-INF/sass/components/_typography.scss new file mode 100644 index 0000000..b9b93b3 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_typography.scss @@ -0,0 +1,60 @@ + +a { + text-decoration: none; +} + +html{ + line-height: 1.5; + + @media only screen and (min-width: 0) { + font-size: 14px; + } + + @media only screen and (min-width: $medium-screen) { + font-size: 14.5px; + } + + @media only screen and (min-width: $large-screen) { + font-size: 15px; + } + + font-family: $font-stack; + font-weight: normal; + color: $off-black; +} +h1, h2, h3, h4, h5, h6 { + font-weight: 400; + line-height: 1.3; +} + +// Header Styles +h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; } +h1 { font-size: $h1-fontsize; line-height: 110%; margin: ($h1-fontsize / 1.5) 0 ($h1-fontsize / 2.5) 0;} +h2 { font-size: $h2-fontsize; line-height: 110%; margin: ($h2-fontsize / 1.5) 0 ($h2-fontsize / 2.5) 0;} +h3 { font-size: $h3-fontsize; line-height: 110%; margin: ($h3-fontsize / 1.5) 0 ($h3-fontsize / 2.5) 0;} +h4 { font-size: $h4-fontsize; line-height: 110%; margin: ($h4-fontsize / 1.5) 0 ($h4-fontsize / 2.5) 0;} +h5 { font-size: $h5-fontsize; line-height: 110%; margin: ($h5-fontsize / 1.5) 0 ($h5-fontsize / 2.5) 0;} +h6 { font-size: $h6-fontsize; line-height: 110%; margin: ($h6-fontsize / 1.5) 0 ($h6-fontsize / 2.5) 0;} + +// Text Styles +em { font-style: italic; } +strong { font-weight: 500; } +small { font-size: 75%; } +.light { font-weight: 300; } +.thin { font-weight: 200; } + + +.flow-text{ + $i: 0; + @while $i <= $intervals { + @media only screen and (min-width : 360 + ($i * $interval-size)) { + font-size: 1.2rem * (1 + (.02 * $i)); + } + $i: $i + 1; + } + + // Handle below 360px screen + @media only screen and (max-width: 360px) { + font-size: 1.2rem; + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/_variables.scss b/src/main/webapp/WEB-INF/sass/components/_variables.scss new file mode 100644 index 0000000..4c59c12 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_variables.scss @@ -0,0 +1,349 @@ +// ========================================================================== +// Materialize variables +// ========================================================================== +// +// Table of Contents: +// +// 1. Colors +// 2. Badges +// 3. Buttons +// 4. Cards +// 5. Carousel +// 6. Collapsible +// 7. Chips +// 8. Date + Time Picker +// 9. Dropdown +// 10. Forms +// 11. Global +// 12. Grid +// 13. Navigation Bar +// 14. Side Navigation +// 15. Photo Slider +// 16. Spinners | Loaders +// 17. Tabs +// 18. Tables +// 19. Toasts +// 20. Typography +// 21. Footer +// 22. Flow Text +// 23. Collections +// 24. Progress Bar + + + +// 1. Colors +// ========================================================================== + +$primary-color: color("materialize-red", "lighten-2") !default; +$primary-color-light: lighten($primary-color, 15%) !default; +$primary-color-dark: darken($primary-color, 15%) !default; + +$secondary-color: color("teal", "lighten-1") !default; +$success-color: color("green", "base") !default; +$error-color: color("red", "base") !default; +$link-color: color("light-blue", "darken-1") !default; + + +// 2. Badges +// ========================================================================== + +$badge-bg-color: $secondary-color !default; +$badge-height: 22px !default; + + +// 3. Buttons +// ========================================================================== + +// Shared styles +$button-border: none !default; +$button-background-focus: lighten($secondary-color, 4%) !default; +$button-font-size: 14px !default; +$button-icon-font-size: 1.3rem !default; +$button-height: 36px !default; +$button-padding: 0 16px !default; +$button-radius: 2px !default; + +// Disabled styles +$button-disabled-background: #DFDFDF !default; +$button-disabled-color: #9F9F9F !default; + +// Raised buttons +$button-raised-background: $secondary-color !default; +$button-raised-background-hover: lighten($button-raised-background, 5%) !default; +$button-raised-color: #fff !default; + +// Large buttons +$button-large-font-size: 15px !default; +$button-large-icon-font-size: 1.6rem !default; +$button-large-height: $button-height * 1.5 !default; +$button-floating-large-size: 56px !default; + +// Small buttons +$button-small-font-size: 13px !default; +$button-small-icon-font-size: 1.2rem !default; +$button-small-height: $button-height * .9 !default; +$button-floating-small-size: $button-height * .9 !default; + +// Flat buttons +$button-flat-color: #343434 !default; +$button-flat-disabled-color: lighten(#999, 10%) !default; + +// Floating buttons +$button-floating-background: $secondary-color !default; +$button-floating-background-hover: $button-floating-background !default; +$button-floating-color: #fff !default; +$button-floating-size: 40px !default; +$button-floating-radius: 50% !default; + + +// 4. Cards +// ========================================================================== + +$card-padding: 24px !default; +$card-bg-color: #fff !default; +$card-link-color: color("orange", "accent-2") !default; +$card-link-color-light: lighten($card-link-color, 20%) !default; + + +// 5. Carousel +// ========================================================================== + +$carousel-height: 400px !default; +$carousel-item-height: $carousel-height / 2 !default; +$carousel-item-width: $carousel-item-height !default; + + +// 6. Collapsible +// ========================================================================== + +$collapsible-height: 3rem !default; +$collapsible-line-height: $collapsible-height !default; +$collapsible-header-color: #fff !default; +$collapsible-border-color: #ddd !default; + + +// 7. Chips +// ========================================================================== + +$chip-bg-color: #e4e4e4 !default; +$chip-border-color: #9e9e9e !default; +$chip-selected-color: #26a69a !default; +$chip-margin: 5px !default; + + +// 8. Date + Time Picker +// ========================================================================== + +$datepicker-display-font-size: 2.8rem; +$datepicker-calendar-header-color: #999; +$datepicker-weekday-color: rgba(0, 0, 0, .87) !default; +$datepicker-weekday-bg: darken($secondary-color, 7%) !default; +$datepicker-date-bg: $secondary-color !default; +$datepicker-year: rgba(255, 255, 255, .7) !default; +$datepicker-focus: rgba(0,0,0, .05) !default; +$datepicker-selected: $secondary-color !default; +$datepicker-selected-outfocus: desaturate(lighten($secondary-color, 35%), 15%) !default; +$datepicker-day-focus: transparentize(desaturate($secondary-color, 5%), .75) !default; +$datepicker-disabled-day-color: rgba(0, 0, 0, .3) !default; + +$timepicker-clock-color: rgba(0, 0, 0, .87) !default; +$timepicker-clock-plate-bg: #eee !default; + + +// 9. Dropdown +// ========================================================================== + +$dropdown-bg-color: #fff !default; +$dropdown-hover-bg-color: #eee !default; +$dropdown-color: $secondary-color !default; +$dropdown-item-height: 50px !default; + + +// 10. Forms +// ========================================================================== + +// Text Inputs + Textarea +$input-height: 3rem !default; +$input-border-color: color("grey", "base") !default; +$input-border: 1px solid $input-border-color !default; +$input-background: #fff !default; +$input-error-color: $error-color !default; +$input-success-color: $success-color !default; +$input-focus-color: $secondary-color !default; +$input-font-size: 16px !default; +$input-margin-bottom: 8px; +$input-margin: 0 0 $input-margin-bottom 0 !default; +$input-padding: 0 !default; +$label-font-size: .8rem !default; +$input-disabled-color: rgba(0,0,0, .42) !default; +$input-disabled-solid-color: #949494 !default; +$input-disabled-border: 1px dotted $input-disabled-color !default; +$input-invalid-border: 1px solid $input-error-color !default; +$input-icon-size: 2rem; +$placeholder-text-color: lighten($input-border-color, 20%) !default; + +// Radio Buttons +$radio-fill-color: $secondary-color !default; +$radio-empty-color: #5a5a5a !default; +$radio-border: 2px solid $radio-fill-color !default; + +// Range +$range-height: 14px !default; +$range-width: 14px !default; +$track-height: 3px !default; + +// Select +$select-border: 1px solid #f2f2f2 !default; +$select-background: rgba(255, 255, 255, 0.90) !default; +$select-focus: 1px solid lighten($secondary-color, 47%) !default; +$select-option-hover: rgba(0,0,0,.08) !default; +$select-option-focus: rgba(0,0,0,.08) !default; +$select-option-selected: rgba(0,0,0,.03) !default; +$select-padding: 5px !default; +$select-radius: 2px !default; +$select-disabled-color: rgba(0,0,0,.3) !default; + +// Switches +$switch-bg-color: $secondary-color !default; +$switch-checked-lever-bg: desaturate(lighten($switch-bg-color, 25%), 25%) !default; +$switch-unchecked-bg: #F1F1F1 !default; +$switch-unchecked-lever-bg: rgba(0,0,0,.38) !default; +$switch-radius: 15px !default; + + +// 11. Global +// ========================================================================== + +// Media Query Ranges +$small-screen-up: 601px !default; +$medium-screen-up: 993px !default; +$large-screen-up: 1201px !default; +$small-screen: 600px !default; +$medium-screen: 992px !default; +$large-screen: 1200px !default; + +$medium-and-up: "only screen and (min-width : #{$small-screen-up})" !default; +$large-and-up: "only screen and (min-width : #{$medium-screen-up})" !default; +$extra-large-and-up: "only screen and (min-width : #{$large-screen-up})" !default; +$small-and-down: "only screen and (max-width : #{$small-screen})" !default; +$medium-and-down: "only screen and (max-width : #{$medium-screen})" !default; +$medium-only: "only screen and (min-width : #{$small-screen-up}) and (max-width : #{$medium-screen})" !default; + + +// 12. Grid +// ========================================================================== + +$num-cols: 12 !default; +$gutter-width: 1.5rem !default; +$element-top-margin: $gutter-width/3 !default; +$element-bottom-margin: ($gutter-width*2)/3 !default; + + +// 13. Navigation Bar +// ========================================================================== + +$navbar-height: 64px !default; +$navbar-line-height: $navbar-height !default; +$navbar-height-mobile: 56px !default; +$navbar-line-height-mobile: $navbar-height-mobile !default; +$navbar-font-size: 1rem !default; +$navbar-font-color: #fff !default; +$navbar-brand-font-size: 2.1rem !default; + +// 14. Side Navigation +// ========================================================================== + +$sidenav-width: 300px !default; +$sidenav-font-size: 14px !default; +$sidenav-font-color: rgba(0,0,0,.87) !default; +$sidenav-bg-color: #fff !default; +$sidenav-padding: 16px !default; +$sidenav-item-height: 48px !default; +$sidenav-line-height: $sidenav-item-height !default; + + +// 15. Photo Slider +// ========================================================================== + +$slider-bg-color: color('grey', 'base') !default; +$slider-bg-color-light: color('grey', 'lighten-2') !default; +$slider-indicator-color: color('green', 'base') !default; + + +// 16. Spinners | Loaders +// ========================================================================== + +$spinner-default-color: $secondary-color !default; + + +// 17. Tabs +// ========================================================================== + +$tabs-underline-color: $primary-color-light !default; +$tabs-text-color: $primary-color !default; +$tabs-bg-color: #fff !default; + + +// 18. Tables +// ========================================================================== + +$table-border-color: rgba(0,0,0,.12) !default; +$table-striped-color: rgba(242, 242, 242, 0.5) !default; + + +// 19. Toasts +// ========================================================================== + +$toast-height: 48px !default; +$toast-color: #323232 !default; +$toast-text-color: #fff !default; +$toast-action-color: #eeff41; + + +// 20. Typography +// ========================================================================== + +$font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !default; +$off-black: rgba(0, 0, 0, 0.87) !default; +// Header Styles +$h1-fontsize: 4.2rem !default; +$h2-fontsize: 3.56rem !default; +$h3-fontsize: 2.92rem !default; +$h4-fontsize: 2.28rem !default; +$h5-fontsize: 1.64rem !default; +$h6-fontsize: 1.15rem !default; + + +// 21. Footer +// ========================================================================== + +$footer-font-color: #fff !default; +$footer-bg-color: $primary-color !default; +$footer-copyright-font-color: rgba(255,255,255,.8) !default; +$footer-copyright-bg-color: rgba(51,51,51,.08) !default; + + +// 22. Flow Text +// ========================================================================== + +$range : $large-screen - $small-screen !default; +$intervals: 20 !default; +$interval-size: $range / $intervals !default; + + +// 23. Collections +// ========================================================================== + +$collection-border-color: #e0e0e0 !default; +$collection-bg-color: #fff !default; +$collection-active-bg-color: $secondary-color !default; +$collection-active-color: lighten($secondary-color, 55%) !default; +$collection-hover-bg-color: #ddd !default; +$collection-link-color: $secondary-color !default; +$collection-line-height: 1.5rem !default; + + +// 24. Progress Bar +// ========================================================================== + +$progress-bar-color: $secondary-color !default; diff --git a/src/main/webapp/WEB-INF/sass/components/_waves.scss b/src/main/webapp/WEB-INF/sass/components/_waves.scss new file mode 100644 index 0000000..5a3229b --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/_waves.scss @@ -0,0 +1,114 @@ + +/*! + * Waves v0.6.0 + * http://fian.my.id/Waves + * + * Copyright 2014 Alfiana E. Sibuea and other contributors + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + */ + + +.waves-effect { + position: relative; + cursor: pointer; + display: inline-block; + overflow: hidden; + user-select: none; + -webkit-tap-highlight-color: transparent; + vertical-align: middle; + z-index: 1; + transition: .3s ease-out; + + .waves-ripple { + position: absolute; + border-radius: 50%; + width: 20px; + height: 20px; + margin-top:-10px; + margin-left:-10px; + opacity: 0; + + background: rgba(0,0,0,0.2); + transition: all 0.7s ease-out; + transition-property: transform, opacity; + transform: scale(0); + pointer-events: none; + } + + // Waves Colors + &.waves-light .waves-ripple { + background-color: rgba(255, 255, 255, 0.45); + } + &.waves-red .waves-ripple { + background-color: rgba(244, 67, 54, .70); + } + &.waves-yellow .waves-ripple { + background-color: rgba(255, 235, 59, .70); + } + &.waves-orange .waves-ripple { + background-color: rgba(255, 152, 0, .70); + } + &.waves-purple .waves-ripple { + background-color: rgba(156, 39, 176, 0.70); + } + &.waves-green .waves-ripple { + background-color: rgba(76, 175, 80, 0.70); + } + &.waves-teal .waves-ripple { + background-color: rgba(0, 150, 136, 0.70); + } + + // Style input button bug. + input[type="button"], input[type="reset"], input[type="submit"] { + border: 0; + font-style: normal; + font-size: inherit; + text-transform: inherit; + background: none; + } + + img { + position: relative; + z-index: -1; + } +} + +.waves-notransition { + transition: none #{"!important"}; +} + +.waves-circle { + transform: translateZ(0); + -webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%); +} + +.waves-input-wrapper { + border-radius: 0.2em; + vertical-align: bottom; + + .waves-button-input { + position: relative; + top: 0; + left: 0; + z-index: 1; + } +} + +.waves-circle { + text-align: center; + width: 2.5em; + height: 2.5em; + line-height: 2.5em; + border-radius: 50%; + -webkit-mask-image: none; +} + +.waves-block { + display: block; +} + +/* Firefox Bug: link not triggered */ +.waves-effect .waves-ripple { + z-index: -1; +} \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/sass/components/forms/_checkboxes.scss b/src/main/webapp/WEB-INF/sass/components/forms/_checkboxes.scss new file mode 100644 index 0000000..ddc7d96 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/forms/_checkboxes.scss @@ -0,0 +1,200 @@ +/* Checkboxes + ========================================================================== */ + +/* Remove default checkbox */ +[type="checkbox"]:not(:checked), +[type="checkbox"]:checked { + position: absolute; + opacity: 0; + pointer-events: none; +} + +// Checkbox Styles +[type="checkbox"] { + // Text Label Style + + span:not(.lever) { + position: relative; + padding-left: 35px; + cursor: pointer; + display: inline-block; + height: 25px; + line-height: 25px; + font-size: 1rem; + user-select: none; + } + + /* checkbox aspect */ + + span:not(.lever):before, + &:not(.filled-in) + span:not(.lever):after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 18px; + height: 18px; + z-index: 0; + border: 2px solid $radio-empty-color; + border-radius: 1px; + margin-top: 3px; + transition: .2s; + } + + &:not(.filled-in) + span:not(.lever):after { + border: 0; + transform: scale(0); + } + + &:not(:checked):disabled + span:not(.lever):before { + border: none; + background-color: $input-disabled-color; + } + + // Focused styles + &.tabbed:focus + span:not(.lever):after { + transform: scale(1); + border: 0; + border-radius: 50%; + box-shadow: 0 0 0 10px rgba(0,0,0,.1); + background-color: rgba(0,0,0,.1); + } +} + +[type="checkbox"]:checked { + + span:not(.lever):before { + top: -4px; + left: -5px; + width: 12px; + height: 22px; + border-top: 2px solid transparent; + border-left: 2px solid transparent; + border-right: $radio-border; + border-bottom: $radio-border; + transform: rotate(40deg); + backface-visibility: hidden; + transform-origin: 100% 100%; + } + + &:disabled + span:before { + border-right: 2px solid $input-disabled-color; + border-bottom: 2px solid $input-disabled-color; + } +} + +/* Indeterminate checkbox */ +[type="checkbox"]:indeterminate { + + span:not(.lever):before { + top: -11px; + left: -12px; + width: 10px; + height: 22px; + border-top: none; + border-left: none; + border-right: $radio-border; + border-bottom: none; + transform: rotate(90deg); + backface-visibility: hidden; + transform-origin: 100% 100%; + } + + // Disabled indeterminate + &:disabled + span:not(.lever):before { + border-right: 2px solid $input-disabled-color; + background-color: transparent; + } +} + +// Filled in Style +[type="checkbox"].filled-in { + // General + + span:not(.lever):after { + border-radius: 2px; + } + + + span:not(.lever):before, + + span:not(.lever):after { + content: ''; + left: 0; + position: absolute; + /* .1s delay is for check animation */ + transition: border .25s, background-color .25s, width .20s .1s, height .20s .1s, top .20s .1s, left .20s .1s; + z-index: 1; + } + + // Unchecked style + &:not(:checked) + span:not(.lever):before { + width: 0; + height: 0; + border: 3px solid transparent; + left: 6px; + top: 10px; + transform: rotateZ(37deg); + transform-origin: 100% 100%; + } + + &:not(:checked) + span:not(.lever):after { + height: 20px; + width: 20px; + background-color: transparent; + border: 2px solid $radio-empty-color; + top: 0px; + z-index: 0; + } + + // Checked style + &:checked { + + span:not(.lever):before { + top: 0; + left: 1px; + width: 8px; + height: 13px; + border-top: 2px solid transparent; + border-left: 2px solid transparent; + border-right: 2px solid $input-background; + border-bottom: 2px solid $input-background; + transform: rotateZ(37deg); + transform-origin: 100% 100%; + } + + + span:not(.lever):after { + top: 0; + width: 20px; + height: 20px; + border: 2px solid $secondary-color; + background-color: $secondary-color; + z-index: 0; + } + } + + // Focused styles + &.tabbed:focus + span:not(.lever):after { + border-radius: 2px; + border-color: $radio-empty-color; + background-color: rgba(0,0,0,.1); + } + + &.tabbed:checked:focus + span:not(.lever):after { + border-radius: 2px; + background-color: $secondary-color; + border-color: $secondary-color; + } + + // Disabled style + &:disabled:not(:checked) + span:not(.lever):before { + background-color: transparent; + border: 2px solid transparent; + } + + &:disabled:not(:checked) + span:not(.lever):after { + border-color: transparent; + background-color: $input-disabled-solid-color; + } + + &:disabled:checked + span:not(.lever):before { + background-color: transparent; + } + + &:disabled:checked + span:not(.lever):after { + background-color: $input-disabled-solid-color; + border-color: $input-disabled-solid-color; + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/forms/_file-input.scss b/src/main/webapp/WEB-INF/sass/components/forms/_file-input.scss new file mode 100644 index 0000000..e2becc9 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/forms/_file-input.scss @@ -0,0 +1,44 @@ +/* File Input + ========================================================================== */ + +.file-field { + position: relative; + + .file-path-wrapper { + overflow: hidden; + padding-left: 10px; + } + + input.file-path { width: 100%; } + + .btn { + float: left; + height: $input-height; + line-height: $input-height; + } + + span { + cursor: pointer; + } + + input[type=file] { + + // Needed to override webkit button + &::-webkit-file-upload-button { + display: none; + } + + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + width: 100%; + margin: 0; + padding: 0; + font-size: 20px; + cursor: pointer; + opacity: 0; + filter: alpha(opacity=0); + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/forms/_forms.scss b/src/main/webapp/WEB-INF/sass/components/forms/_forms.scss new file mode 100644 index 0000000..e9b65b4 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/forms/_forms.scss @@ -0,0 +1,22 @@ +// Remove Focus Boxes +select:focus { + outline: $select-focus; +} + +button:focus { + outline: none; + background-color: $button-background-focus; +} + +label { + font-size: $label-font-size; + color: $input-border-color; +} + +@import 'input-fields'; +@import 'radio-buttons'; +@import 'checkboxes'; +@import 'switches'; +@import 'select'; +@import 'file-input'; +@import 'range'; diff --git a/src/main/webapp/WEB-INF/sass/components/forms/_input-fields.scss b/src/main/webapp/WEB-INF/sass/components/forms/_input-fields.scss new file mode 100644 index 0000000..f18c2f8 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/forms/_input-fields.scss @@ -0,0 +1,354 @@ +/* Text Inputs + Textarea + ========================================================================== */ + +/* Style Placeholders */ + +::placeholder { + color: $placeholder-text-color; +} + +/* Text inputs */ + +input:not([type]), +input[type=text]:not(.browser-default), +input[type=password]:not(.browser-default), +input[type=email]:not(.browser-default), +input[type=url]:not(.browser-default), +input[type=time]:not(.browser-default), +input[type=date]:not(.browser-default), +input[type=datetime]:not(.browser-default), +input[type=datetime-local]:not(.browser-default), +input[type=tel]:not(.browser-default), +input[type=number]:not(.browser-default), +input[type=search]:not(.browser-default), +textarea.materialize-textarea { + + // General Styles + background-color: transparent; + border: none; + border-bottom: $input-border; + border-radius: 0; + outline: none; + height: $input-height; + width: 100%; + font-size: $input-font-size; + margin: $input-margin; + padding: $input-padding; + box-shadow: none; + box-sizing: content-box; + transition: box-shadow .3s, border .3s; + + // Disabled input style + &:disabled, + &[readonly="readonly"] { + color: $input-disabled-color; + border-bottom: $input-disabled-border; + } + + // Disabled label style + &:disabled+label, + &[readonly="readonly"]+label { + color: $input-disabled-color; + } + + // Focused input style + &:focus:not([readonly]) { + border-bottom: 1px solid $input-focus-color; + box-shadow: 0 1px 0 0 $input-focus-color; + } + + // Focused label style + &:focus:not([readonly])+label { + color: $input-focus-color; + } + + // Hide helper text on data message + &.valid ~ .helper-text[data-success], + &:focus.valid ~ .helper-text[data-success], + &.invalid ~ .helper-text[data-error], + &:focus.invalid ~ .helper-text[data-error] { + @extend %hidden-text; + } + + // Valid Input Style + &.valid, + &:focus.valid { + @extend %valid-input-style; + } + + // Custom Success Message + &.valid ~ .helper-text:after, + &:focus.valid ~ .helper-text:after { + @extend %custom-success-message; + } + &:focus.valid ~ label { + color: $input-success-color; + } + + // Invalid Input Style + &.invalid, + &:focus.invalid { + @extend %invalid-input-style; + } + + // Custom Error message + &.invalid ~ .helper-text:after, + &:focus.invalid ~ .helper-text:after { + @extend %custom-error-message; + } + &:focus.invalid ~ label { + color: $input-error-color; + } + + // Full width label when using validate for error messages + &.validate + label { + width: 100%; + } + + // Form Message Shared Styles + & + label:after { + @extend %input-after-style; + } +} + + +/* Validation Sass Placeholders */ +%valid-input-style { + border-bottom: 1px solid $input-success-color; + box-shadow: 0 1px 0 0 $input-success-color; +} +%invalid-input-style { + border-bottom: $input-invalid-border; + box-shadow: 0 1px 0 0 $input-error-color; +} +%hidden-text { + color: transparent; + user-select: none; + pointer-events: none; +} +%custom-success-message { + content: attr(data-success); + color: $input-success-color; +} +%custom-error-message { + content: attr(data-error); + color: $input-error-color; +} +%input-after-style { + display: block; + content: ""; + position: absolute; + top: 100%; + left: 0; + opacity: 0; + transition: .2s opacity ease-out, .2s color ease-out; +} + + +// Styling for input field wrapper +.input-field { + // Inline styles + &.inline { + display: inline-block; + vertical-align: middle; + margin-left: 5px; + + input, + .select-dropdown { + margin-bottom: 1rem; + } + } + + // Gutter spacing + &.col { + label { + left: $gutter-width / 2; + } + + .prefix ~ label, + .prefix ~ .validate ~ label { + width: calc(100% - 3rem - #{$gutter-width}); + } + } + + position: relative; + margin-top: 1rem; + margin-bottom: 1rem; + + & > label { + color: $input-border-color; + position: absolute; + top: 0; + left: 0; + font-size: 1rem; + cursor: text; + transition: transform .2s ease-out, color .2s ease-out; + transform-origin: 0% 100%; + text-align: initial; + transform: translateY(12px); + + &:not(.label-icon).active { + transform: translateY(-14px) scale(.8); + transform-origin: 0 0; + } + } + + // Autofill + date + time inputs + & > input[type]:-webkit-autofill:not(.browser-default):not([type="search"]) + label, + & > input[type=date]:not(.browser-default) + label, + & > input[type=time]:not(.browser-default) + label { + transform: translateY(-14px) scale(.8); + transform-origin: 0 0; + } + + .helper-text { + &::after { + opacity: 1; + position: absolute; + top: 0; + left: 0; + } + + position: relative; + min-height: 18px; + display: block; + font-size: 12px; + color: rgba(0,0,0,.54); + } + + // Prefix Icons + .prefix { + position: absolute; + width: $input-height; + font-size: $input-icon-size; + transition: color .2s; + top: ($input-height - $input-icon-size) / 2; + + &.active { color: $input-focus-color; } + } + + .prefix ~ input, + .prefix ~ textarea, + .prefix ~ label, + .prefix ~ .validate ~ label, + .prefix ~ .helper-text, + .prefix ~ .autocomplete-content { + margin-left: 3rem; + width: 92%; + width: calc(100% - 3rem); + } + + .prefix ~ label { margin-left: 3rem; } + + @media #{$medium-and-down} { + .prefix ~ input { + width: 86%; + width: calc(100% - 3rem); + } + } + + @media #{$small-and-down} { + .prefix ~ input { + width: 80%; + width: calc(100% - 3rem); + } + } +} + + +/* Search Field */ + +.input-field input[type=search] { + display: block; + line-height: inherit; + transition: .3s background-color; + + .nav-wrapper & { + height: inherit; + padding-left: 4rem; + width: calc(100% - 4rem); + border: 0; + box-shadow: none; + } + + &:focus:not(.browser-default) { + background-color: $input-background; + border: 0; + box-shadow: none; + color: #444; + + & + label i, + & ~ .mdi-navigation-close, + & ~ .material-icons { + color: #444; + } + } + + & + .label-icon { + transform: none; + left: 1rem; + } + + & ~ .mdi-navigation-close, + & ~ .material-icons { + position: absolute; + top: 0; + right: 1rem; + color: transparent; + cursor: pointer; + font-size: $input-icon-size; + transition: .3s color; + } +} + + +/* Textarea */ + +// Default textarea +textarea { + width: 100%; + height: $input-height; + background-color: transparent; + + &.materialize-textarea { + line-height: normal; + overflow-y: hidden; /* prevents scroll bar flash */ + padding: .8rem 0 .8rem 0; /* prevents text jump on Enter keypress */ + resize: none; + min-height: $input-height; + box-sizing: border-box; + } +} + +// For textarea autoresize +.hiddendiv { + visibility: hidden; + white-space: pre-wrap; + word-wrap: break-word; + overflow-wrap: break-word; /* future version of deprecated 'word-wrap' */ + padding-top: 1.2rem; /* prevents text jump on Enter keypress */ + + // Reduces repaints + position: absolute; + top: 0; + z-index: -1; +} + + +/* Autocomplete */ +.autocomplete-content { + li { + .highlight { color: #444; } + + img { + height: $dropdown-item-height - 10; + width: $dropdown-item-height - 10; + margin: 5px 15px; + } + } +} + +/* Character Counter */ +.character-counter { + min-height: 18px; +} diff --git a/src/main/webapp/WEB-INF/sass/components/forms/_radio-buttons.scss b/src/main/webapp/WEB-INF/sass/components/forms/_radio-buttons.scss new file mode 100644 index 0000000..c9f7296 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/forms/_radio-buttons.scss @@ -0,0 +1,115 @@ +/* Radio Buttons + ========================================================================== */ + +// Remove default Radio Buttons +[type="radio"]:not(:checked), +[type="radio"]:checked { + position: absolute; + opacity: 0; + pointer-events: none; +} + +[type="radio"]:not(:checked) + span, +[type="radio"]:checked + span { + position: relative; + padding-left: 35px; + cursor: pointer; + display: inline-block; + height: 25px; + line-height: 25px; + font-size: 1rem; + transition: .28s ease; + user-select: none; +} + +[type="radio"] + span:before, +[type="radio"] + span:after { + content: ''; + position: absolute; + left: 0; + top: 0; + margin: 4px; + width: 16px; + height: 16px; + z-index: 0; + transition: .28s ease; +} + +/* Unchecked styles */ +[type="radio"]:not(:checked) + span:before, +[type="radio"]:not(:checked) + span:after, +[type="radio"]:checked + span:before, +[type="radio"]:checked + span:after, +[type="radio"].with-gap:checked + span:before, +[type="radio"].with-gap:checked + span:after { + border-radius: 50%; +} + +[type="radio"]:not(:checked) + span:before, +[type="radio"]:not(:checked) + span:after { + border: 2px solid $radio-empty-color; +} + +[type="radio"]:not(:checked) + span:after { + transform: scale(0); +} + +/* Checked styles */ +[type="radio"]:checked + span:before { + border: 2px solid transparent; +} + +[type="radio"]:checked + span:after, +[type="radio"].with-gap:checked + span:before, +[type="radio"].with-gap:checked + span:after { + border: $radio-border; +} + +[type="radio"]:checked + span:after, +[type="radio"].with-gap:checked + span:after { + background-color: $radio-fill-color; +} + +[type="radio"]:checked + span:after { + transform: scale(1.02); +} + +/* Radio With gap */ +[type="radio"].with-gap:checked + span:after { + transform: scale(.5); +} + +/* Focused styles */ +[type="radio"].tabbed:focus + span:before { + box-shadow: 0 0 0 10px rgba(0,0,0,.1); +} + +/* Disabled Radio With gap */ +[type="radio"].with-gap:disabled:checked + span:before { + border: 2px solid $input-disabled-color; +} + +[type="radio"].with-gap:disabled:checked + span:after { + border: none; + background-color: $input-disabled-color; +} + +/* Disabled style */ +[type="radio"]:disabled:not(:checked) + span:before, +[type="radio"]:disabled:checked + span:before { + background-color: transparent; + border-color: $input-disabled-color; +} + +[type="radio"]:disabled + span { + color: $input-disabled-color; +} + +[type="radio"]:disabled:not(:checked) + span:before { + border-color: $input-disabled-color; +} + +[type="radio"]:disabled:checked + span:after { + background-color: $input-disabled-color; + border-color: $input-disabled-solid-color; +} diff --git a/src/main/webapp/WEB-INF/sass/components/forms/_range.scss b/src/main/webapp/WEB-INF/sass/components/forms/_range.scss new file mode 100644 index 0000000..18607f5 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/forms/_range.scss @@ -0,0 +1,161 @@ +/* Range + ========================================================================== */ + +.range-field { + position: relative; +} + +input[type=range], +input[type=range] + .thumb { + @extend .no-select; + cursor: pointer; +} + +input[type=range] { + position: relative; + background-color: transparent; + border: none; + outline: none; + width: 100%; + margin: 15px 0; + padding: 0; + + &:focus { + outline: none; + } +} + +input[type=range] + .thumb { + position: absolute; + top: 10px; + left: 0; + border: none; + height: 0; + width: 0; + border-radius: 50%; + background-color: $radio-fill-color; + margin-left: 7px; + + transform-origin: 50% 50%; + transform: rotate(-45deg); + + .value { + display: block; + width: 30px; + text-align: center; + color: $radio-fill-color; + font-size: 0; + transform: rotate(45deg); + } + + &.active { + border-radius: 50% 50% 50% 0; + + .value { + color: $input-background; + margin-left: -1px; + margin-top: 8px; + font-size: 10px; + } + } +} + +// Shared +@mixin range-track { + height: $track-height; + background: #c2c0c2; + border: none; +} + +@mixin range-thumb { + border: none; + height: $range-height; + width: $range-width; + border-radius: 50%; + background: $radio-fill-color; + transition: box-shadow .3s; +} + +// WebKit +input[type=range] { + -webkit-appearance: none; +} + +input[type=range]::-webkit-slider-runnable-track { + @include range-track; +} + +input[type=range]::-webkit-slider-thumb { + @include range-thumb; + -webkit-appearance: none; + background-color: $radio-fill-color; + transform-origin: 50% 50%; + margin: -5px 0 0 0; + +} + +.keyboard-focused input[type=range]:focus:not(.active)::-webkit-slider-thumb { + box-shadow: 0 0 0 10px rgba($radio-fill-color, .26); +} + +// FireFox +input[type=range] { + /* fix for FF unable to apply focus style bug */ + border: 1px solid white; + + /*required for proper track sizing in FF*/ +} + +input[type=range]::-moz-range-track { + @include range-track; +} + +input[type=range]::-moz-focus-inner { + border: 0; +} + +input[type=range]::-moz-range-thumb { + @include range-thumb; + margin-top: -5px; +} + +// hide the outline behind the border +input[type=range]:-moz-focusring { + outline: 1px solid #fff; + outline-offset: -1px; +} + +.keyboard-focused input[type=range]:focus:not(.active)::-moz-range-thumb { + box-shadow: 0 0 0 10px rgba($radio-fill-color, .26); +} + +// IE 10+ +input[type=range]::-ms-track { + height: $track-height; + + // remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead + background: transparent; + + // leave room for the larger thumb to overflow with a transparent border */ + border-color: transparent; + border-width: 6px 0; + + /*remove default tick marks*/ + color: transparent; +} + +input[type=range]::-ms-fill-lower { + background: #777; +} + +input[type=range]::-ms-fill-upper { + background: #ddd; +} + +input[type=range]::-ms-thumb { + @include range-thumb; +} + +.keyboard-focused input[type=range]:focus:not(.active)::-ms-thumb { + box-shadow: 0 0 0 10px rgba($radio-fill-color, .26); +} diff --git a/src/main/webapp/WEB-INF/sass/components/forms/_select.scss b/src/main/webapp/WEB-INF/sass/components/forms/_select.scss new file mode 100644 index 0000000..2fd04d3 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/forms/_select.scss @@ -0,0 +1,180 @@ +/* Select Field + ========================================================================== */ + +select { display: none; } +select.browser-default { display: block; } + +select { + background-color: $select-background; + width: 100%; + padding: $select-padding; + border: $select-border; + border-radius: $select-radius; + height: $input-height; +} + +.select-label { + position: absolute; +} + +.select-wrapper { + &.valid .helper-text[data-success], + &.invalid ~ .helper-text[data-error] { + @extend %hidden-text; + } + + &.valid { + & > input.select-dropdown { + @extend %valid-input-style; + } + + & ~ .helper-text:after { + @extend %custom-success-message; + } + } + + &.invalid { + & > input.select-dropdown, + & > input.select-dropdown:focus { + @extend %invalid-input-style; + } + + & ~ .helper-text:after { + @extend %custom-error-message; + } + } + + &.valid + label, + &.invalid + label { + width: 100%; + pointer-events: none; + } + + & + label:after { + @extend %input-after-style; + } + + position: relative; + + input.select-dropdown { + &:focus { + border-bottom: 1px solid $input-focus-color; + } + position: relative; + cursor: pointer; + background-color: transparent; + border: none; + border-bottom: $input-border; + outline: none; + height: $input-height; + line-height: $input-height; + width: 100%; + font-size: $input-font-size; + margin: $input-margin; + padding: 0; + display: block; + user-select:none; + z-index: 1; + } + + .caret { + position: absolute; + right: 0; + top: 0; + bottom: 0; + margin: auto 0; + z-index: 0; + fill: rgba(0,0,0,.87); + } + + & + label { + position: absolute; + top: -26px; + font-size: $label-font-size; + } +} + +// Disabled styles +select:disabled { + color: $input-disabled-color; +} + +.select-wrapper.disabled { + + label { + color: $input-disabled-color; + } + .caret { + fill: $input-disabled-color; + } +} + +.select-wrapper input.select-dropdown:disabled { + color: $input-disabled-color; + cursor: default; + user-select: none; +} + +.select-wrapper i { + color: $select-disabled-color; +} + +.select-dropdown li.disabled, +.select-dropdown li.disabled > span, +.select-dropdown li.optgroup { + color: $select-disabled-color; + background-color: transparent; +} + +body.keyboard-focused { + .select-dropdown.dropdown-content li:focus { + background-color: $select-option-focus; + } +} + +.select-dropdown.dropdown-content { + li { + &:hover { + background-color: $select-option-hover; + } + + &.selected { + background-color: $select-option-selected; + } + } +} + +// Prefix Icons +.prefix ~ .select-wrapper { + margin-left: 3rem; + width: 92%; + width: calc(100% - 3rem); +} + +.prefix ~ label { margin-left: 3rem; } + +// Icons +.select-dropdown li { + img { + height: $dropdown-item-height - 10; + width: $dropdown-item-height - 10; + margin: 5px 15px; + float: right; + } +} + +// Optgroup styles +.select-dropdown li.optgroup { + border-top: 1px solid $dropdown-hover-bg-color; + + &.selected > span { + color: rgba(0, 0, 0, .7); + } + + & > span { + color: rgba(0, 0, 0, .4); + } + + & ~ li.optgroup-option { + padding-left: 1rem; + } +} diff --git a/src/main/webapp/WEB-INF/sass/components/forms/_switches.scss b/src/main/webapp/WEB-INF/sass/components/forms/_switches.scss new file mode 100644 index 0000000..5976779 --- /dev/null +++ b/src/main/webapp/WEB-INF/sass/components/forms/_switches.scss @@ -0,0 +1,89 @@ +/* Switch + ========================================================================== */ + +.switch, +.switch * { + -webkit-tap-highlight-color: transparent; + user-select: none; +} + +.switch label { + cursor: pointer; +} + +.switch label input[type=checkbox] { + opacity: 0; + width: 0; + height: 0; + + &:checked + .lever { + background-color: $switch-checked-lever-bg; + + &:before, &:after { + left: 18px; + } + + &:after { + background-color: $switch-bg-color; + } + } +} + +.switch label .lever { + content: ""; + display: inline-block; + position: relative; + width: 36px; + height: 14px; + background-color: $switch-unchecked-lever-bg; + border-radius: $switch-radius; + margin-right: 10px; + transition: background 0.3s ease; + vertical-align: middle; + margin: 0 16px; + + &:before, &:after { + content: ""; + position: absolute; + display: inline-block; + width: 20px; + height: 20px; + border-radius: 50%; + left: 0; + top: -3px; + transition: left 0.3s ease, background .3s ease, box-shadow 0.1s ease, transform .1s ease; + } + + &:before { + background-color: transparentize($switch-bg-color, .85); + } + + &:after { + background-color: $switch-unchecked-bg; + box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12); + } +} + +// Switch active style +input[type=checkbox]:checked:not(:disabled) ~ .lever:active::before, +input[type=checkbox]:checked:not(:disabled).tabbed:focus ~ .lever::before { + transform: scale(2.4); + background-color: transparentize($switch-bg-color, .85); +} + +input[type=checkbox]:not(:disabled) ~ .lever:active:before, +input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::before { + transform: scale(2.4); + background-color: rgba(0,0,0,.08); +} + +// Disabled Styles +.switch input[type=checkbox][disabled] + .lever { + cursor: default; + background-color: rgba(0,0,0,.12); +} + +.switch label input[type=checkbox][disabled] + .lever:after, +.switch label input[type=checkbox][disabled]:checked + .lever:after { + background-color: $input-disabled-solid-color; +} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..91fa9fc --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,15 @@ + + + + AREN + + AREN is an application that handle online debate. + + + 60 + + diff --git a/src/main/webapp/assets/css/app.css b/src/main/webapp/assets/css/app.css new file mode 100644 index 0000000..e81e48d --- /dev/null +++ b/src/main/webapp/assets/css/app.css @@ -0,0 +1,7949 @@ +@font-face { + font-family: "Seravek"; + src: url("../font/seravek-light-webfont.woff") format("woff"); + font-weight: 100; } +@font-face { + font-family: "Seravek"; + src: url("../font/seravek-regular-webfont.woff") format("woff"); + font-weight: 400; } +@font-face { + font-family: "Seravek"; + src: url("../font/seravek-medium-webfont.woff") format("woff"); + font-weight: 700; } +@font-face { + font-family: "Seravek"; + src: url("../font/seravek-bold-webfont.woff") format("woff"); + font-weight: 900; } +@font-face { + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: url("../font/material-icons.woff") format("woff2"); } +/*$error-color: color("red", "base") !default;*/ +:root { + --blue-color: #4D9999; + --red-color: #BA4100; + --green-color: #26A96C; + --grey-color: #B2B2B2; } + +.materialize-red { + background-color: #e51c23 !important; } + +.materialize-red-text { + color: #e51c23 !important; } + +.materialize-red.lighten-5 { + background-color: #fdeaeb !important; } + +.materialize-red-text.text-lighten-5 { + color: #fdeaeb !important; } + +.materialize-red.lighten-4 { + background-color: #f8c1c3 !important; } + +.materialize-red-text.text-lighten-4 { + color: #f8c1c3 !important; } + +.materialize-red.lighten-3 { + background-color: #f3989b !important; } + +.materialize-red-text.text-lighten-3 { + color: #f3989b !important; } + +.materialize-red.lighten-2 { + background-color: #ee6e73 !important; } + +.materialize-red-text.text-lighten-2 { + color: #ee6e73 !important; } + +.materialize-red.lighten-1 { + background-color: #ea454b !important; } + +.materialize-red-text.text-lighten-1 { + color: #ea454b !important; } + +.materialize-red.darken-1 { + background-color: #d0181e !important; } + +.materialize-red-text.text-darken-1 { + color: #d0181e !important; } + +.materialize-red.darken-2 { + background-color: #b9151b !important; } + +.materialize-red-text.text-darken-2 { + color: #b9151b !important; } + +.materialize-red.darken-3 { + background-color: #a21318 !important; } + +.materialize-red-text.text-darken-3 { + color: #a21318 !important; } + +.materialize-red.darken-4 { + background-color: #8b1014 !important; } + +.materialize-red-text.text-darken-4 { + color: #8b1014 !important; } + +.red { + background-color: #F44336 !important; } + +.red-text { + color: #F44336 !important; } + +.red.lighten-5 { + background-color: #FFEBEE !important; } + +.red-text.text-lighten-5 { + color: #FFEBEE !important; } + +.red.lighten-4 { + background-color: #FFCDD2 !important; } + +.red-text.text-lighten-4 { + color: #FFCDD2 !important; } + +.red.lighten-3 { + background-color: #EF9A9A !important; } + +.red-text.text-lighten-3 { + color: #EF9A9A !important; } + +.red.lighten-2 { + background-color: #E57373 !important; } + +.red-text.text-lighten-2 { + color: #E57373 !important; } + +.red.lighten-1 { + background-color: #EF5350 !important; } + +.red-text.text-lighten-1 { + color: #EF5350 !important; } + +.red.darken-1 { + background-color: #E53935 !important; } + +.red-text.text-darken-1 { + color: #E53935 !important; } + +.red.darken-2 { + background-color: #D32F2F !important; } + +.red-text.text-darken-2 { + color: #D32F2F !important; } + +.red.darken-3 { + background-color: #C62828 !important; } + +.red-text.text-darken-3 { + color: #C62828 !important; } + +.red.darken-4 { + background-color: #B71C1C !important; } + +.red-text.text-darken-4 { + color: #B71C1C !important; } + +.red.accent-1 { + background-color: #FF8A80 !important; } + +.red-text.text-accent-1 { + color: #FF8A80 !important; } + +.red.accent-2 { + background-color: #FF5252 !important; } + +.red-text.text-accent-2 { + color: #FF5252 !important; } + +.red.accent-3 { + background-color: #FF1744 !important; } + +.red-text.text-accent-3 { + color: #FF1744 !important; } + +.red.accent-4 { + background-color: #D50000 !important; } + +.red-text.text-accent-4 { + color: #D50000 !important; } + +.pink { + background-color: #e91e63 !important; } + +.pink-text { + color: #e91e63 !important; } + +.pink.lighten-5 { + background-color: #fce4ec !important; } + +.pink-text.text-lighten-5 { + color: #fce4ec !important; } + +.pink.lighten-4 { + background-color: #f8bbd0 !important; } + +.pink-text.text-lighten-4 { + color: #f8bbd0 !important; } + +.pink.lighten-3 { + background-color: #f48fb1 !important; } + +.pink-text.text-lighten-3 { + color: #f48fb1 !important; } + +.pink.lighten-2 { + background-color: #f06292 !important; } + +.pink-text.text-lighten-2 { + color: #f06292 !important; } + +.pink.lighten-1 { + background-color: #ec407a !important; } + +.pink-text.text-lighten-1 { + color: #ec407a !important; } + +.pink.darken-1 { + background-color: #d81b60 !important; } + +.pink-text.text-darken-1 { + color: #d81b60 !important; } + +.pink.darken-2 { + background-color: #c2185b !important; } + +.pink-text.text-darken-2 { + color: #c2185b !important; } + +.pink.darken-3 { + background-color: #ad1457 !important; } + +.pink-text.text-darken-3 { + color: #ad1457 !important; } + +.pink.darken-4 { + background-color: #880e4f !important; } + +.pink-text.text-darken-4 { + color: #880e4f !important; } + +.pink.accent-1 { + background-color: #ff80ab !important; } + +.pink-text.text-accent-1 { + color: #ff80ab !important; } + +.pink.accent-2 { + background-color: #ff4081 !important; } + +.pink-text.text-accent-2 { + color: #ff4081 !important; } + +.pink.accent-3 { + background-color: #f50057 !important; } + +.pink-text.text-accent-3 { + color: #f50057 !important; } + +.pink.accent-4 { + background-color: #c51162 !important; } + +.pink-text.text-accent-4 { + color: #c51162 !important; } + +.purple { + background-color: #9c27b0 !important; } + +.purple-text { + color: #9c27b0 !important; } + +.purple.lighten-5 { + background-color: #f3e5f5 !important; } + +.purple-text.text-lighten-5 { + color: #f3e5f5 !important; } + +.purple.lighten-4 { + background-color: #e1bee7 !important; } + +.purple-text.text-lighten-4 { + color: #e1bee7 !important; } + +.purple.lighten-3 { + background-color: #ce93d8 !important; } + +.purple-text.text-lighten-3 { + color: #ce93d8 !important; } + +.purple.lighten-2 { + background-color: #ba68c8 !important; } + +.purple-text.text-lighten-2 { + color: #ba68c8 !important; } + +.purple.lighten-1 { + background-color: #ab47bc !important; } + +.purple-text.text-lighten-1 { + color: #ab47bc !important; } + +.purple.darken-1 { + background-color: #8e24aa !important; } + +.purple-text.text-darken-1 { + color: #8e24aa !important; } + +.purple.darken-2 { + background-color: #7b1fa2 !important; } + +.purple-text.text-darken-2 { + color: #7b1fa2 !important; } + +.purple.darken-3 { + background-color: #6a1b9a !important; } + +.purple-text.text-darken-3 { + color: #6a1b9a !important; } + +.purple.darken-4 { + background-color: #4a148c !important; } + +.purple-text.text-darken-4 { + color: #4a148c !important; } + +.purple.accent-1 { + background-color: #ea80fc !important; } + +.purple-text.text-accent-1 { + color: #ea80fc !important; } + +.purple.accent-2 { + background-color: #e040fb !important; } + +.purple-text.text-accent-2 { + color: #e040fb !important; } + +.purple.accent-3 { + background-color: #d500f9 !important; } + +.purple-text.text-accent-3 { + color: #d500f9 !important; } + +.purple.accent-4 { + background-color: #aa00ff !important; } + +.purple-text.text-accent-4 { + color: #aa00ff !important; } + +.deep-purple { + background-color: #673ab7 !important; } + +.deep-purple-text { + color: #673ab7 !important; } + +.deep-purple.lighten-5 { + background-color: #ede7f6 !important; } + +.deep-purple-text.text-lighten-5 { + color: #ede7f6 !important; } + +.deep-purple.lighten-4 { + background-color: #d1c4e9 !important; } + +.deep-purple-text.text-lighten-4 { + color: #d1c4e9 !important; } + +.deep-purple.lighten-3 { + background-color: #b39ddb !important; } + +.deep-purple-text.text-lighten-3 { + color: #b39ddb !important; } + +.deep-purple.lighten-2 { + background-color: #9575cd !important; } + +.deep-purple-text.text-lighten-2 { + color: #9575cd !important; } + +.deep-purple.lighten-1 { + background-color: #7e57c2 !important; } + +.deep-purple-text.text-lighten-1 { + color: #7e57c2 !important; } + +.deep-purple.darken-1 { + background-color: #5e35b1 !important; } + +.deep-purple-text.text-darken-1 { + color: #5e35b1 !important; } + +.deep-purple.darken-2 { + background-color: #512da8 !important; } + +.deep-purple-text.text-darken-2 { + color: #512da8 !important; } + +.deep-purple.darken-3 { + background-color: #4527a0 !important; } + +.deep-purple-text.text-darken-3 { + color: #4527a0 !important; } + +.deep-purple.darken-4 { + background-color: #311b92 !important; } + +.deep-purple-text.text-darken-4 { + color: #311b92 !important; } + +.deep-purple.accent-1 { + background-color: #b388ff !important; } + +.deep-purple-text.text-accent-1 { + color: #b388ff !important; } + +.deep-purple.accent-2 { + background-color: #7c4dff !important; } + +.deep-purple-text.text-accent-2 { + color: #7c4dff !important; } + +.deep-purple.accent-3 { + background-color: #651fff !important; } + +.deep-purple-text.text-accent-3 { + color: #651fff !important; } + +.deep-purple.accent-4 { + background-color: #6200ea !important; } + +.deep-purple-text.text-accent-4 { + color: #6200ea !important; } + +.indigo { + background-color: #3f51b5 !important; } + +.indigo-text { + color: #3f51b5 !important; } + +.indigo.lighten-5 { + background-color: #e8eaf6 !important; } + +.indigo-text.text-lighten-5 { + color: #e8eaf6 !important; } + +.indigo.lighten-4 { + background-color: #c5cae9 !important; } + +.indigo-text.text-lighten-4 { + color: #c5cae9 !important; } + +.indigo.lighten-3 { + background-color: #9fa8da !important; } + +.indigo-text.text-lighten-3 { + color: #9fa8da !important; } + +.indigo.lighten-2 { + background-color: #7986cb !important; } + +.indigo-text.text-lighten-2 { + color: #7986cb !important; } + +.indigo.lighten-1 { + background-color: #5c6bc0 !important; } + +.indigo-text.text-lighten-1 { + color: #5c6bc0 !important; } + +.indigo.darken-1 { + background-color: #3949ab !important; } + +.indigo-text.text-darken-1 { + color: #3949ab !important; } + +.indigo.darken-2 { + background-color: #303f9f !important; } + +.indigo-text.text-darken-2 { + color: #303f9f !important; } + +.indigo.darken-3 { + background-color: #283593 !important; } + +.indigo-text.text-darken-3 { + color: #283593 !important; } + +.indigo.darken-4 { + background-color: #1a237e !important; } + +.indigo-text.text-darken-4 { + color: #1a237e !important; } + +.indigo.accent-1 { + background-color: #8c9eff !important; } + +.indigo-text.text-accent-1 { + color: #8c9eff !important; } + +.indigo.accent-2 { + background-color: #536dfe !important; } + +.indigo-text.text-accent-2 { + color: #536dfe !important; } + +.indigo.accent-3 { + background-color: #3d5afe !important; } + +.indigo-text.text-accent-3 { + color: #3d5afe !important; } + +.indigo.accent-4 { + background-color: #304ffe !important; } + +.indigo-text.text-accent-4 { + color: #304ffe !important; } + +.blue { + background-color: #2196F3 !important; } + +.blue-text { + color: #2196F3 !important; } + +.blue.lighten-5 { + background-color: #E3F2FD !important; } + +.blue-text.text-lighten-5 { + color: #E3F2FD !important; } + +.blue.lighten-4 { + background-color: #BBDEFB !important; } + +.blue-text.text-lighten-4 { + color: #BBDEFB !important; } + +.blue.lighten-3 { + background-color: #90CAF9 !important; } + +.blue-text.text-lighten-3 { + color: #90CAF9 !important; } + +.blue.lighten-2 { + background-color: #64B5F6 !important; } + +.blue-text.text-lighten-2 { + color: #64B5F6 !important; } + +.blue.lighten-1 { + background-color: #42A5F5 !important; } + +.blue-text.text-lighten-1 { + color: #42A5F5 !important; } + +.blue.darken-1 { + background-color: #1E88E5 !important; } + +.blue-text.text-darken-1 { + color: #1E88E5 !important; } + +.blue.darken-2 { + background-color: #1976D2 !important; } + +.blue-text.text-darken-2 { + color: #1976D2 !important; } + +.blue.darken-3 { + background-color: #1565C0 !important; } + +.blue-text.text-darken-3 { + color: #1565C0 !important; } + +.blue.darken-4 { + background-color: #0D47A1 !important; } + +.blue-text.text-darken-4 { + color: #0D47A1 !important; } + +.blue.accent-1 { + background-color: #82B1FF !important; } + +.blue-text.text-accent-1 { + color: #82B1FF !important; } + +.blue.accent-2 { + background-color: #448AFF !important; } + +.blue-text.text-accent-2 { + color: #448AFF !important; } + +.blue.accent-3 { + background-color: #2979FF !important; } + +.blue-text.text-accent-3 { + color: #2979FF !important; } + +.blue.accent-4 { + background-color: #2962FF !important; } + +.blue-text.text-accent-4 { + color: #2962FF !important; } + +.light-blue { + background-color: #03a9f4 !important; } + +.light-blue-text { + color: #03a9f4 !important; } + +.light-blue.lighten-5 { + background-color: #e1f5fe !important; } + +.light-blue-text.text-lighten-5 { + color: #e1f5fe !important; } + +.light-blue.lighten-4 { + background-color: #b3e5fc !important; } + +.light-blue-text.text-lighten-4 { + color: #b3e5fc !important; } + +.light-blue.lighten-3 { + background-color: #81d4fa !important; } + +.light-blue-text.text-lighten-3 { + color: #81d4fa !important; } + +.light-blue.lighten-2 { + background-color: #4fc3f7 !important; } + +.light-blue-text.text-lighten-2 { + color: #4fc3f7 !important; } + +.light-blue.lighten-1 { + background-color: #29b6f6 !important; } + +.light-blue-text.text-lighten-1 { + color: #29b6f6 !important; } + +.light-blue.darken-1 { + background-color: #039be5 !important; } + +.light-blue-text.text-darken-1 { + color: #039be5 !important; } + +.light-blue.darken-2 { + background-color: #0288d1 !important; } + +.light-blue-text.text-darken-2 { + color: #0288d1 !important; } + +.light-blue.darken-3 { + background-color: #0277bd !important; } + +.light-blue-text.text-darken-3 { + color: #0277bd !important; } + +.light-blue.darken-4 { + background-color: #01579b !important; } + +.light-blue-text.text-darken-4 { + color: #01579b !important; } + +.light-blue.accent-1 { + background-color: #80d8ff !important; } + +.light-blue-text.text-accent-1 { + color: #80d8ff !important; } + +.light-blue.accent-2 { + background-color: #40c4ff !important; } + +.light-blue-text.text-accent-2 { + color: #40c4ff !important; } + +.light-blue.accent-3 { + background-color: #00b0ff !important; } + +.light-blue-text.text-accent-3 { + color: #00b0ff !important; } + +.light-blue.accent-4 { + background-color: #0091ea !important; } + +.light-blue-text.text-accent-4 { + color: #0091ea !important; } + +.cyan { + background-color: #00bcd4 !important; } + +.cyan-text { + color: #00bcd4 !important; } + +.cyan.lighten-5 { + background-color: #e0f7fa !important; } + +.cyan-text.text-lighten-5 { + color: #e0f7fa !important; } + +.cyan.lighten-4 { + background-color: #b2ebf2 !important; } + +.cyan-text.text-lighten-4 { + color: #b2ebf2 !important; } + +.cyan.lighten-3 { + background-color: #80deea !important; } + +.cyan-text.text-lighten-3 { + color: #80deea !important; } + +.cyan.lighten-2 { + background-color: #4dd0e1 !important; } + +.cyan-text.text-lighten-2 { + color: #4dd0e1 !important; } + +.cyan.lighten-1 { + background-color: #26c6da !important; } + +.cyan-text.text-lighten-1 { + color: #26c6da !important; } + +.cyan.darken-1 { + background-color: #00acc1 !important; } + +.cyan-text.text-darken-1 { + color: #00acc1 !important; } + +.cyan.darken-2 { + background-color: #0097a7 !important; } + +.cyan-text.text-darken-2 { + color: #0097a7 !important; } + +.cyan.darken-3 { + background-color: #00838f !important; } + +.cyan-text.text-darken-3 { + color: #00838f !important; } + +.cyan.darken-4 { + background-color: #006064 !important; } + +.cyan-text.text-darken-4 { + color: #006064 !important; } + +.cyan.accent-1 { + background-color: #84ffff !important; } + +.cyan-text.text-accent-1 { + color: #84ffff !important; } + +.cyan.accent-2 { + background-color: #18ffff !important; } + +.cyan-text.text-accent-2 { + color: #18ffff !important; } + +.cyan.accent-3 { + background-color: #00e5ff !important; } + +.cyan-text.text-accent-3 { + color: #00e5ff !important; } + +.cyan.accent-4 { + background-color: #00b8d4 !important; } + +.cyan-text.text-accent-4 { + color: #00b8d4 !important; } + +.teal { + background-color: #009688 !important; } + +.teal-text { + color: #009688 !important; } + +.teal.lighten-5 { + background-color: #e0f2f1 !important; } + +.teal-text.text-lighten-5 { + color: #e0f2f1 !important; } + +.teal.lighten-4 { + background-color: #b2dfdb !important; } + +.teal-text.text-lighten-4 { + color: #b2dfdb !important; } + +.teal.lighten-3 { + background-color: #80cbc4 !important; } + +.teal-text.text-lighten-3 { + color: #80cbc4 !important; } + +.teal.lighten-2 { + background-color: #4db6ac !important; } + +.teal-text.text-lighten-2 { + color: #4db6ac !important; } + +.teal.lighten-1 { + background-color: #26a69a !important; } + +.teal-text.text-lighten-1 { + color: #26a69a !important; } + +.teal.darken-1 { + background-color: #00897b !important; } + +.teal-text.text-darken-1 { + color: #00897b !important; } + +.teal.darken-2 { + background-color: #00796b !important; } + +.teal-text.text-darken-2 { + color: #00796b !important; } + +.teal.darken-3 { + background-color: #00695c !important; } + +.teal-text.text-darken-3 { + color: #00695c !important; } + +.teal.darken-4 { + background-color: #004d40 !important; } + +.teal-text.text-darken-4 { + color: #004d40 !important; } + +.teal.accent-1 { + background-color: #a7ffeb !important; } + +.teal-text.text-accent-1 { + color: #a7ffeb !important; } + +.teal.accent-2 { + background-color: #64ffda !important; } + +.teal-text.text-accent-2 { + color: #64ffda !important; } + +.teal.accent-3 { + background-color: #1de9b6 !important; } + +.teal-text.text-accent-3 { + color: #1de9b6 !important; } + +.teal.accent-4 { + background-color: #00bfa5 !important; } + +.teal-text.text-accent-4 { + color: #00bfa5 !important; } + +.green { + background-color: #4CAF50 !important; } + +.green-text { + color: #4CAF50 !important; } + +.green.lighten-5 { + background-color: #E8F5E9 !important; } + +.green-text.text-lighten-5 { + color: #E8F5E9 !important; } + +.green.lighten-4 { + background-color: #C8E6C9 !important; } + +.green-text.text-lighten-4 { + color: #C8E6C9 !important; } + +.green.lighten-3 { + background-color: #A5D6A7 !important; } + +.green-text.text-lighten-3 { + color: #A5D6A7 !important; } + +.green.lighten-2 { + background-color: #81C784 !important; } + +.green-text.text-lighten-2 { + color: #81C784 !important; } + +.green.lighten-1 { + background-color: #66BB6A !important; } + +.green-text.text-lighten-1 { + color: #66BB6A !important; } + +.green.darken-1 { + background-color: #43A047 !important; } + +.green-text.text-darken-1 { + color: #43A047 !important; } + +.green.darken-2 { + background-color: #388E3C !important; } + +.green-text.text-darken-2 { + color: #388E3C !important; } + +.green.darken-3 { + background-color: #2E7D32 !important; } + +.green-text.text-darken-3 { + color: #2E7D32 !important; } + +.green.darken-4 { + background-color: #1B5E20 !important; } + +.green-text.text-darken-4 { + color: #1B5E20 !important; } + +.green.accent-1 { + background-color: #B9F6CA !important; } + +.green-text.text-accent-1 { + color: #B9F6CA !important; } + +.green.accent-2 { + background-color: #69F0AE !important; } + +.green-text.text-accent-2 { + color: #69F0AE !important; } + +.green.accent-3 { + background-color: #00E676 !important; } + +.green-text.text-accent-3 { + color: #00E676 !important; } + +.green.accent-4 { + background-color: #00C853 !important; } + +.green-text.text-accent-4 { + color: #00C853 !important; } + +.light-green { + background-color: #8bc34a !important; } + +.light-green-text { + color: #8bc34a !important; } + +.light-green.lighten-5 { + background-color: #f1f8e9 !important; } + +.light-green-text.text-lighten-5 { + color: #f1f8e9 !important; } + +.light-green.lighten-4 { + background-color: #dcedc8 !important; } + +.light-green-text.text-lighten-4 { + color: #dcedc8 !important; } + +.light-green.lighten-3 { + background-color: #c5e1a5 !important; } + +.light-green-text.text-lighten-3 { + color: #c5e1a5 !important; } + +.light-green.lighten-2 { + background-color: #aed581 !important; } + +.light-green-text.text-lighten-2 { + color: #aed581 !important; } + +.light-green.lighten-1 { + background-color: #9ccc65 !important; } + +.light-green-text.text-lighten-1 { + color: #9ccc65 !important; } + +.light-green.darken-1 { + background-color: #7cb342 !important; } + +.light-green-text.text-darken-1 { + color: #7cb342 !important; } + +.light-green.darken-2 { + background-color: #689f38 !important; } + +.light-green-text.text-darken-2 { + color: #689f38 !important; } + +.light-green.darken-3 { + background-color: #558b2f !important; } + +.light-green-text.text-darken-3 { + color: #558b2f !important; } + +.light-green.darken-4 { + background-color: #33691e !important; } + +.light-green-text.text-darken-4 { + color: #33691e !important; } + +.light-green.accent-1 { + background-color: #ccff90 !important; } + +.light-green-text.text-accent-1 { + color: #ccff90 !important; } + +.light-green.accent-2 { + background-color: #b2ff59 !important; } + +.light-green-text.text-accent-2 { + color: #b2ff59 !important; } + +.light-green.accent-3 { + background-color: #76ff03 !important; } + +.light-green-text.text-accent-3 { + color: #76ff03 !important; } + +.light-green.accent-4 { + background-color: #64dd17 !important; } + +.light-green-text.text-accent-4 { + color: #64dd17 !important; } + +.lime { + background-color: #cddc39 !important; } + +.lime-text { + color: #cddc39 !important; } + +.lime.lighten-5 { + background-color: #f9fbe7 !important; } + +.lime-text.text-lighten-5 { + color: #f9fbe7 !important; } + +.lime.lighten-4 { + background-color: #f0f4c3 !important; } + +.lime-text.text-lighten-4 { + color: #f0f4c3 !important; } + +.lime.lighten-3 { + background-color: #e6ee9c !important; } + +.lime-text.text-lighten-3 { + color: #e6ee9c !important; } + +.lime.lighten-2 { + background-color: #dce775 !important; } + +.lime-text.text-lighten-2 { + color: #dce775 !important; } + +.lime.lighten-1 { + background-color: #d4e157 !important; } + +.lime-text.text-lighten-1 { + color: #d4e157 !important; } + +.lime.darken-1 { + background-color: #c0ca33 !important; } + +.lime-text.text-darken-1 { + color: #c0ca33 !important; } + +.lime.darken-2 { + background-color: #afb42b !important; } + +.lime-text.text-darken-2 { + color: #afb42b !important; } + +.lime.darken-3 { + background-color: #9e9d24 !important; } + +.lime-text.text-darken-3 { + color: #9e9d24 !important; } + +.lime.darken-4 { + background-color: #827717 !important; } + +.lime-text.text-darken-4 { + color: #827717 !important; } + +.lime.accent-1 { + background-color: #f4ff81 !important; } + +.lime-text.text-accent-1 { + color: #f4ff81 !important; } + +.lime.accent-2 { + background-color: #eeff41 !important; } + +.lime-text.text-accent-2 { + color: #eeff41 !important; } + +.lime.accent-3 { + background-color: #c6ff00 !important; } + +.lime-text.text-accent-3 { + color: #c6ff00 !important; } + +.lime.accent-4 { + background-color: #aeea00 !important; } + +.lime-text.text-accent-4 { + color: #aeea00 !important; } + +.yellow { + background-color: #ffeb3b !important; } + +.yellow-text { + color: #ffeb3b !important; } + +.yellow.lighten-5 { + background-color: #fffde7 !important; } + +.yellow-text.text-lighten-5 { + color: #fffde7 !important; } + +.yellow.lighten-4 { + background-color: #fff9c4 !important; } + +.yellow-text.text-lighten-4 { + color: #fff9c4 !important; } + +.yellow.lighten-3 { + background-color: #fff59d !important; } + +.yellow-text.text-lighten-3 { + color: #fff59d !important; } + +.yellow.lighten-2 { + background-color: #fff176 !important; } + +.yellow-text.text-lighten-2 { + color: #fff176 !important; } + +.yellow.lighten-1 { + background-color: #ffee58 !important; } + +.yellow-text.text-lighten-1 { + color: #ffee58 !important; } + +.yellow.darken-1 { + background-color: #fdd835 !important; } + +.yellow-text.text-darken-1 { + color: #fdd835 !important; } + +.yellow.darken-2 { + background-color: #fbc02d !important; } + +.yellow-text.text-darken-2 { + color: #fbc02d !important; } + +.yellow.darken-3 { + background-color: #f9a825 !important; } + +.yellow-text.text-darken-3 { + color: #f9a825 !important; } + +.yellow.darken-4 { + background-color: #f57f17 !important; } + +.yellow-text.text-darken-4 { + color: #f57f17 !important; } + +.yellow.accent-1 { + background-color: #ffff8d !important; } + +.yellow-text.text-accent-1 { + color: #ffff8d !important; } + +.yellow.accent-2 { + background-color: #ffff00 !important; } + +.yellow-text.text-accent-2 { + color: #ffff00 !important; } + +.yellow.accent-3 { + background-color: #ffea00 !important; } + +.yellow-text.text-accent-3 { + color: #ffea00 !important; } + +.yellow.accent-4 { + background-color: #ffd600 !important; } + +.yellow-text.text-accent-4 { + color: #ffd600 !important; } + +.amber { + background-color: #ffc107 !important; } + +.amber-text { + color: #ffc107 !important; } + +.amber.lighten-5 { + background-color: #fff8e1 !important; } + +.amber-text.text-lighten-5 { + color: #fff8e1 !important; } + +.amber.lighten-4 { + background-color: #ffecb3 !important; } + +.amber-text.text-lighten-4 { + color: #ffecb3 !important; } + +.amber.lighten-3 { + background-color: #ffe082 !important; } + +.amber-text.text-lighten-3 { + color: #ffe082 !important; } + +.amber.lighten-2 { + background-color: #ffd54f !important; } + +.amber-text.text-lighten-2 { + color: #ffd54f !important; } + +.amber.lighten-1 { + background-color: #ffca28 !important; } + +.amber-text.text-lighten-1 { + color: #ffca28 !important; } + +.amber.darken-1 { + background-color: #ffb300 !important; } + +.amber-text.text-darken-1 { + color: #ffb300 !important; } + +.amber.darken-2 { + background-color: #ffa000 !important; } + +.amber-text.text-darken-2 { + color: #ffa000 !important; } + +.amber.darken-3 { + background-color: #ff8f00 !important; } + +.amber-text.text-darken-3 { + color: #ff8f00 !important; } + +.amber.darken-4 { + background-color: #ff6f00 !important; } + +.amber-text.text-darken-4 { + color: #ff6f00 !important; } + +.amber.accent-1 { + background-color: #ffe57f !important; } + +.amber-text.text-accent-1 { + color: #ffe57f !important; } + +.amber.accent-2 { + background-color: #ffd740 !important; } + +.amber-text.text-accent-2 { + color: #ffd740 !important; } + +.amber.accent-3 { + background-color: #ffc400 !important; } + +.amber-text.text-accent-3 { + color: #ffc400 !important; } + +.amber.accent-4 { + background-color: #ffab00 !important; } + +.amber-text.text-accent-4 { + color: #ffab00 !important; } + +.orange { + background-color: #ff9800 !important; } + +.orange-text { + color: #ff9800 !important; } + +.orange.lighten-5 { + background-color: #fff3e0 !important; } + +.orange-text.text-lighten-5 { + color: #fff3e0 !important; } + +.orange.lighten-4 { + background-color: #ffe0b2 !important; } + +.orange-text.text-lighten-4 { + color: #ffe0b2 !important; } + +.orange.lighten-3 { + background-color: #ffcc80 !important; } + +.orange-text.text-lighten-3 { + color: #ffcc80 !important; } + +.orange.lighten-2 { + background-color: #ffb74d !important; } + +.orange-text.text-lighten-2 { + color: #ffb74d !important; } + +.orange.lighten-1 { + background-color: #ffa726 !important; } + +.orange-text.text-lighten-1 { + color: #ffa726 !important; } + +.orange.darken-1 { + background-color: #fb8c00 !important; } + +.orange-text.text-darken-1 { + color: #fb8c00 !important; } + +.orange.darken-2 { + background-color: #f57c00 !important; } + +.orange-text.text-darken-2 { + color: #f57c00 !important; } + +.orange.darken-3 { + background-color: #ef6c00 !important; } + +.orange-text.text-darken-3 { + color: #ef6c00 !important; } + +.orange.darken-4 { + background-color: #e65100 !important; } + +.orange-text.text-darken-4 { + color: #e65100 !important; } + +.orange.accent-1 { + background-color: #ffd180 !important; } + +.orange-text.text-accent-1 { + color: #ffd180 !important; } + +.orange.accent-2 { + background-color: #ffab40 !important; } + +.orange-text.text-accent-2 { + color: #ffab40 !important; } + +.orange.accent-3 { + background-color: #ff9100 !important; } + +.orange-text.text-accent-3 { + color: #ff9100 !important; } + +.orange.accent-4 { + background-color: #ff6d00 !important; } + +.orange-text.text-accent-4 { + color: #ff6d00 !important; } + +.deep-orange { + background-color: #ff5722 !important; } + +.deep-orange-text { + color: #ff5722 !important; } + +.deep-orange.lighten-5 { + background-color: #fbe9e7 !important; } + +.deep-orange-text.text-lighten-5 { + color: #fbe9e7 !important; } + +.deep-orange.lighten-4 { + background-color: #ffccbc !important; } + +.deep-orange-text.text-lighten-4 { + color: #ffccbc !important; } + +.deep-orange.lighten-3 { + background-color: #ffab91 !important; } + +.deep-orange-text.text-lighten-3 { + color: #ffab91 !important; } + +.deep-orange.lighten-2 { + background-color: #ff8a65 !important; } + +.deep-orange-text.text-lighten-2 { + color: #ff8a65 !important; } + +.deep-orange.lighten-1 { + background-color: #ff7043 !important; } + +.deep-orange-text.text-lighten-1 { + color: #ff7043 !important; } + +.deep-orange.darken-1 { + background-color: #f4511e !important; } + +.deep-orange-text.text-darken-1 { + color: #f4511e !important; } + +.deep-orange.darken-2 { + background-color: #e64a19 !important; } + +.deep-orange-text.text-darken-2 { + color: #e64a19 !important; } + +.deep-orange.darken-3 { + background-color: #d84315 !important; } + +.deep-orange-text.text-darken-3 { + color: #d84315 !important; } + +.deep-orange.darken-4 { + background-color: #bf360c !important; } + +.deep-orange-text.text-darken-4 { + color: #bf360c !important; } + +.deep-orange.accent-1 { + background-color: #ff9e80 !important; } + +.deep-orange-text.text-accent-1 { + color: #ff9e80 !important; } + +.deep-orange.accent-2 { + background-color: #ff6e40 !important; } + +.deep-orange-text.text-accent-2 { + color: #ff6e40 !important; } + +.deep-orange.accent-3 { + background-color: #ff3d00 !important; } + +.deep-orange-text.text-accent-3 { + color: #ff3d00 !important; } + +.deep-orange.accent-4 { + background-color: #dd2c00 !important; } + +.deep-orange-text.text-accent-4 { + color: #dd2c00 !important; } + +.brown { + background-color: #795548 !important; } + +.brown-text { + color: #795548 !important; } + +.brown.lighten-5 { + background-color: #efebe9 !important; } + +.brown-text.text-lighten-5 { + color: #efebe9 !important; } + +.brown.lighten-4 { + background-color: #d7ccc8 !important; } + +.brown-text.text-lighten-4 { + color: #d7ccc8 !important; } + +.brown.lighten-3 { + background-color: #bcaaa4 !important; } + +.brown-text.text-lighten-3 { + color: #bcaaa4 !important; } + +.brown.lighten-2 { + background-color: #a1887f !important; } + +.brown-text.text-lighten-2 { + color: #a1887f !important; } + +.brown.lighten-1 { + background-color: #8d6e63 !important; } + +.brown-text.text-lighten-1 { + color: #8d6e63 !important; } + +.brown.darken-1 { + background-color: #6d4c41 !important; } + +.brown-text.text-darken-1 { + color: #6d4c41 !important; } + +.brown.darken-2 { + background-color: #5d4037 !important; } + +.brown-text.text-darken-2 { + color: #5d4037 !important; } + +.brown.darken-3 { + background-color: #4e342e !important; } + +.brown-text.text-darken-3 { + color: #4e342e !important; } + +.brown.darken-4 { + background-color: #3e2723 !important; } + +.brown-text.text-darken-4 { + color: #3e2723 !important; } + +.blue-grey { + background-color: #607d8b !important; } + +.blue-grey-text { + color: #607d8b !important; } + +.blue-grey.lighten-5 { + background-color: #eceff1 !important; } + +.blue-grey-text.text-lighten-5 { + color: #eceff1 !important; } + +.blue-grey.lighten-4 { + background-color: #cfd8dc !important; } + +.blue-grey-text.text-lighten-4 { + color: #cfd8dc !important; } + +.blue-grey.lighten-3 { + background-color: #b0bec5 !important; } + +.blue-grey-text.text-lighten-3 { + color: #b0bec5 !important; } + +.blue-grey.lighten-2 { + background-color: #90a4ae !important; } + +.blue-grey-text.text-lighten-2 { + color: #90a4ae !important; } + +.blue-grey.lighten-1 { + background-color: #78909c !important; } + +.blue-grey-text.text-lighten-1 { + color: #78909c !important; } + +.blue-grey.darken-1 { + background-color: #546e7a !important; } + +.blue-grey-text.text-darken-1 { + color: #546e7a !important; } + +.blue-grey.darken-2 { + background-color: #455a64 !important; } + +.blue-grey-text.text-darken-2 { + color: #455a64 !important; } + +.blue-grey.darken-3 { + background-color: #37474f !important; } + +.blue-grey-text.text-darken-3 { + color: #37474f !important; } + +.blue-grey.darken-4 { + background-color: #263238 !important; } + +.blue-grey-text.text-darken-4 { + color: #263238 !important; } + +.grey { + background-color: #9e9e9e !important; } + +.grey-text { + color: #9e9e9e !important; } + +.grey.lighten-5 { + background-color: #fafafa !important; } + +.grey-text.text-lighten-5 { + color: #fafafa !important; } + +.grey.lighten-4 { + background-color: #f5f5f5 !important; } + +.grey-text.text-lighten-4 { + color: #f5f5f5 !important; } + +.grey.lighten-3 { + background-color: #eeeeee !important; } + +.grey-text.text-lighten-3 { + color: #eeeeee !important; } + +.grey.lighten-2 { + background-color: #e0e0e0 !important; } + +.grey-text.text-lighten-2 { + color: #e0e0e0 !important; } + +.grey.lighten-1 { + background-color: #bdbdbd !important; } + +.grey-text.text-lighten-1 { + color: #bdbdbd !important; } + +.grey.darken-1 { + background-color: #757575 !important; } + +.grey-text.text-darken-1 { + color: #757575 !important; } + +.grey.darken-2 { + background-color: #616161 !important; } + +.grey-text.text-darken-2 { + color: #616161 !important; } + +.grey.darken-3 { + background-color: #424242 !important; } + +.grey-text.text-darken-3 { + color: #424242 !important; } + +.grey.darken-4 { + background-color: #212121 !important; } + +.grey-text.text-darken-4 { + color: #212121 !important; } + +.black { + background-color: #000000 !important; } + +.black-text { + color: #000000 !important; } + +.white { + background-color: #FFFFFF !important; } + +.white-text { + color: #FFFFFF !important; } + +.transparent { + background-color: transparent !important; } + +.transparent-text { + color: transparent !important; } + +/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ +/* Document + ========================================================================== */ +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in + * IE on Windows Phone and in iOS. + */ +html { + line-height: 1.15; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/* Sections + ========================================================================== */ +/** + * Remove the margin in all browsers (opinionated). + */ +body { + margin: 0; } + +/** + * Add the correct display in IE 9-. + */ +article, +aside, +footer, +header, +nav, +section { + display: block; } + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/* Grouping content + ========================================================================== */ +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in IE. + */ +figcaption, +figure, +main { + /* 1 */ + display: block; } + +/** + * Add the correct margin in IE 8. + */ +figure { + margin: 1em 40px; } + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ +hr { + box-sizing: content-box; + /* 1 */ + height: 0; + /* 1 */ + overflow: visible; + /* 2 */ } + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +pre { + font-family: monospace, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ } + +/* Text-level semantics + ========================================================================== */ +/** + * 1. Remove the gray background on active links in IE 10. + * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. + */ +a { + background-color: transparent; + /* 1 */ + -webkit-text-decoration-skip: objects; + /* 2 */ } + +/** + * 1. Remove the bottom border in Chrome 57- and Firefox 39-. + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ +abbr[title] { + border-bottom: none; + /* 1 */ + text-decoration: underline; + /* 2 */ + text-decoration: underline dotted; + /* 2 */ } + +/** + * Prevent the duplicate application of `bolder` by the next rule in Safari 6. + */ +b, +strong { + font-weight: inherit; } + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ +b, +strong { + font-weight: bolder; } + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +code, +kbd, +samp { + font-family: monospace, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ } + +/** + * Add the correct font style in Android 4.3-. + */ +dfn { + font-style: italic; } + +/** + * Add the correct background and color in IE 9-. + */ +mark { + background-color: #ff0; + color: #000; } + +/** + * Add the correct font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sub { + bottom: -0.25em; } + +sup { + top: -0.5em; } + +/* Embedded content + ========================================================================== */ +/** + * Add the correct display in IE 9-. + */ +audio, +video { + display: inline-block; } + +/** + * Add the correct display in iOS 4-7. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Remove the border on images inside links in IE 10-. + */ +img { + border-style: none; } + +/** + * Hide the overflow in IE. + */ +svg:not(:root) { + overflow: hidden; } + +/* Forms + ========================================================================== */ +/** + * 1. Change the font styles in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. + */ +button, +input, +optgroup, +select, +textarea { + font-family: sans-serif; + /* 1 */ + font-size: 100%; + /* 1 */ + line-height: 1.15; + /* 1 */ + margin: 0; + /* 2 */ } + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ +button, +input { + /* 1 */ + overflow: visible; } + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ +button, +select { + /* 1 */ + text-transform: none; } + +/** + * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` + * controls in Android 4. + * 2. Correct the inability to style clickable types in iOS and Safari. + */ +button, +html [type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; + /* 2 */ } + +/** + * Remove the inner border and padding in Firefox. + */ +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; } + +/** + * Restore the focus styles unset by the previous rule. + */ +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; } + +/** + * Correct the padding in Firefox. + */ +fieldset { + padding: 0.35em 0.75em 0.625em; } + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ +legend { + box-sizing: border-box; + /* 1 */ + color: inherit; + /* 2 */ + display: table; + /* 1 */ + max-width: 100%; + /* 1 */ + padding: 0; + /* 3 */ + white-space: normal; + /* 1 */ } + +/** + * 1. Add the correct display in IE 9-. + * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ +progress { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Remove the default vertical scrollbar in IE. + */ +textarea { + overflow: auto; } + +/** + * 1. Add the correct box sizing in IE 10-. + * 2. Remove the padding in IE 10-. + */ +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ +[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ } + +/** + * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. + */ +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ } + +/* Interactive + ========================================================================== */ +/* + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. + */ +details, +menu { + display: block; } + +/* + * Add the correct display in all browsers. + */ +summary { + display: list-item; } + +/* Scripting + ========================================================================== */ +/** + * Add the correct display in IE 9-. + */ +canvas { + display: inline-block; } + +/** + * Add the correct display in IE. + */ +template { + display: none; } + +/* Hidden + ========================================================================== */ +/** + * Add the correct display in IE 10-. + */ +[hidden] { + display: none; } + +html { + box-sizing: border-box; } + +*, *:before, *:after { + box-sizing: inherit; } + +button, +input, +optgroup, +select, +textarea { + font-family: Seravek, Helvetica, Roboto, Arial, sans-serif; } + +ul:not(.browser-default) { + padding-left: 0; + list-style-type: none; } + ul:not(.browser-default) > li { + list-style-type: none; } + +a { + color: #336362; + text-decoration: none; + -webkit-tap-highlight-color: transparent; } + +.valign-wrapper { + display: flex; + align-items: center; } + +.clearfix { + clear: both; } + +.z-depth-0 { + box-shadow: none !important; } + +/* 2dp elevation modified*/ +.z-depth-1, nav, .card-panel, .card, .toast, .btn, .btn-large, .btn-small, .btn-floating, .dropdown-content, .collapsible, .sidenav { + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2); } + +.z-depth-1-half, .btn:hover, .btn-large:hover, .btn-small:hover, .btn-floating:hover { + box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.14), 0 1px 7px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -1px rgba(0, 0, 0, 0.2); } + +/* 6dp elevation modified*/ +.z-depth-2 { + box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.3); } + +/* 12dp elevation modified*/ +.z-depth-3 { + box-shadow: 0 8px 17px 2px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12), 0 5px 5px -3px rgba(0, 0, 0, 0.2); } + +/* 16dp elevation */ +.z-depth-4 { + box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -7px rgba(0, 0, 0, 0.2); } + +/* 24dp elevation */ +.z-depth-5, .modal { + box-shadow: 0 24px 38px 3px rgba(0, 0, 0, 0.14), 0 9px 46px 8px rgba(0, 0, 0, 0.12), 0 11px 15px -7px rgba(0, 0, 0, 0.2); } + +.hoverable { + transition: box-shadow .25s; } + .hoverable:hover { + box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); } + +.divider { + height: 1px; + overflow: hidden; + background-color: #e0e0e0; } + +blockquote { + margin: 20px 0; + padding-left: 1.5rem; + border-left: 5px solid #B84000; } + +i { + line-height: inherit; } + i.left { + float: left; + margin-right: 15px; } + i.right { + float: right; + margin-left: 15px; } + i.tiny { + font-size: 1rem; } + i.small { + font-size: 2rem; } + i.medium { + font-size: 4rem; } + i.large { + font-size: 6rem; } + +img.responsive-img, +video.responsive-video { + max-width: 100%; + height: auto; } + +.pagination li { + display: inline-block; + border-radius: 2px; + text-align: center; + vertical-align: top; + height: 30px; } + .pagination li a { + color: #444; + display: inline-block; + font-size: 1.2rem; + padding: 0 10px; + line-height: 30px; } + .pagination li.active a { + color: #fff; } + .pagination li.active { + background-color: #B84000; } + .pagination li.disabled a { + cursor: default; + color: #999; } + .pagination li i { + font-size: 2rem; } +.pagination li.pages ul li { + display: inline-block; + float: none; } + +@media only screen and (max-width: 992px) { + .pagination { + width: 100%; } + .pagination li.prev, + .pagination li.next { + width: 10%; } + .pagination li.pages { + width: 80%; + overflow: hidden; + white-space: nowrap; } } +.breadcrumb { + font-size: 18px; + color: rgba(255, 255, 255, 0.7); } + .breadcrumb i, + .breadcrumb [class^="mdi-"], .breadcrumb [class*="mdi-"], + .breadcrumb i.material-icons { + display: inline-block; + float: left; + font-size: 24px; } + .breadcrumb:before { + content: '\E5CC'; + color: rgba(255, 255, 255, 0.7); + vertical-align: top; + display: inline-block; + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 25px; + margin: 0 10px 0 8px; + -webkit-font-smoothing: antialiased; } + .breadcrumb:first-child:before { + display: none; } + .breadcrumb:last-child { + color: #fff; } + +.parallax-container { + position: relative; + overflow: hidden; + height: 500px; } + .parallax-container .parallax { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: -1; } + .parallax-container .parallax img { + opacity: 0; + position: absolute; + left: 50%; + bottom: 0; + min-width: 100%; + min-height: 100%; + transform: translate3d(0, 0, 0); + transform: translateX(-50%); } + +.pin-top, .pin-bottom { + position: relative; } + +.pinned { + position: fixed !important; } + +/********************* + Transition Classes +**********************/ +ul.staggered-list li { + opacity: 0; } + +.fade-in { + opacity: 0; + transform-origin: 0 50%; } + +/********************* + Media Query Classes +**********************/ +@media only screen and (max-width: 600px) { + .hide-on-small-only, .hide-on-small-and-down { + display: none !important; } } + +@media only screen and (max-width: 992px) { + .hide-on-med-and-down { + display: none !important; } } + +@media only screen and (min-width: 601px) { + .hide-on-med-and-up { + display: none !important; } } + +@media only screen and (min-width: 600px) and (max-width: 992px) { + .hide-on-med-only { + display: none !important; } } + +@media only screen and (min-width: 993px) { + .hide-on-large-only { + display: none !important; } } + +@media only screen and (min-width: 1201px) { + .hide-on-extra-large-only { + display: none !important; } } + +@media only screen and (min-width: 1201px) { + .show-on-extra-large { + display: block !important; } } + +@media only screen and (min-width: 993px) { + .show-on-large { + display: block !important; } } + +@media only screen and (min-width: 600px) and (max-width: 992px) { + .show-on-medium { + display: block !important; } } + +@media only screen and (max-width: 600px) { + .show-on-small { + display: block !important; } } + +@media only screen and (min-width: 601px) { + .show-on-medium-and-up { + display: block !important; } } + +@media only screen and (max-width: 992px) { + .show-on-medium-and-down { + display: block !important; } } + +@media only screen and (max-width: 600px) { + .center-on-small-only { + text-align: center; } } + +.page-footer { + padding-top: 20px; + color: #fff; + background-color: #B84000; } + .page-footer .footer-copyright { + overflow: hidden; + min-height: 50px; + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0px; + color: rgba(255, 255, 255, 0.8); + background-color: rgba(51, 51, 51, 0.08); } + +table, th, td { + border: none; } + +table { + width: 100%; + display: table; + border-collapse: collapse; + border-spacing: 0; } + table.striped tr { + border-bottom: none; } + table.striped > tbody > tr:nth-child(odd) { + background-color: rgba(242, 242, 242, 0.5); } + table.striped > tbody > tr > td { + border-radius: 0; } + table.highlight > tbody > tr { + transition: background-color .25s ease; } + table.highlight > tbody > tr:hover { + background-color: rgba(242, 242, 242, 0.5); } + table.centered thead tr th, table.centered tbody tr td { + text-align: center; } + +tr { + border-bottom: 1px solid rgba(0, 0, 0, 0.12); } + +td, th { + padding: 15px 5px; + display: table-cell; + text-align: left; + vertical-align: middle; + border-radius: 2px; } + +@media only screen and (max-width: 992px) { + table.responsive-table { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + display: block; + position: relative; + /* sort out borders */ } + table.responsive-table td:empty:before { + content: '\00a0'; } + table.responsive-table th, + table.responsive-table td { + margin: 0; + vertical-align: top; } + table.responsive-table th { + text-align: left; } + table.responsive-table thead { + display: block; + float: left; } + table.responsive-table thead tr { + display: block; + padding: 0 10px 0 0; } + table.responsive-table thead tr th::before { + content: "\00a0"; } + table.responsive-table tbody { + display: block; + width: auto; + position: relative; + overflow-x: auto; + white-space: nowrap; } + table.responsive-table tbody tr { + display: inline-block; + vertical-align: top; } + table.responsive-table th { + display: block; + text-align: right; } + table.responsive-table td { + display: block; + min-height: 1.25em; + text-align: left; } + table.responsive-table tr { + border-bottom: none; + padding: 0 10px; } + table.responsive-table thead { + border: 0; + border-right: 1px solid rgba(0, 0, 0, 0.12); } } +.collection { + margin: 0.5rem 0 1rem 0; + border: 1px solid #e0e0e0; + border-radius: 2px; + overflow: hidden; + position: relative; } + .collection .collection-item { + background-color: #fff; + line-height: 1.5rem; + padding: 10px 20px; + margin: 0; + border-bottom: 1px solid #e0e0e0; } + .collection .collection-item.avatar { + min-height: 84px; + padding-left: 72px; + position: relative; } + .collection .collection-item.avatar:not(.circle-clipper) > .circle, + .collection .collection-item.avatar :not(.circle-clipper) > .circle { + position: absolute; + width: 42px; + height: 42px; + overflow: hidden; + left: 15px; + display: inline-block; + vertical-align: middle; } + .collection .collection-item.avatar i.circle { + font-size: 18px; + line-height: 42px; + color: #fff; + background-color: #999; + text-align: center; } + .collection .collection-item.avatar .title { + font-size: 16px; } + .collection .collection-item.avatar p { + margin: 0; } + .collection .collection-item.avatar .secondary-content { + position: absolute; + top: 16px; + right: 16px; } + .collection .collection-item:last-child { + border-bottom: none; } + .collection .collection-item.active { + background-color: #4D9999; + color: white; } + .collection .collection-item.active .secondary-content { + color: #fff; } + .collection a.collection-item { + display: block; + transition: .25s; + color: #4D9999; } + .collection a.collection-item:not(.active):hover { + background-color: #ddd; } + .collection.with-header .collection-header { + background-color: #fff; + border-bottom: 1px solid #e0e0e0; + padding: 10px 20px; } + .collection.with-header .collection-item { + padding-left: 30px; } + .collection.with-header .collection-item.avatar { + padding-left: 72px; } + +.secondary-content { + float: right; + color: #4D9999; } + +.collapsible .collection { + margin: 0; + border: none; } + +.video-container { + position: relative; + padding-bottom: 56.25%; + height: 0; + overflow: hidden; } + .video-container iframe, .video-container object, .video-container embed { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; } + +.progress { + position: relative; + height: 4px; + display: block; + width: 100%; + background-color: #cce6e6; + border-radius: 2px; + margin: 0.5rem 0 1rem 0; + overflow: hidden; } + .progress .determinate { + position: absolute; + top: 0; + left: 0; + bottom: 0; + background-color: #4D9999; + transition: width .3s linear; } + .progress .indeterminate { + background-color: #4D9999; } + .progress .indeterminate:before { + content: ''; + position: absolute; + background-color: inherit; + top: 0; + left: 0; + bottom: 0; + will-change: left, right; + animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite; } + .progress .indeterminate:after { + content: ''; + position: absolute; + background-color: inherit; + top: 0; + left: 0; + bottom: 0; + will-change: left, right; + animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite; + animation-delay: 1.15s; } + +@keyframes indeterminate { + 0% { + left: -35%; + right: 100%; } + 60% { + left: 100%; + right: -90%; } + 100% { + left: 100%; + right: -90%; } } +@keyframes indeterminate-short { + 0% { + left: -200%; + right: 100%; } + 60% { + left: 107%; + right: -8%; } + 100% { + left: 107%; + right: -8%; } } +/******************* + Utility Classes +*******************/ +.hide { + display: none !important; } + +.left-align { + text-align: left; } + +.right-align { + text-align: right; } + +.center, .center-align { + text-align: center; } + +.left { + float: left !important; } + +.right { + float: right !important; } + +.no-select, input[type=range], +input[type=range] + .thumb { + user-select: none; } + +.circle { + border-radius: 50%; } + +.center-block { + display: block; + margin-left: auto; + margin-right: auto; } + +.truncate { + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } + +.no-padding { + padding: 0 !important; } + +span.badge { + min-width: 3rem; + padding: 0 6px; + margin-left: 14px; + text-align: center; + font-size: 1rem; + line-height: 22px; + height: 22px; + color: #757575; + float: right; + box-sizing: border-box; } + span.badge.new { + font-weight: 300; + font-size: 0.8rem; + color: #fff; + background-color: #4D9999; + border-radius: 2px; } + span.badge.new:after { + content: " new"; } + span.badge[data-badge-caption]::after { + content: " " attr(data-badge-caption); } + +nav ul a span.badge { + display: inline-block; + float: none; + margin-left: 4px; + line-height: 22px; + height: 22px; + -webkit-font-smoothing: auto; } + +.collection-item span.badge { + margin-top: calc(0.75rem - 11px); } + +.collapsible span.badge { + margin-left: auto; } + +.sidenav span.badge { + margin-top: calc(24px - 11px); } + +table span.badge { + display: inline-block; + float: none; + margin-left: auto; } + +/* This is needed for some mobile phones to display the Google Icon font properly */ +.material-icons { + text-rendering: optimizeLegibility; + font-feature-settings: 'liga'; } + +.container { + margin: 0 auto; + max-width: 1280px; + width: 90%; } + +@media only screen and (min-width: 601px) { + .container { + width: 85%; } } +@media only screen and (min-width: 993px) { + .container { + width: 70%; } } +.col .row { + margin-left: -0.75rem; + margin-right: -0.75rem; } + +.section { + padding-top: 1rem; + padding-bottom: 1rem; } + .section.no-pad { + padding: 0; } + .section.no-pad-bot { + padding-bottom: 0; } + .section.no-pad-top { + padding-top: 0; } + +.row { + margin-left: auto; + margin-right: auto; + margin-bottom: 20px; } + .row:after { + content: ""; + display: table; + clear: both; } + .row .col { + float: left; + box-sizing: border-box; + padding: 0 0.75rem; + min-height: 1px; } + .row .col[class*="push-"], .row .col[class*="pull-"] { + position: relative; } + .row .col.s1 { + width: 8.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s2 { + width: 16.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s3 { + width: 25%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s4 { + width: 33.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s5 { + width: 41.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s6 { + width: 50%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s7 { + width: 58.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s8 { + width: 66.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s9 { + width: 75%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s10 { + width: 83.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s11 { + width: 91.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.s12 { + width: 100%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.offset-s1 { + margin-left: 8.3333333333%; } + .row .col.pull-s1 { + right: 8.3333333333%; } + .row .col.push-s1 { + left: 8.3333333333%; } + .row .col.offset-s2 { + margin-left: 16.6666666667%; } + .row .col.pull-s2 { + right: 16.6666666667%; } + .row .col.push-s2 { + left: 16.6666666667%; } + .row .col.offset-s3 { + margin-left: 25%; } + .row .col.pull-s3 { + right: 25%; } + .row .col.push-s3 { + left: 25%; } + .row .col.offset-s4 { + margin-left: 33.3333333333%; } + .row .col.pull-s4 { + right: 33.3333333333%; } + .row .col.push-s4 { + left: 33.3333333333%; } + .row .col.offset-s5 { + margin-left: 41.6666666667%; } + .row .col.pull-s5 { + right: 41.6666666667%; } + .row .col.push-s5 { + left: 41.6666666667%; } + .row .col.offset-s6 { + margin-left: 50%; } + .row .col.pull-s6 { + right: 50%; } + .row .col.push-s6 { + left: 50%; } + .row .col.offset-s7 { + margin-left: 58.3333333333%; } + .row .col.pull-s7 { + right: 58.3333333333%; } + .row .col.push-s7 { + left: 58.3333333333%; } + .row .col.offset-s8 { + margin-left: 66.6666666667%; } + .row .col.pull-s8 { + right: 66.6666666667%; } + .row .col.push-s8 { + left: 66.6666666667%; } + .row .col.offset-s9 { + margin-left: 75%; } + .row .col.pull-s9 { + right: 75%; } + .row .col.push-s9 { + left: 75%; } + .row .col.offset-s10 { + margin-left: 83.3333333333%; } + .row .col.pull-s10 { + right: 83.3333333333%; } + .row .col.push-s10 { + left: 83.3333333333%; } + .row .col.offset-s11 { + margin-left: 91.6666666667%; } + .row .col.pull-s11 { + right: 91.6666666667%; } + .row .col.push-s11 { + left: 91.6666666667%; } + .row .col.offset-s12 { + margin-left: 100%; } + .row .col.pull-s12 { + right: 100%; } + .row .col.push-s12 { + left: 100%; } + @media only screen and (min-width: 601px) { + .row .col.m1 { + width: 8.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m2 { + width: 16.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m3 { + width: 25%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m4 { + width: 33.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m5 { + width: 41.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m6 { + width: 50%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m7 { + width: 58.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m8 { + width: 66.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m9 { + width: 75%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m10 { + width: 83.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m11 { + width: 91.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.m12 { + width: 100%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.offset-m1 { + margin-left: 8.3333333333%; } + .row .col.pull-m1 { + right: 8.3333333333%; } + .row .col.push-m1 { + left: 8.3333333333%; } + .row .col.offset-m2 { + margin-left: 16.6666666667%; } + .row .col.pull-m2 { + right: 16.6666666667%; } + .row .col.push-m2 { + left: 16.6666666667%; } + .row .col.offset-m3 { + margin-left: 25%; } + .row .col.pull-m3 { + right: 25%; } + .row .col.push-m3 { + left: 25%; } + .row .col.offset-m4 { + margin-left: 33.3333333333%; } + .row .col.pull-m4 { + right: 33.3333333333%; } + .row .col.push-m4 { + left: 33.3333333333%; } + .row .col.offset-m5 { + margin-left: 41.6666666667%; } + .row .col.pull-m5 { + right: 41.6666666667%; } + .row .col.push-m5 { + left: 41.6666666667%; } + .row .col.offset-m6 { + margin-left: 50%; } + .row .col.pull-m6 { + right: 50%; } + .row .col.push-m6 { + left: 50%; } + .row .col.offset-m7 { + margin-left: 58.3333333333%; } + .row .col.pull-m7 { + right: 58.3333333333%; } + .row .col.push-m7 { + left: 58.3333333333%; } + .row .col.offset-m8 { + margin-left: 66.6666666667%; } + .row .col.pull-m8 { + right: 66.6666666667%; } + .row .col.push-m8 { + left: 66.6666666667%; } + .row .col.offset-m9 { + margin-left: 75%; } + .row .col.pull-m9 { + right: 75%; } + .row .col.push-m9 { + left: 75%; } + .row .col.offset-m10 { + margin-left: 83.3333333333%; } + .row .col.pull-m10 { + right: 83.3333333333%; } + .row .col.push-m10 { + left: 83.3333333333%; } + .row .col.offset-m11 { + margin-left: 91.6666666667%; } + .row .col.pull-m11 { + right: 91.6666666667%; } + .row .col.push-m11 { + left: 91.6666666667%; } + .row .col.offset-m12 { + margin-left: 100%; } + .row .col.pull-m12 { + right: 100%; } + .row .col.push-m12 { + left: 100%; } } + @media only screen and (min-width: 993px) { + .row .col.l1 { + width: 8.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l2 { + width: 16.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l3 { + width: 25%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l4 { + width: 33.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l5 { + width: 41.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l6 { + width: 50%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l7 { + width: 58.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l8 { + width: 66.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l9 { + width: 75%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l10 { + width: 83.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l11 { + width: 91.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.l12 { + width: 100%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.offset-l1 { + margin-left: 8.3333333333%; } + .row .col.pull-l1 { + right: 8.3333333333%; } + .row .col.push-l1 { + left: 8.3333333333%; } + .row .col.offset-l2 { + margin-left: 16.6666666667%; } + .row .col.pull-l2 { + right: 16.6666666667%; } + .row .col.push-l2 { + left: 16.6666666667%; } + .row .col.offset-l3 { + margin-left: 25%; } + .row .col.pull-l3 { + right: 25%; } + .row .col.push-l3 { + left: 25%; } + .row .col.offset-l4 { + margin-left: 33.3333333333%; } + .row .col.pull-l4 { + right: 33.3333333333%; } + .row .col.push-l4 { + left: 33.3333333333%; } + .row .col.offset-l5 { + margin-left: 41.6666666667%; } + .row .col.pull-l5 { + right: 41.6666666667%; } + .row .col.push-l5 { + left: 41.6666666667%; } + .row .col.offset-l6 { + margin-left: 50%; } + .row .col.pull-l6 { + right: 50%; } + .row .col.push-l6 { + left: 50%; } + .row .col.offset-l7 { + margin-left: 58.3333333333%; } + .row .col.pull-l7 { + right: 58.3333333333%; } + .row .col.push-l7 { + left: 58.3333333333%; } + .row .col.offset-l8 { + margin-left: 66.6666666667%; } + .row .col.pull-l8 { + right: 66.6666666667%; } + .row .col.push-l8 { + left: 66.6666666667%; } + .row .col.offset-l9 { + margin-left: 75%; } + .row .col.pull-l9 { + right: 75%; } + .row .col.push-l9 { + left: 75%; } + .row .col.offset-l10 { + margin-left: 83.3333333333%; } + .row .col.pull-l10 { + right: 83.3333333333%; } + .row .col.push-l10 { + left: 83.3333333333%; } + .row .col.offset-l11 { + margin-left: 91.6666666667%; } + .row .col.pull-l11 { + right: 91.6666666667%; } + .row .col.push-l11 { + left: 91.6666666667%; } + .row .col.offset-l12 { + margin-left: 100%; } + .row .col.pull-l12 { + right: 100%; } + .row .col.push-l12 { + left: 100%; } } + @media only screen and (min-width: 1201px) { + .row .col.xl1 { + width: 8.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl2 { + width: 16.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl3 { + width: 25%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl4 { + width: 33.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl5 { + width: 41.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl6 { + width: 50%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl7 { + width: 58.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl8 { + width: 66.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl9 { + width: 75%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl10 { + width: 83.3333333333%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl11 { + width: 91.6666666667%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.xl12 { + width: 100%; + margin-left: auto; + left: auto; + right: auto; } + .row .col.offset-xl1 { + margin-left: 8.3333333333%; } + .row .col.pull-xl1 { + right: 8.3333333333%; } + .row .col.push-xl1 { + left: 8.3333333333%; } + .row .col.offset-xl2 { + margin-left: 16.6666666667%; } + .row .col.pull-xl2 { + right: 16.6666666667%; } + .row .col.push-xl2 { + left: 16.6666666667%; } + .row .col.offset-xl3 { + margin-left: 25%; } + .row .col.pull-xl3 { + right: 25%; } + .row .col.push-xl3 { + left: 25%; } + .row .col.offset-xl4 { + margin-left: 33.3333333333%; } + .row .col.pull-xl4 { + right: 33.3333333333%; } + .row .col.push-xl4 { + left: 33.3333333333%; } + .row .col.offset-xl5 { + margin-left: 41.6666666667%; } + .row .col.pull-xl5 { + right: 41.6666666667%; } + .row .col.push-xl5 { + left: 41.6666666667%; } + .row .col.offset-xl6 { + margin-left: 50%; } + .row .col.pull-xl6 { + right: 50%; } + .row .col.push-xl6 { + left: 50%; } + .row .col.offset-xl7 { + margin-left: 58.3333333333%; } + .row .col.pull-xl7 { + right: 58.3333333333%; } + .row .col.push-xl7 { + left: 58.3333333333%; } + .row .col.offset-xl8 { + margin-left: 66.6666666667%; } + .row .col.pull-xl8 { + right: 66.6666666667%; } + .row .col.push-xl8 { + left: 66.6666666667%; } + .row .col.offset-xl9 { + margin-left: 75%; } + .row .col.pull-xl9 { + right: 75%; } + .row .col.push-xl9 { + left: 75%; } + .row .col.offset-xl10 { + margin-left: 83.3333333333%; } + .row .col.pull-xl10 { + right: 83.3333333333%; } + .row .col.push-xl10 { + left: 83.3333333333%; } + .row .col.offset-xl11 { + margin-left: 91.6666666667%; } + .row .col.pull-xl11 { + right: 91.6666666667%; } + .row .col.push-xl11 { + left: 91.6666666667%; } + .row .col.offset-xl12 { + margin-left: 100%; } + .row .col.pull-xl12 { + right: 100%; } + .row .col.push-xl12 { + left: 100%; } } + +nav { + color: #fff; + background-color: #B84000; + width: 100%; + height: 56px; + line-height: 56px; } + nav.nav-extended { + height: auto; } + nav.nav-extended .nav-wrapper { + min-height: 56px; + height: auto; } + nav.nav-extended .nav-content { + position: relative; + line-height: normal; } + nav a { + color: #fff; } + nav i, + nav [class^="mdi-"], nav [class*="mdi-"], + nav i.material-icons { + display: block; + font-size: 24px; + height: 56px; + line-height: 56px; } + nav .nav-wrapper { + position: relative; + height: 100%; } + @media only screen and (min-width: 993px) { + nav a.sidenav-trigger { + display: none; } } + nav .sidenav-trigger { + float: left; + position: relative; + z-index: 1; + height: 56px; + margin: 0 18px; } + nav .sidenav-trigger i { + height: 56px; + line-height: 56px; } + nav .brand-logo { + position: absolute; + color: #fff; + display: inline-block; + font-size: 2.1rem; + padding: 0; } + nav .brand-logo.center { + left: 50%; + transform: translateX(-50%); } + @media only screen and (max-width: 992px) { + nav .brand-logo { + left: 50%; + transform: translateX(-50%); } + nav .brand-logo.left, nav .brand-logo.right { + padding: 0; + transform: none; } + nav .brand-logo.left { + left: 0.5rem; } + nav .brand-logo.right { + right: 0.5rem; + left: auto; } } + nav .brand-logo.right { + right: 0.5rem; + padding: 0; } + nav .brand-logo i, + nav .brand-logo [class^="mdi-"], nav .brand-logo [class*="mdi-"], + nav .brand-logo i.material-icons { + float: left; + margin-right: 15px; } + nav .nav-title { + display: inline-block; + font-size: 32px; + padding: 28px 0; } + nav ul { + margin: 0; } + nav ul li { + transition: background-color .3s; + float: left; + padding: 0; } + nav ul li.active { + background-color: rgba(0, 0, 0, 0.1); } + nav ul a { + transition: background-color .3s; + font-size: 1rem; + color: #fff; + display: block; + padding: 0 15px; + cursor: pointer; } + nav ul a.btn, nav ul a.btn-large, nav ul a.btn-small, nav ul a.btn-large, nav ul a.btn-flat, nav ul a.btn-floating { + margin-top: -2px; + margin-left: 15px; + margin-right: 15px; } + nav ul a.btn > .material-icons, nav ul a.btn-large > .material-icons, nav ul a.btn-small > .material-icons, nav ul a.btn-large > .material-icons, nav ul a.btn-flat > .material-icons, nav ul a.btn-floating > .material-icons { + height: inherit; + line-height: inherit; } + nav ul a:hover { + background-color: rgba(0, 0, 0, 0.1); } + nav ul.left { + float: left; } + nav form { + height: 100%; } + nav .input-field { + margin: 0; + height: 100%; } + nav .input-field input { + height: 100%; + font-size: 1.2rem; + border: none; + padding-left: 2rem; } + nav .input-field input:focus, nav .input-field input[type=text]:valid, nav .input-field input[type=password]:valid, nav .input-field input[type=email]:valid, nav .input-field input[type=url]:valid, nav .input-field input[type=date]:valid { + border: none; + box-shadow: none; } + nav .input-field label { + top: 0; + left: 0; } + nav .input-field label i { + color: rgba(255, 255, 255, 0.7); + transition: color .3s; } + nav .input-field label.active i { + color: #fff; } + +.navbar-fixed { + position: relative; + height: 56px; + z-index: 997; } + .navbar-fixed nav { + position: fixed; } + +@media only screen and (min-width: 601px) { + nav.nav-extended .nav-wrapper { + min-height: 64px; } + + nav, nav .nav-wrapper i, nav a.sidenav-trigger, nav a.sidenav-trigger i { + height: 64px; + line-height: 64px; } + + .navbar-fixed { + height: 64px; } } +a { + text-decoration: none; } + +html { + line-height: 1.5; + font-family: Seravek, Helvetica, Roboto, Arial, sans-serif; + font-weight: normal; + color: rgba(0, 0, 0, 0.87); } + @media only screen and (min-width: 0) { + html { + font-size: 14px; } } + @media only screen and (min-width: 992px) { + html { + font-size: 14.5px; } } + @media only screen and (min-width: 1200px) { + html { + font-size: 15px; } } + +h1, h2, h3, h4, h5, h6 { + font-weight: 400; + line-height: 1.3; } + +h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { + font-weight: inherit; } + +h1 { + font-size: 1.4em; + line-height: 110%; + margin: 0.9333333333em 0 0.56em 0; } + +h2 { + font-size: 1.2em; + line-height: 110%; + margin: 0.8em 0 0.48em 0; } + +h3 { + font-size: 1em; + line-height: 110%; + margin: 0.6666666667em 0 0.4em 0; } + +h4 { + font-size: 0.8em; + line-height: 110%; + margin: 0.5333333333em 0 0.32em 0; } + +h5 { + font-size: 0.8em; + line-height: 110%; + margin: 0.5333333333em 0 0.32em 0; } + +h6 { + font-size: 1.15rem; + line-height: 110%; + margin: 0.7666666667rem 0 0.46rem 0; } + +em { + font-style: italic; } + +strong { + font-weight: 500; } + +small { + font-size: 75%; } + +.light { + font-weight: 300; } + +.thin { + font-weight: 200; } + +@media only screen and (min-width: 360px) { + .flow-text { + font-size: 1.2rem; } } +@media only screen and (min-width: 390px) { + .flow-text { + font-size: 1.224rem; } } +@media only screen and (min-width: 420px) { + .flow-text { + font-size: 1.248rem; } } +@media only screen and (min-width: 450px) { + .flow-text { + font-size: 1.272rem; } } +@media only screen and (min-width: 480px) { + .flow-text { + font-size: 1.296rem; } } +@media only screen and (min-width: 510px) { + .flow-text { + font-size: 1.32rem; } } +@media only screen and (min-width: 540px) { + .flow-text { + font-size: 1.344rem; } } +@media only screen and (min-width: 570px) { + .flow-text { + font-size: 1.368rem; } } +@media only screen and (min-width: 600px) { + .flow-text { + font-size: 1.392rem; } } +@media only screen and (min-width: 630px) { + .flow-text { + font-size: 1.416rem; } } +@media only screen and (min-width: 660px) { + .flow-text { + font-size: 1.44rem; } } +@media only screen and (min-width: 690px) { + .flow-text { + font-size: 1.464rem; } } +@media only screen and (min-width: 720px) { + .flow-text { + font-size: 1.488rem; } } +@media only screen and (min-width: 750px) { + .flow-text { + font-size: 1.512rem; } } +@media only screen and (min-width: 780px) { + .flow-text { + font-size: 1.536rem; } } +@media only screen and (min-width: 810px) { + .flow-text { + font-size: 1.56rem; } } +@media only screen and (min-width: 840px) { + .flow-text { + font-size: 1.584rem; } } +@media only screen and (min-width: 870px) { + .flow-text { + font-size: 1.608rem; } } +@media only screen and (min-width: 900px) { + .flow-text { + font-size: 1.632rem; } } +@media only screen and (min-width: 930px) { + .flow-text { + font-size: 1.656rem; } } +@media only screen and (min-width: 960px) { + .flow-text { + font-size: 1.68rem; } } +@media only screen and (max-width: 360px) { + .flow-text { + font-size: 1.2rem; } } + +.scale-transition { + transition: transform 0.3s cubic-bezier(0.53, 0.01, 0.36, 1.63) !important; } + .scale-transition.scale-out { + transform: scale(0); + transition: transform .2s !important; } + .scale-transition.scale-in { + transform: scale(1); } + +.card-panel { + transition: box-shadow .25s; + padding: 24px; + margin: 0.5rem 0 1rem 0; + border-radius: 2px; + background-color: #fff; } + +.card { + position: relative; + margin: 0.5rem 0 1rem 0; + background-color: #fff; + transition: box-shadow .25s; + border-radius: 2px; } + .card .card-title { + font-size: 24px; + font-weight: 300; } + .card .card-title.activator { + cursor: pointer; } + .card.small, .card.medium, .card.large { + position: relative; } + .card.small .card-image, .card.medium .card-image, .card.large .card-image { + max-height: 60%; + overflow: hidden; } + .card.small .card-image + .card-content, .card.medium .card-image + .card-content, .card.large .card-image + .card-content { + max-height: 40%; } + .card.small .card-content, .card.medium .card-content, .card.large .card-content { + max-height: 100%; + overflow: hidden; } + .card.small .card-action, .card.medium .card-action, .card.large .card-action { + position: absolute; + bottom: 0; + left: 0; + right: 0; } + .card.small { + height: 300px; } + .card.medium { + height: 400px; } + .card.large { + height: 500px; } + .card.horizontal { + display: flex; } + .card.horizontal.small .card-image, .card.horizontal.medium .card-image, .card.horizontal.large .card-image { + height: 100%; + max-height: none; + overflow: visible; } + .card.horizontal.small .card-image img, .card.horizontal.medium .card-image img, .card.horizontal.large .card-image img { + height: 100%; } + .card.horizontal .card-image { + max-width: 50%; } + .card.horizontal .card-image img { + border-radius: 2px 0 0 2px; + max-width: 100%; + width: auto; } + .card.horizontal .card-stacked { + display: flex; + flex-direction: column; + flex: 1; + position: relative; } + .card.horizontal .card-stacked .card-content { + flex-grow: 1; } + .card.sticky-action .card-action { + z-index: 2; } + .card.sticky-action .card-reveal { + z-index: 1; + padding-bottom: 64px; } + .card .card-image { + position: relative; } + .card .card-image img { + display: block; + border-radius: 2px 2px 0 0; + position: relative; + left: 0; + right: 0; + top: 0; + bottom: 0; + width: 100%; } + .card .card-image .card-title { + color: #fff; + position: absolute; + bottom: 0; + left: 0; + max-width: 100%; + padding: 24px; } + .card .card-content { + padding: 24px; + border-radius: 0 0 2px 2px; } + .card .card-content p { + margin: 0; } + .card .card-content .card-title { + display: block; + line-height: 32px; + margin-bottom: 8px; } + .card .card-content .card-title i { + line-height: 32px; } + .card .card-action { + background-color: inherit; + border-top: 1px solid rgba(160, 160, 160, 0.2); + position: relative; + padding: 16px 24px; } + .card .card-action:last-child { + border-radius: 0 0 2px 2px; } + .card .card-action a:not(.btn):not(.btn-large):not(.btn-small):not(.btn-large):not(.btn-floating) { + color: #ffab40; + margin-right: 24px; + transition: color .3s ease; + text-transform: uppercase; } + .card .card-action a:not(.btn):not(.btn-large):not(.btn-small):not(.btn-large):not(.btn-floating):hover { + color: #ffd8a6; } + .card .card-reveal { + padding: 24px; + position: absolute; + background-color: #fff; + width: 100%; + overflow-y: auto; + left: 0; + top: 100%; + height: 100%; + z-index: 3; + display: none; } + .card .card-reveal .card-title { + cursor: pointer; + display: block; } + +#toast-container { + display: block; + position: fixed; + z-index: 10000; } + @media only screen and (max-width: 600px) { + #toast-container { + min-width: 100%; + bottom: 0%; } } + @media only screen and (min-width: 601px) and (max-width: 992px) { + #toast-container { + left: 5%; + bottom: 7%; + max-width: 90%; } } + @media only screen and (min-width: 993px) { + #toast-container { + top: 10%; + right: 7%; + max-width: 86%; } } + +.toast { + border-radius: 2px; + top: 35px; + width: auto; + margin-top: 10px; + position: relative; + max-width: 100%; + height: auto; + min-height: 48px; + line-height: 1.5em; + background-color: #323232; + padding: 10px 25px; + font-size: 1.1rem; + font-weight: 300; + color: #fff; + display: flex; + align-items: center; + justify-content: space-between; + cursor: default; } + .toast .toast-action { + color: #eeff41; + font-weight: 500; + margin-right: -25px; + margin-left: 3rem; } + .toast.rounded { + border-radius: 24px; } + @media only screen and (max-width: 600px) { + .toast { + width: 100%; + border-radius: 0; } } + +.tabs { + position: relative; + overflow-x: auto; + overflow-y: hidden; + height: 48px; + width: 100%; + background-color: #fff; + margin: 0 auto; + white-space: nowrap; } + .tabs.tabs-transparent { + background-color: transparent; } + .tabs.tabs-transparent .tab a, + .tabs.tabs-transparent .tab.disabled a, + .tabs.tabs-transparent .tab.disabled a:hover { + color: rgba(255, 255, 255, 0.7); } + .tabs.tabs-transparent .tab a:hover, + .tabs.tabs-transparent .tab a.active { + color: #fff; } + .tabs.tabs-transparent .indicator { + background-color: #fff; } + .tabs.tabs-fixed-width { + display: flex; } + .tabs.tabs-fixed-width .tab { + flex-grow: 1; } + .tabs .tab { + display: inline-block; + text-align: center; + line-height: 48px; + height: 48px; + padding: 0; + margin: 0; + text-transform: uppercase; } + .tabs .tab a { + color: rgba(184, 64, 0, 0.7); + display: block; + width: 100%; + height: 100%; + padding: 0 24px; + font-size: 14px; + text-overflow: ellipsis; + overflow: hidden; + transition: color .28s ease, background-color .28s ease; } + .tabs .tab a:focus, .tabs .tab a:focus.active { + background-color: rgba(255, 238, 230, 0.2); + outline: none; } + .tabs .tab a:hover, .tabs .tab a.active { + background-color: transparent; + color: #B84000; } + .tabs .tab.disabled a, .tabs .tab.disabled a:hover { + color: rgba(184, 64, 0, 0.4); + cursor: default; } + .tabs .indicator { + position: absolute; + bottom: 0; + height: 2px; + background-color: #ffeee6; + will-change: left, right; } + +@media only screen and (max-width: 992px) { + .tabs { + display: flex; } + .tabs .tab { + flex-grow: 1; } + .tabs .tab a { + padding: 0 12px; } } +.material-tooltip { + padding: 10px 8px; + font-size: 1rem; + z-index: 2000; + background-color: transparent; + border-radius: 2px; + color: #fff; + min-height: 36px; + line-height: 120%; + opacity: 0; + position: absolute; + text-align: center; + max-width: calc(100% - 4px); + overflow: hidden; + left: 0; + top: 0; + pointer-events: none; + visibility: hidden; + background-color: #323232; } + +.backdrop { + position: absolute; + opacity: 0; + height: 7px; + width: 14px; + border-radius: 0 0 50% 50%; + background-color: #323232; + z-index: -1; + transform-origin: 50% 0%; + visibility: hidden; } + +.btn, .btn-large, .btn-small, +.btn-flat { + border: none; + border-radius: 2px; + display: inline-block; + height: 36px; + line-height: 36px; + padding: 0 16px; + text-transform: uppercase; + vertical-align: middle; + -webkit-tap-highlight-color: transparent; } + +.btn.disabled, .disabled.btn-large, .disabled.btn-small, +.btn-floating.disabled, +.btn-large.disabled, +.btn-small.disabled, +.btn-flat.disabled, +.btn:disabled, +.btn-large:disabled, +.btn-small:disabled, +.btn-floating:disabled, +.btn-large:disabled, +.btn-small:disabled, +.btn-flat:disabled, +.btn[disabled], +[disabled].btn-large, +[disabled].btn-small, +.btn-floating[disabled], +.btn-large[disabled], +.btn-small[disabled], +.btn-flat[disabled] { + pointer-events: none; + background-color: #DFDFDF !important; + box-shadow: none; + color: #9F9F9F !important; + cursor: default; } + .btn.disabled:hover, .disabled.btn-large:hover, .disabled.btn-small:hover, + .btn-floating.disabled:hover, + .btn-large.disabled:hover, + .btn-small.disabled:hover, + .btn-flat.disabled:hover, + .btn:disabled:hover, + .btn-large:disabled:hover, + .btn-small:disabled:hover, + .btn-floating:disabled:hover, + .btn-large:disabled:hover, + .btn-small:disabled:hover, + .btn-flat:disabled:hover, + .btn[disabled]:hover, + [disabled].btn-large:hover, + [disabled].btn-small:hover, + .btn-floating[disabled]:hover, + .btn-large[disabled]:hover, + .btn-small[disabled]:hover, + .btn-flat[disabled]:hover { + background-color: #DFDFDF !important; + color: #9F9F9F !important; } + +.btn, .btn-large, .btn-small, +.btn-floating, +.btn-large, +.btn-small, +.btn-flat { + font-size: 14px; + outline: 0; } + .btn i, .btn-large i, .btn-small i, + .btn-floating i, + .btn-large i, + .btn-small i, + .btn-flat i { + font-size: 1.3rem; + line-height: inherit; } + +.btn:focus, .btn-large:focus, .btn-small:focus, +.btn-floating:focus { + background-color: #3c7777; } + +.btn, .btn-large, .btn-small { + text-decoration: none; + color: #fff; + background-color: #4D9999; + text-align: center; + letter-spacing: .5px; + transition: background-color .2s ease-out; + cursor: pointer; } + .btn:hover, .btn-large:hover, .btn-small:hover { + background-color: #56aaaa; } + +.btn-floating { + display: inline-block; + color: #fff; + position: relative; + overflow: hidden; + z-index: 1; + width: 40px; + height: 40px; + line-height: 40px; + padding: 0; + background-color: #4D9999; + border-radius: 50%; + transition: background-color .3s; + cursor: pointer; + vertical-align: middle; } + .btn-floating:hover { + background-color: #4D9999; } + .btn-floating:before { + border-radius: 0; } + .btn-floating.btn-large { + width: 56px; + height: 56px; + padding: 0; } + .btn-floating.btn-large.halfway-fab { + bottom: -28px; } + .btn-floating.btn-large i { + line-height: 56px; } + .btn-floating.btn-small { + width: 32.4px; + height: 32.4px; } + .btn-floating.btn-small.halfway-fab { + bottom: -16.2px; } + .btn-floating.btn-small i { + line-height: 32.4px; } + .btn-floating.halfway-fab { + position: absolute; + right: 24px; + bottom: -20px; } + .btn-floating.halfway-fab.left { + right: auto; + left: 24px; } + .btn-floating i { + width: inherit; + display: inline-block; + text-align: center; + color: #fff; + font-size: 1.6rem; + line-height: 40px; } + +button.btn-floating { + border: none; } + +.fixed-action-btn { + position: fixed; + right: 23px; + bottom: 23px; + padding-top: 15px; + margin-bottom: 0; + z-index: 997; } + .fixed-action-btn.active ul { + visibility: visible; } + .fixed-action-btn.direction-left, .fixed-action-btn.direction-right { + padding: 0 0 0 15px; } + .fixed-action-btn.direction-left ul, .fixed-action-btn.direction-right ul { + text-align: right; + right: 64px; + top: 50%; + transform: translateY(-50%); + height: 100%; + left: auto; + /*width 100% only goes to width of button container */ + width: 500px; } + .fixed-action-btn.direction-left ul li, .fixed-action-btn.direction-right ul li { + display: inline-block; + margin: 7.5px 15px 0 0; } + .fixed-action-btn.direction-right { + padding: 0 15px 0 0; } + .fixed-action-btn.direction-right ul { + text-align: left; + direction: rtl; + left: 64px; + right: auto; } + .fixed-action-btn.direction-right ul li { + margin: 7.5px 0 0 15px; } + .fixed-action-btn.direction-bottom { + padding: 0 0 15px 0; } + .fixed-action-btn.direction-bottom ul { + top: 64px; + bottom: auto; + display: flex; + flex-direction: column-reverse; } + .fixed-action-btn.direction-bottom ul li { + margin: 15px 0 0 0; } + .fixed-action-btn.toolbar { + padding: 0; + height: 56px; } + .fixed-action-btn.toolbar.active > a i { + opacity: 0; } + .fixed-action-btn.toolbar ul { + display: flex; + top: 0; + bottom: 0; + z-index: 1; } + .fixed-action-btn.toolbar ul li { + flex: 1; + display: inline-block; + margin: 0; + height: 100%; + transition: none; } + .fixed-action-btn.toolbar ul li a { + display: block; + overflow: hidden; + position: relative; + width: 100%; + height: 100%; + background-color: transparent; + box-shadow: none; + color: #fff; + line-height: 56px; + z-index: 1; } + .fixed-action-btn.toolbar ul li a i { + line-height: inherit; } + .fixed-action-btn ul { + left: 0; + right: 0; + text-align: center; + position: absolute; + bottom: 64px; + margin: 0; + visibility: hidden; } + .fixed-action-btn ul li { + margin-bottom: 15px; } + .fixed-action-btn ul a.btn-floating { + opacity: 0; } + .fixed-action-btn .fab-backdrop { + position: absolute; + top: 0; + left: 0; + z-index: -1; + width: 40px; + height: 40px; + background-color: #4D9999; + border-radius: 50%; + transform: scale(0); } + +.btn-flat { + box-shadow: none; + background-color: transparent; + color: #343434; + cursor: pointer; + transition: background-color .2s; } + .btn-flat:focus, .btn-flat:hover { + box-shadow: none; } + .btn-flat:focus { + background-color: rgba(0, 0, 0, 0.1); } + .btn-flat.disabled, .btn-flat.btn-flat[disabled] { + background-color: transparent !important; + color: #b3b3b3 !important; + cursor: default; } + +.btn-large { + height: 54px; + line-height: 54px; + font-size: 15px; + padding: 0 28px; } + .btn-large i { + font-size: 1.6rem; } + +.btn-small { + height: 32.4px; + line-height: 32.4px; + font-size: 13px; } + .btn-small i { + font-size: 1.2rem; } + +.btn-block { + display: block; } + +.dropdown-content { + background-color: #fff; + margin: 0; + display: none; + min-width: 100px; + overflow-y: auto; + opacity: 0; + position: absolute; + left: 0; + top: 0; + z-index: 9999; + transform-origin: 0 0; } + .dropdown-content:focus { + outline: 0; } + .dropdown-content li { + clear: both; + color: rgba(0, 0, 0, 0.87); + cursor: pointer; + min-height: 50px; + line-height: 1.5rem; + width: 100%; + text-align: left; } + .dropdown-content li:hover, .dropdown-content li.active { + background-color: #eee; } + .dropdown-content li:focus { + outline: none; } + .dropdown-content li.divider { + min-height: 0; + height: 1px; } + .dropdown-content li > a, .dropdown-content li > span { + font-size: 16px; + color: #4D9999; + display: block; + line-height: 22px; + padding: 14px 16px; } + .dropdown-content li > span > label { + top: 1px; + left: 0; + height: 18px; } + .dropdown-content li > a > i { + height: inherit; + line-height: inherit; + float: left; + margin: 0 24px 0 0; + width: 24px; } + +body.keyboard-focused .dropdown-content li:focus { + background-color: #dadada; } + +.input-field.col .dropdown-content [type="checkbox"] + label { + top: 1px; + left: 0; + height: 18px; + transform: none; } + +.dropdown-trigger { + cursor: pointer; } + +/*! + * Waves v0.6.0 + * http://fian.my.id/Waves + * + * Copyright 2014 Alfiana E. Sibuea and other contributors + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + */ +.waves-effect { + position: relative; + cursor: pointer; + display: inline-block; + overflow: hidden; + user-select: none; + -webkit-tap-highlight-color: transparent; + vertical-align: middle; + z-index: 1; + transition: .3s ease-out; } + .waves-effect .waves-ripple { + position: absolute; + border-radius: 50%; + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + opacity: 0; + background: rgba(0, 0, 0, 0.2); + transition: all 0.7s ease-out; + transition-property: transform, opacity; + transform: scale(0); + pointer-events: none; } + .waves-effect.waves-light .waves-ripple { + background-color: rgba(255, 255, 255, 0.45); } + .waves-effect.waves-red .waves-ripple { + background-color: rgba(244, 67, 54, 0.7); } + .waves-effect.waves-yellow .waves-ripple { + background-color: rgba(255, 235, 59, 0.7); } + .waves-effect.waves-orange .waves-ripple { + background-color: rgba(255, 152, 0, 0.7); } + .waves-effect.waves-purple .waves-ripple { + background-color: rgba(156, 39, 176, 0.7); } + .waves-effect.waves-green .waves-ripple { + background-color: rgba(76, 175, 80, 0.7); } + .waves-effect.waves-teal .waves-ripple { + background-color: rgba(0, 150, 136, 0.7); } + .waves-effect input[type="button"], .waves-effect input[type="reset"], .waves-effect input[type="submit"] { + border: 0; + font-style: normal; + font-size: inherit; + text-transform: inherit; + background: none; } + .waves-effect img { + position: relative; + z-index: -1; } + +.waves-notransition { + transition: none !important; } + +.waves-circle { + transform: translateZ(0); + -webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%); } + +.waves-input-wrapper { + border-radius: 0.2em; + vertical-align: bottom; } + .waves-input-wrapper .waves-button-input { + position: relative; + top: 0; + left: 0; + z-index: 1; } + +.waves-circle { + text-align: center; + width: 2.5em; + height: 2.5em; + line-height: 2.5em; + border-radius: 50%; + -webkit-mask-image: none; } + +.waves-block { + display: block; } + +/* Firefox Bug: link not triggered */ +.waves-effect .waves-ripple { + z-index: -1; } + +.modal { + display: none; + position: fixed; + left: 0; + right: 0; + background-color: #fafafa; + padding: 0; + max-height: 70%; + width: 55%; + margin: auto; + overflow-y: auto; + border-radius: 2px; + will-change: top, opacity; } + .modal:focus { + outline: none; } + @media only screen and (max-width: 992px) { + .modal { + width: 80%; } } + .modal h1, .modal h2, .modal h3, .modal h4 { + margin-top: 0; } + .modal .modal-content { + padding: 24px; } + .modal .modal-close { + cursor: pointer; } + .modal .modal-footer { + border-radius: 0 0 2px 2px; + background-color: #fafafa; + padding: 4px 6px; + height: 56px; + width: 100%; + text-align: right; } + .modal .modal-footer .btn, .modal .modal-footer .btn-large, .modal .modal-footer .btn-small, .modal .modal-footer .btn-flat { + margin: 6px 0; } + +.modal-overlay { + position: fixed; + z-index: 999; + top: -25%; + left: 0; + bottom: 0; + right: 0; + height: 125%; + width: 100%; + background: #000; + display: none; + will-change: opacity; } + +.modal.modal-fixed-footer { + padding: 0; + height: 70%; } + .modal.modal-fixed-footer .modal-content { + position: absolute; + height: calc(100% - 56px); + max-height: 100%; + width: 100%; + overflow-y: auto; } + .modal.modal-fixed-footer .modal-footer { + border-top: 1px solid rgba(0, 0, 0, 0.1); + position: absolute; + bottom: 0; } + +.modal.bottom-sheet { + top: auto; + bottom: -100%; + margin: 0; + width: 100%; + max-height: 45%; + border-radius: 0; + will-change: bottom, opacity; } + +.collapsible { + border-top: 1px solid #ddd; + border-right: 1px solid #ddd; + border-left: 1px solid #ddd; + margin: 0.5rem 0 1rem 0; } + +.collapsible-header { + display: flex; + cursor: pointer; + -webkit-tap-highlight-color: transparent; + line-height: 1.5; + padding: 1rem; + background-color: #fff; + border-bottom: 1px solid #ddd; } + .collapsible-header:focus { + outline: 0; } + .collapsible-header i { + width: 2rem; + font-size: 1.6rem; + display: inline-block; + text-align: center; + margin-right: 1rem; } + +.keyboard-focused .collapsible-header:focus { + background-color: #eee; } + +.collapsible-body { + display: none; + border-bottom: 1px solid #ddd; + box-sizing: border-box; + padding: 2rem; } + +.sidenav .collapsible, +.sidenav.fixed .collapsible { + border: none; + box-shadow: none; } + .sidenav .collapsible li, + .sidenav.fixed .collapsible li { + padding: 0; } +.sidenav .collapsible-header, +.sidenav.fixed .collapsible-header { + background-color: transparent; + border: none; + line-height: inherit; + height: inherit; + padding: 0 16px; } + .sidenav .collapsible-header:hover, + .sidenav.fixed .collapsible-header:hover { + background-color: rgba(0, 0, 0, 0.05); } + .sidenav .collapsible-header i, + .sidenav.fixed .collapsible-header i { + line-height: inherit; } +.sidenav .collapsible-body, +.sidenav.fixed .collapsible-body { + border: 0; + background-color: #fff; } + .sidenav .collapsible-body li a, + .sidenav.fixed .collapsible-body li a { + padding: 0 23.5px 0 31px; } + +.collapsible.popout { + border: none; + box-shadow: none; } + .collapsible.popout > li { + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + margin: 0 24px; + transition: margin 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94); } + .collapsible.popout > li.active { + box-shadow: 0 5px 11px 0 rgba(0, 0, 0, 0.18), 0 4px 15px 0 rgba(0, 0, 0, 0.15); + margin: 16px 0; } + +.chip { + display: inline-block; + height: 32px; + font-size: 13px; + font-weight: 500; + color: rgba(0, 0, 0, 0.6); + line-height: 32px; + padding: 0 12px; + border-radius: 16px; + background-color: #e4e4e4; + margin-bottom: 5px; + margin-right: 5px; } + .chip:focus { + outline: none; + background-color: #26a69a; + color: #fff; } + .chip > img { + float: left; + margin: 0 8px 0 -12px; + height: 32px; + width: 32px; + border-radius: 50%; } + .chip .close { + cursor: pointer; + float: right; + font-size: 16px; + line-height: 32px; + padding-left: 8px; } + +.chips { + border: none; + border-bottom: 1px solid #9e9e9e; + box-shadow: none; + margin: 0 0 8px 0; + min-height: 45px; + outline: none; + transition: all .3s; } + .chips.focus { + border-bottom: 1px solid #26a69a; + box-shadow: 0 1px 0 0 #26a69a; } + .chips:hover { + cursor: text; } + .chips .input { + background: none; + border: 0; + color: rgba(0, 0, 0, 0.6); + display: inline-block; + font-size: 16px; + height: 3rem; + line-height: 32px; + outline: 0; + margin: 0; + padding: 0 !important; + width: 120px !important; } + .chips .input:focus { + border: 0 !important; + box-shadow: none !important; } + .chips .autocomplete-content { + margin-top: 0; + margin-bottom: 0; } + +.prefix ~ .chips { + margin-left: 3rem; + width: 92%; + width: calc(100% - 3rem); } + +.chips:empty ~ label { + font-size: 0.8rem; + transform: translateY(-140%); } + +.materialboxed { + display: block; + cursor: zoom-in; + position: relative; + transition: opacity .4s; + -webkit-backface-visibility: hidden; } + .materialboxed:hover:not(.active) { + opacity: .8; } + .materialboxed.active { + cursor: zoom-out; } + +#materialbox-overlay { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: #292929; + z-index: 1000; + will-change: opacity; } + +.materialbox-caption { + position: fixed; + display: none; + color: #fff; + line-height: 50px; + bottom: 0; + left: 0; + width: 100%; + text-align: center; + padding: 0% 15%; + height: 50px; + z-index: 1000; + -webkit-font-smoothing: antialiased; } + +select:focus { + outline: 1px solid #e4f2f2; } + +button:focus { + outline: none; + background-color: #54a7a7; } + +label { + font-size: 0.8rem; + color: #9e9e9e; } + +/* Text Inputs + Textarea + ========================================================================== */ +/* Style Placeholders */ +::placeholder { + color: #d1d1d1; } + +/* Text inputs */ +input:not([type]), +input[type=text]:not(.browser-default), +input[type=password]:not(.browser-default), +input[type=email]:not(.browser-default), +input[type=url]:not(.browser-default), +input[type=time]:not(.browser-default), +input[type=date]:not(.browser-default), +input[type=datetime]:not(.browser-default), +input[type=datetime-local]:not(.browser-default), +input[type=tel]:not(.browser-default), +input[type=number]:not(.browser-default), +input[type=search]:not(.browser-default), +textarea.materialize-textarea { + background-color: transparent; + border: none; + border-bottom: 1px solid #9e9e9e; + border-radius: 0; + outline: none; + height: 3rem; + width: 100%; + font-size: 16px; + margin: 0 0 8px 0; + padding: 0; + box-shadow: none; + box-sizing: content-box; + transition: box-shadow .3s, border .3s; } + input:not([type]):disabled, input:not([type])[readonly="readonly"], + input[type=text]:not(.browser-default):disabled, + input[type=text]:not(.browser-default)[readonly="readonly"], + input[type=password]:not(.browser-default):disabled, + input[type=password]:not(.browser-default)[readonly="readonly"], + input[type=email]:not(.browser-default):disabled, + input[type=email]:not(.browser-default)[readonly="readonly"], + input[type=url]:not(.browser-default):disabled, + input[type=url]:not(.browser-default)[readonly="readonly"], + input[type=time]:not(.browser-default):disabled, + input[type=time]:not(.browser-default)[readonly="readonly"], + input[type=date]:not(.browser-default):disabled, + input[type=date]:not(.browser-default)[readonly="readonly"], + input[type=datetime]:not(.browser-default):disabled, + input[type=datetime]:not(.browser-default)[readonly="readonly"], + input[type=datetime-local]:not(.browser-default):disabled, + input[type=datetime-local]:not(.browser-default)[readonly="readonly"], + input[type=tel]:not(.browser-default):disabled, + input[type=tel]:not(.browser-default)[readonly="readonly"], + input[type=number]:not(.browser-default):disabled, + input[type=number]:not(.browser-default)[readonly="readonly"], + input[type=search]:not(.browser-default):disabled, + input[type=search]:not(.browser-default)[readonly="readonly"], + textarea.materialize-textarea:disabled, + textarea.materialize-textarea[readonly="readonly"] { + color: rgba(0, 0, 0, 0.42); + border-bottom: 1px dotted rgba(0, 0, 0, 0.42); } + input:not([type]):disabled + label, input:not([type])[readonly="readonly"] + label, + input[type=text]:not(.browser-default):disabled + label, + input[type=text]:not(.browser-default)[readonly="readonly"] + label, + input[type=password]:not(.browser-default):disabled + label, + input[type=password]:not(.browser-default)[readonly="readonly"] + label, + input[type=email]:not(.browser-default):disabled + label, + input[type=email]:not(.browser-default)[readonly="readonly"] + label, + input[type=url]:not(.browser-default):disabled + label, + input[type=url]:not(.browser-default)[readonly="readonly"] + label, + input[type=time]:not(.browser-default):disabled + label, + input[type=time]:not(.browser-default)[readonly="readonly"] + label, + input[type=date]:not(.browser-default):disabled + label, + input[type=date]:not(.browser-default)[readonly="readonly"] + label, + input[type=datetime]:not(.browser-default):disabled + label, + input[type=datetime]:not(.browser-default)[readonly="readonly"] + label, + input[type=datetime-local]:not(.browser-default):disabled + label, + input[type=datetime-local]:not(.browser-default)[readonly="readonly"] + label, + input[type=tel]:not(.browser-default):disabled + label, + input[type=tel]:not(.browser-default)[readonly="readonly"] + label, + input[type=number]:not(.browser-default):disabled + label, + input[type=number]:not(.browser-default)[readonly="readonly"] + label, + input[type=search]:not(.browser-default):disabled + label, + input[type=search]:not(.browser-default)[readonly="readonly"] + label, + textarea.materialize-textarea:disabled + label, + textarea.materialize-textarea[readonly="readonly"] + label { + color: rgba(0, 0, 0, 0.42); } + input:not([type]):focus:not([readonly]), + input[type=text]:not(.browser-default):focus:not([readonly]), + input[type=password]:not(.browser-default):focus:not([readonly]), + input[type=email]:not(.browser-default):focus:not([readonly]), + input[type=url]:not(.browser-default):focus:not([readonly]), + input[type=time]:not(.browser-default):focus:not([readonly]), + input[type=date]:not(.browser-default):focus:not([readonly]), + input[type=datetime]:not(.browser-default):focus:not([readonly]), + input[type=datetime-local]:not(.browser-default):focus:not([readonly]), + input[type=tel]:not(.browser-default):focus:not([readonly]), + input[type=number]:not(.browser-default):focus:not([readonly]), + input[type=search]:not(.browser-default):focus:not([readonly]), + textarea.materialize-textarea:focus:not([readonly]) { + border-bottom: 1px solid #4D9999; + box-shadow: 0 1px 0 0 #4D9999; } + input:not([type]):focus:not([readonly]) + label, + input[type=text]:not(.browser-default):focus:not([readonly]) + label, + input[type=password]:not(.browser-default):focus:not([readonly]) + label, + input[type=email]:not(.browser-default):focus:not([readonly]) + label, + input[type=url]:not(.browser-default):focus:not([readonly]) + label, + input[type=time]:not(.browser-default):focus:not([readonly]) + label, + input[type=date]:not(.browser-default):focus:not([readonly]) + label, + input[type=datetime]:not(.browser-default):focus:not([readonly]) + label, + input[type=datetime-local]:not(.browser-default):focus:not([readonly]) + label, + input[type=tel]:not(.browser-default):focus:not([readonly]) + label, + input[type=number]:not(.browser-default):focus:not([readonly]) + label, + input[type=search]:not(.browser-default):focus:not([readonly]) + label, + textarea.materialize-textarea:focus:not([readonly]) + label { + color: #4D9999; } + input:not([type]):focus.valid ~ label, + input[type=text]:not(.browser-default):focus.valid ~ label, + input[type=password]:not(.browser-default):focus.valid ~ label, + input[type=email]:not(.browser-default):focus.valid ~ label, + input[type=url]:not(.browser-default):focus.valid ~ label, + input[type=time]:not(.browser-default):focus.valid ~ label, + input[type=date]:not(.browser-default):focus.valid ~ label, + input[type=datetime]:not(.browser-default):focus.valid ~ label, + input[type=datetime-local]:not(.browser-default):focus.valid ~ label, + input[type=tel]:not(.browser-default):focus.valid ~ label, + input[type=number]:not(.browser-default):focus.valid ~ label, + input[type=search]:not(.browser-default):focus.valid ~ label, + textarea.materialize-textarea:focus.valid ~ label { + color: #26A96C; } + input:not([type]):focus.invalid ~ label, + input[type=text]:not(.browser-default):focus.invalid ~ label, + input[type=password]:not(.browser-default):focus.invalid ~ label, + input[type=email]:not(.browser-default):focus.invalid ~ label, + input[type=url]:not(.browser-default):focus.invalid ~ label, + input[type=time]:not(.browser-default):focus.invalid ~ label, + input[type=date]:not(.browser-default):focus.invalid ~ label, + input[type=datetime]:not(.browser-default):focus.invalid ~ label, + input[type=datetime-local]:not(.browser-default):focus.invalid ~ label, + input[type=tel]:not(.browser-default):focus.invalid ~ label, + input[type=number]:not(.browser-default):focus.invalid ~ label, + input[type=search]:not(.browser-default):focus.invalid ~ label, + textarea.materialize-textarea:focus.invalid ~ label { + color: #F44336; } + input:not([type]).validate + label, + input[type=text]:not(.browser-default).validate + label, + input[type=password]:not(.browser-default).validate + label, + input[type=email]:not(.browser-default).validate + label, + input[type=url]:not(.browser-default).validate + label, + input[type=time]:not(.browser-default).validate + label, + input[type=date]:not(.browser-default).validate + label, + input[type=datetime]:not(.browser-default).validate + label, + input[type=datetime-local]:not(.browser-default).validate + label, + input[type=tel]:not(.browser-default).validate + label, + input[type=number]:not(.browser-default).validate + label, + input[type=search]:not(.browser-default).validate + label, + textarea.materialize-textarea.validate + label { + width: 100%; } + +/* Validation Sass Placeholders */ +input.valid:not([type]), input.valid:not([type]):focus, +input[type=text].valid:not(.browser-default), +input[type=text].valid:not(.browser-default):focus, +input[type=password].valid:not(.browser-default), +input[type=password].valid:not(.browser-default):focus, +input[type=email].valid:not(.browser-default), +input[type=email].valid:not(.browser-default):focus, +input[type=url].valid:not(.browser-default), +input[type=url].valid:not(.browser-default):focus, +input[type=time].valid:not(.browser-default), +input[type=time].valid:not(.browser-default):focus, +input[type=date].valid:not(.browser-default), +input[type=date].valid:not(.browser-default):focus, +input[type=datetime].valid:not(.browser-default), +input[type=datetime].valid:not(.browser-default):focus, +input[type=datetime-local].valid:not(.browser-default), +input[type=datetime-local].valid:not(.browser-default):focus, +input[type=tel].valid:not(.browser-default), +input[type=tel].valid:not(.browser-default):focus, +input[type=number].valid:not(.browser-default), +input[type=number].valid:not(.browser-default):focus, +input[type=search].valid:not(.browser-default), +input[type=search].valid:not(.browser-default):focus, +textarea.materialize-textarea.valid, +textarea.materialize-textarea.valid:focus, .select-wrapper.valid > input.select-dropdown { + border-bottom: 1px solid #26A96C; + box-shadow: 0 1px 0 0 #26A96C; } + +input.invalid:not([type]), input.invalid:not([type]):focus, +input[type=text].invalid:not(.browser-default), +input[type=text].invalid:not(.browser-default):focus, +input[type=password].invalid:not(.browser-default), +input[type=password].invalid:not(.browser-default):focus, +input[type=email].invalid:not(.browser-default), +input[type=email].invalid:not(.browser-default):focus, +input[type=url].invalid:not(.browser-default), +input[type=url].invalid:not(.browser-default):focus, +input[type=time].invalid:not(.browser-default), +input[type=time].invalid:not(.browser-default):focus, +input[type=date].invalid:not(.browser-default), +input[type=date].invalid:not(.browser-default):focus, +input[type=datetime].invalid:not(.browser-default), +input[type=datetime].invalid:not(.browser-default):focus, +input[type=datetime-local].invalid:not(.browser-default), +input[type=datetime-local].invalid:not(.browser-default):focus, +input[type=tel].invalid:not(.browser-default), +input[type=tel].invalid:not(.browser-default):focus, +input[type=number].invalid:not(.browser-default), +input[type=number].invalid:not(.browser-default):focus, +input[type=search].invalid:not(.browser-default), +input[type=search].invalid:not(.browser-default):focus, +textarea.materialize-textarea.invalid, +textarea.materialize-textarea.invalid:focus, .select-wrapper.invalid > input.select-dropdown, .select-wrapper.invalid > input.select-dropdown:focus { + border-bottom: 1px solid #F44336; + box-shadow: 0 1px 0 0 #F44336; } + +input:not([type]).valid ~ .helper-text[data-success], input:not([type]):focus.valid ~ .helper-text[data-success], input:not([type]).invalid ~ .helper-text[data-error], input:not([type]):focus.invalid ~ .helper-text[data-error], +input[type=text]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=text]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=text]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=text]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +input[type=password]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=password]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=password]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=password]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +input[type=email]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=email]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=email]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=email]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +input[type=url]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=url]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=url]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=url]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +input[type=time]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=time]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=time]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=time]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +input[type=date]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=date]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=date]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=date]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +input[type=datetime]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=datetime]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=datetime]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=datetime]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +input[type=datetime-local]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=datetime-local]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=datetime-local]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=datetime-local]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +input[type=tel]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=tel]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=tel]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=tel]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +input[type=number]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=number]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=number]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=number]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +input[type=search]:not(.browser-default).valid ~ .helper-text[data-success], +input[type=search]:not(.browser-default):focus.valid ~ .helper-text[data-success], +input[type=search]:not(.browser-default).invalid ~ .helper-text[data-error], +input[type=search]:not(.browser-default):focus.invalid ~ .helper-text[data-error], +textarea.materialize-textarea.valid ~ .helper-text[data-success], +textarea.materialize-textarea:focus.valid ~ .helper-text[data-success], +textarea.materialize-textarea.invalid ~ .helper-text[data-error], +textarea.materialize-textarea:focus.invalid ~ .helper-text[data-error], .select-wrapper.valid .helper-text[data-success], .select-wrapper.invalid ~ .helper-text[data-error] { + color: transparent; + user-select: none; + pointer-events: none; } + +input:not([type]).valid ~ .helper-text:after, input:not([type]):focus.valid ~ .helper-text:after, +input[type=text]:not(.browser-default).valid ~ .helper-text:after, +input[type=text]:not(.browser-default):focus.valid ~ .helper-text:after, +input[type=password]:not(.browser-default).valid ~ .helper-text:after, +input[type=password]:not(.browser-default):focus.valid ~ .helper-text:after, +input[type=email]:not(.browser-default).valid ~ .helper-text:after, +input[type=email]:not(.browser-default):focus.valid ~ .helper-text:after, +input[type=url]:not(.browser-default).valid ~ .helper-text:after, +input[type=url]:not(.browser-default):focus.valid ~ .helper-text:after, +input[type=time]:not(.browser-default).valid ~ .helper-text:after, +input[type=time]:not(.browser-default):focus.valid ~ .helper-text:after, +input[type=date]:not(.browser-default).valid ~ .helper-text:after, +input[type=date]:not(.browser-default):focus.valid ~ .helper-text:after, +input[type=datetime]:not(.browser-default).valid ~ .helper-text:after, +input[type=datetime]:not(.browser-default):focus.valid ~ .helper-text:after, +input[type=datetime-local]:not(.browser-default).valid ~ .helper-text:after, +input[type=datetime-local]:not(.browser-default):focus.valid ~ .helper-text:after, +input[type=tel]:not(.browser-default).valid ~ .helper-text:after, +input[type=tel]:not(.browser-default):focus.valid ~ .helper-text:after, +input[type=number]:not(.browser-default).valid ~ .helper-text:after, +input[type=number]:not(.browser-default):focus.valid ~ .helper-text:after, +input[type=search]:not(.browser-default).valid ~ .helper-text:after, +input[type=search]:not(.browser-default):focus.valid ~ .helper-text:after, +textarea.materialize-textarea.valid ~ .helper-text:after, +textarea.materialize-textarea:focus.valid ~ .helper-text:after, .select-wrapper.valid ~ .helper-text:after { + content: attr(data-success); + color: #26A96C; } + +input:not([type]).invalid ~ .helper-text:after, input:not([type]):focus.invalid ~ .helper-text:after, +input[type=text]:not(.browser-default).invalid ~ .helper-text:after, +input[type=text]:not(.browser-default):focus.invalid ~ .helper-text:after, +input[type=password]:not(.browser-default).invalid ~ .helper-text:after, +input[type=password]:not(.browser-default):focus.invalid ~ .helper-text:after, +input[type=email]:not(.browser-default).invalid ~ .helper-text:after, +input[type=email]:not(.browser-default):focus.invalid ~ .helper-text:after, +input[type=url]:not(.browser-default).invalid ~ .helper-text:after, +input[type=url]:not(.browser-default):focus.invalid ~ .helper-text:after, +input[type=time]:not(.browser-default).invalid ~ .helper-text:after, +input[type=time]:not(.browser-default):focus.invalid ~ .helper-text:after, +input[type=date]:not(.browser-default).invalid ~ .helper-text:after, +input[type=date]:not(.browser-default):focus.invalid ~ .helper-text:after, +input[type=datetime]:not(.browser-default).invalid ~ .helper-text:after, +input[type=datetime]:not(.browser-default):focus.invalid ~ .helper-text:after, +input[type=datetime-local]:not(.browser-default).invalid ~ .helper-text:after, +input[type=datetime-local]:not(.browser-default):focus.invalid ~ .helper-text:after, +input[type=tel]:not(.browser-default).invalid ~ .helper-text:after, +input[type=tel]:not(.browser-default):focus.invalid ~ .helper-text:after, +input[type=number]:not(.browser-default).invalid ~ .helper-text:after, +input[type=number]:not(.browser-default):focus.invalid ~ .helper-text:after, +input[type=search]:not(.browser-default).invalid ~ .helper-text:after, +input[type=search]:not(.browser-default):focus.invalid ~ .helper-text:after, +textarea.materialize-textarea.invalid ~ .helper-text:after, +textarea.materialize-textarea:focus.invalid ~ .helper-text:after, .select-wrapper.invalid ~ .helper-text:after { + content: attr(data-error); + color: #F44336; } + +input:not([type]) + label:after, +input[type=text]:not(.browser-default) + label:after, +input[type=password]:not(.browser-default) + label:after, +input[type=email]:not(.browser-default) + label:after, +input[type=url]:not(.browser-default) + label:after, +input[type=time]:not(.browser-default) + label:after, +input[type=date]:not(.browser-default) + label:after, +input[type=datetime]:not(.browser-default) + label:after, +input[type=datetime-local]:not(.browser-default) + label:after, +input[type=tel]:not(.browser-default) + label:after, +input[type=number]:not(.browser-default) + label:after, +input[type=search]:not(.browser-default) + label:after, +textarea.materialize-textarea + label:after, .select-wrapper + label:after { + display: block; + content: ""; + position: absolute; + top: 100%; + left: 0; + opacity: 0; + transition: .2s opacity ease-out, .2s color ease-out; } + +.input-field { + position: relative; + margin-top: 1rem; + margin-bottom: 1rem; } + .input-field.inline { + display: inline-block; + vertical-align: middle; + margin-left: 5px; } + .input-field.inline input, + .input-field.inline .select-dropdown { + margin-bottom: 1rem; } + .input-field.col label { + left: 0.75rem; } + .input-field.col .prefix ~ label, + .input-field.col .prefix ~ .validate ~ label { + width: calc(100% - 3rem - 1.5rem); } + .input-field > label { + color: #9e9e9e; + position: absolute; + top: 0; + left: 0; + font-size: 1rem; + cursor: text; + transition: transform .2s ease-out, color .2s ease-out; + transform-origin: 0% 100%; + text-align: initial; + transform: translateY(12px); } + .input-field > label:not(.label-icon).active { + transform: translateY(-14px) scale(0.8); + transform-origin: 0 0; } + .input-field > input[type]:-webkit-autofill:not(.browser-default):not([type="search"]) + label, .input-field > input[type=date]:not(.browser-default) + label, .input-field > input[type=time]:not(.browser-default) + label { + transform: translateY(-14px) scale(0.8); + transform-origin: 0 0; } + .input-field .helper-text { + position: relative; + min-height: 18px; + display: block; + font-size: 12px; + color: rgba(0, 0, 0, 0.54); } + .input-field .helper-text::after { + opacity: 1; + position: absolute; + top: 0; + left: 0; } + .input-field .prefix { + position: absolute; + width: 3rem; + font-size: 2rem; + transition: color .2s; + top: 0.5rem; } + .input-field .prefix.active { + color: #4D9999; } + .input-field .prefix ~ input, + .input-field .prefix ~ textarea, + .input-field .prefix ~ label, + .input-field .prefix ~ .validate ~ label, + .input-field .prefix ~ .helper-text, + .input-field .prefix ~ .autocomplete-content { + margin-left: 3rem; + width: 92%; + width: calc(100% - 3rem); } + .input-field .prefix ~ label { + margin-left: 3rem; } + @media only screen and (max-width: 992px) { + .input-field .prefix ~ input { + width: 86%; + width: calc(100% - 3rem); } } + @media only screen and (max-width: 600px) { + .input-field .prefix ~ input { + width: 80%; + width: calc(100% - 3rem); } } + +/* Search Field */ +.input-field input[type=search] { + display: block; + line-height: inherit; + transition: .3s background-color; } + .nav-wrapper .input-field input[type=search] { + height: inherit; + padding-left: 4rem; + width: calc(100% - 4rem); + border: 0; + box-shadow: none; } + .input-field input[type=search]:focus:not(.browser-default) { + background-color: #fff; + border: 0; + box-shadow: none; + color: #444; } + .input-field input[type=search]:focus:not(.browser-default) + label i, .input-field input[type=search]:focus:not(.browser-default) ~ .mdi-navigation-close, .input-field input[type=search]:focus:not(.browser-default) ~ .material-icons { + color: #444; } + .input-field input[type=search] + .label-icon { + transform: none; + left: 1rem; } + .input-field input[type=search] ~ .mdi-navigation-close, .input-field input[type=search] ~ .material-icons { + position: absolute; + top: 0; + right: 1rem; + color: transparent; + cursor: pointer; + font-size: 2rem; + transition: .3s color; } + +/* Textarea */ +textarea { + width: 100%; + height: 3rem; + background-color: transparent; } + textarea.materialize-textarea { + line-height: normal; + overflow-y: hidden; + /* prevents scroll bar flash */ + padding: .8rem 0 .8rem 0; + /* prevents text jump on Enter keypress */ + resize: none; + min-height: 3rem; + box-sizing: border-box; } + +.hiddendiv { + visibility: hidden; + white-space: pre-wrap; + word-wrap: break-word; + overflow-wrap: break-word; + /* future version of deprecated 'word-wrap' */ + padding-top: 1.2rem; + /* prevents text jump on Enter keypress */ + position: absolute; + top: 0; + z-index: -1; } + +/* Autocomplete */ +.autocomplete-content li .highlight { + color: #444; } +.autocomplete-content li img { + height: 40px; + width: 40px; + margin: 5px 15px; } + +/* Character Counter */ +.character-counter { + min-height: 18px; } + +/* Radio Buttons + ========================================================================== */ +[type="radio"]:not(:checked), +[type="radio"]:checked { + position: absolute; + opacity: 0; + pointer-events: none; } + +[type="radio"]:not(:checked) + span, +[type="radio"]:checked + span { + position: relative; + padding-left: 35px; + cursor: pointer; + display: inline-block; + height: 25px; + line-height: 25px; + font-size: 1rem; + transition: .28s ease; + user-select: none; } + +[type="radio"] + span:before, +[type="radio"] + span:after { + content: ''; + position: absolute; + left: 0; + top: 0; + margin: 4px; + width: 16px; + height: 16px; + z-index: 0; + transition: .28s ease; } + +/* Unchecked styles */ +[type="radio"]:not(:checked) + span:before, +[type="radio"]:not(:checked) + span:after, +[type="radio"]:checked + span:before, +[type="radio"]:checked + span:after, +[type="radio"].with-gap:checked + span:before, +[type="radio"].with-gap:checked + span:after { + border-radius: 50%; } + +[type="radio"]:not(:checked) + span:before, +[type="radio"]:not(:checked) + span:after { + border: 2px solid #5a5a5a; } + +[type="radio"]:not(:checked) + span:after { + transform: scale(0); } + +/* Checked styles */ +[type="radio"]:checked + span:before { + border: 2px solid transparent; } + +[type="radio"]:checked + span:after, +[type="radio"].with-gap:checked + span:before, +[type="radio"].with-gap:checked + span:after { + border: 2px solid #4D9999; } + +[type="radio"]:checked + span:after, +[type="radio"].with-gap:checked + span:after { + background-color: #4D9999; } + +[type="radio"]:checked + span:after { + transform: scale(1.02); } + +/* Radio With gap */ +[type="radio"].with-gap:checked + span:after { + transform: scale(0.5); } + +/* Focused styles */ +[type="radio"].tabbed:focus + span:before { + box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.1); } + +/* Disabled Radio With gap */ +[type="radio"].with-gap:disabled:checked + span:before { + border: 2px solid rgba(0, 0, 0, 0.42); } + +[type="radio"].with-gap:disabled:checked + span:after { + border: none; + background-color: rgba(0, 0, 0, 0.42); } + +/* Disabled style */ +[type="radio"]:disabled:not(:checked) + span:before, +[type="radio"]:disabled:checked + span:before { + background-color: transparent; + border-color: rgba(0, 0, 0, 0.42); } + +[type="radio"]:disabled + span { + color: rgba(0, 0, 0, 0.42); } + +[type="radio"]:disabled:not(:checked) + span:before { + border-color: rgba(0, 0, 0, 0.42); } + +[type="radio"]:disabled:checked + span:after { + background-color: rgba(0, 0, 0, 0.42); + border-color: #949494; } + +/* Checkboxes + ========================================================================== */ +/* Remove default checkbox */ +[type="checkbox"]:not(:checked), +[type="checkbox"]:checked { + position: absolute; + opacity: 0; + pointer-events: none; } + +[type="checkbox"] { + /* checkbox aspect */ } + [type="checkbox"] + span:not(.lever) { + position: relative; + padding-left: 35px; + cursor: pointer; + display: inline-block; + height: 25px; + line-height: 25px; + font-size: 1rem; + user-select: none; } + [type="checkbox"] + span:not(.lever):before, [type="checkbox"]:not(.filled-in) + span:not(.lever):after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 18px; + height: 18px; + z-index: 0; + border: 2px solid #5a5a5a; + border-radius: 1px; + margin-top: 3px; + transition: .2s; } + [type="checkbox"]:not(.filled-in) + span:not(.lever):after { + border: 0; + transform: scale(0); } + [type="checkbox"]:not(:checked):disabled + span:not(.lever):before { + border: none; + background-color: rgba(0, 0, 0, 0.42); } + [type="checkbox"].tabbed:focus + span:not(.lever):after { + transform: scale(1); + border: 0; + border-radius: 50%; + box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.1); + background-color: rgba(0, 0, 0, 0.1); } + +[type="checkbox"]:checked + span:not(.lever):before { + top: -4px; + left: -5px; + width: 12px; + height: 22px; + border-top: 2px solid transparent; + border-left: 2px solid transparent; + border-right: 2px solid #4D9999; + border-bottom: 2px solid #4D9999; + transform: rotate(40deg); + backface-visibility: hidden; + transform-origin: 100% 100%; } +[type="checkbox"]:checked:disabled + span:before { + border-right: 2px solid rgba(0, 0, 0, 0.42); + border-bottom: 2px solid rgba(0, 0, 0, 0.42); } + +/* Indeterminate checkbox */ +[type="checkbox"]:indeterminate + span:not(.lever):before { + top: -11px; + left: -12px; + width: 10px; + height: 22px; + border-top: none; + border-left: none; + border-right: 2px solid #4D9999; + border-bottom: none; + transform: rotate(90deg); + backface-visibility: hidden; + transform-origin: 100% 100%; } +[type="checkbox"]:indeterminate:disabled + span:not(.lever):before { + border-right: 2px solid rgba(0, 0, 0, 0.42); + background-color: transparent; } + +[type="checkbox"].filled-in + span:not(.lever):after { + border-radius: 2px; } +[type="checkbox"].filled-in + span:not(.lever):before, +[type="checkbox"].filled-in + span:not(.lever):after { + content: ''; + left: 0; + position: absolute; + /* .1s delay is for check animation */ + transition: border .25s, background-color .25s, width .20s .1s, height .20s .1s, top .20s .1s, left .20s .1s; + z-index: 1; } +[type="checkbox"].filled-in:not(:checked) + span:not(.lever):before { + width: 0; + height: 0; + border: 3px solid transparent; + left: 6px; + top: 10px; + transform: rotateZ(37deg); + transform-origin: 100% 100%; } +[type="checkbox"].filled-in:not(:checked) + span:not(.lever):after { + height: 20px; + width: 20px; + background-color: transparent; + border: 2px solid #5a5a5a; + top: 0px; + z-index: 0; } +[type="checkbox"].filled-in:checked + span:not(.lever):before { + top: 0; + left: 1px; + width: 8px; + height: 13px; + border-top: 2px solid transparent; + border-left: 2px solid transparent; + border-right: 2px solid #fff; + border-bottom: 2px solid #fff; + transform: rotateZ(37deg); + transform-origin: 100% 100%; } +[type="checkbox"].filled-in:checked + span:not(.lever):after { + top: 0; + width: 20px; + height: 20px; + border: 2px solid #4D9999; + background-color: #4D9999; + z-index: 0; } +[type="checkbox"].filled-in.tabbed:focus + span:not(.lever):after { + border-radius: 2px; + border-color: #5a5a5a; + background-color: rgba(0, 0, 0, 0.1); } +[type="checkbox"].filled-in.tabbed:checked:focus + span:not(.lever):after { + border-radius: 2px; + background-color: #4D9999; + border-color: #4D9999; } +[type="checkbox"].filled-in:disabled:not(:checked) + span:not(.lever):before { + background-color: transparent; + border: 2px solid transparent; } +[type="checkbox"].filled-in:disabled:not(:checked) + span:not(.lever):after { + border-color: transparent; + background-color: #949494; } +[type="checkbox"].filled-in:disabled:checked + span:not(.lever):before { + background-color: transparent; } +[type="checkbox"].filled-in:disabled:checked + span:not(.lever):after { + background-color: #949494; + border-color: #949494; } + +/* Switch + ========================================================================== */ +.switch, +.switch * { + -webkit-tap-highlight-color: transparent; + user-select: none; } + +.switch label { + cursor: pointer; } + +.switch label input[type=checkbox] { + opacity: 0; + width: 0; + height: 0; } + .switch label input[type=checkbox]:checked + .lever { + background-color: #adb9b9; } + .switch label input[type=checkbox]:checked + .lever:before, .switch label input[type=checkbox]:checked + .lever:after { + left: 18px; } + .switch label input[type=checkbox]:checked + .lever:after { + background-color: #4D9999; } + +.switch label .lever { + content: ""; + display: inline-block; + position: relative; + width: 36px; + height: 14px; + background-color: rgba(0, 0, 0, 0.38); + border-radius: 15px; + margin-right: 10px; + transition: background 0.3s ease; + vertical-align: middle; + margin: 0 16px; } + .switch label .lever:before, .switch label .lever:after { + content: ""; + position: absolute; + display: inline-block; + width: 20px; + height: 20px; + border-radius: 50%; + left: 0; + top: -3px; + transition: left 0.3s ease, background .3s ease, box-shadow 0.1s ease, transform .1s ease; } + .switch label .lever:before { + background-color: rgba(77, 153, 153, 0.15); } + .switch label .lever:after { + background-color: #F1F1F1; + box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12); } + +input[type=checkbox]:checked:not(:disabled) ~ .lever:active::before, +input[type=checkbox]:checked:not(:disabled).tabbed:focus ~ .lever::before { + transform: scale(2.4); + background-color: rgba(77, 153, 153, 0.15); } + +input[type=checkbox]:not(:disabled) ~ .lever:active:before, +input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::before { + transform: scale(2.4); + background-color: rgba(0, 0, 0, 0.08); } + +.switch input[type=checkbox][disabled] + .lever { + cursor: default; + background-color: rgba(0, 0, 0, 0.12); } + +.switch label input[type=checkbox][disabled] + .lever:after, +.switch label input[type=checkbox][disabled]:checked + .lever:after { + background-color: #949494; } + +/* Select Field + ========================================================================== */ +select { + display: none; } + +select.browser-default { + display: block; } + +select { + background-color: rgba(255, 255, 255, 0.9); + width: 100%; + padding: 5px; + border: 1px solid #f2f2f2; + border-radius: 2px; + height: 3rem; } + +.select-label { + position: absolute; } + +.select-wrapper { + position: relative; } + .select-wrapper.valid + label, .select-wrapper.invalid + label { + width: 100%; + pointer-events: none; } + .select-wrapper input.select-dropdown { + position: relative; + cursor: pointer; + background-color: transparent; + border: none; + border-bottom: 1px solid #9e9e9e; + outline: none; + height: 3rem; + line-height: 3rem; + width: 100%; + font-size: 16px; + margin: 0 0 8px 0; + padding: 0; + display: block; + user-select: none; + z-index: 1; } + .select-wrapper input.select-dropdown:focus { + border-bottom: 1px solid #4D9999; } + .select-wrapper .caret { + position: absolute; + right: 0; + top: 0; + bottom: 0; + margin: auto 0; + z-index: 0; + fill: rgba(0, 0, 0, 0.87); } + .select-wrapper + label { + position: absolute; + top: -26px; + font-size: 0.8rem; } + +select:disabled { + color: rgba(0, 0, 0, 0.42); } + +.select-wrapper.disabled + label { + color: rgba(0, 0, 0, 0.42); } +.select-wrapper.disabled .caret { + fill: rgba(0, 0, 0, 0.42); } + +.select-wrapper input.select-dropdown:disabled { + color: rgba(0, 0, 0, 0.42); + cursor: default; + user-select: none; } + +.select-wrapper i { + color: rgba(0, 0, 0, 0.3); } + +.select-dropdown li.disabled, +.select-dropdown li.disabled > span, +.select-dropdown li.optgroup { + color: rgba(0, 0, 0, 0.3); + background-color: transparent; } + +body.keyboard-focused .select-dropdown.dropdown-content li:focus { + background-color: rgba(0, 0, 0, 0.08); } + +.select-dropdown.dropdown-content li:hover { + background-color: rgba(0, 0, 0, 0.08); } +.select-dropdown.dropdown-content li.selected { + background-color: rgba(0, 0, 0, 0.03); } + +.prefix ~ .select-wrapper { + margin-left: 3rem; + width: 92%; + width: calc(100% - 3rem); } + +.prefix ~ label { + margin-left: 3rem; } + +.select-dropdown li img { + height: 40px; + width: 40px; + margin: 5px 15px; + float: right; } + +.select-dropdown li.optgroup { + border-top: 1px solid #eee; } + .select-dropdown li.optgroup.selected > span { + color: rgba(0, 0, 0, 0.7); } + .select-dropdown li.optgroup > span { + color: rgba(0, 0, 0, 0.4); } + .select-dropdown li.optgroup ~ li.optgroup-option { + padding-left: 1rem; } + +/* File Input + ========================================================================== */ +.file-field { + position: relative; } + .file-field .file-path-wrapper { + overflow: hidden; + padding-left: 10px; } + .file-field input.file-path { + width: 100%; } + .file-field .btn, .file-field .btn-large, .file-field .btn-small { + float: left; + height: 3rem; + line-height: 3rem; } + .file-field span { + cursor: pointer; } + .file-field input[type=file] { + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + width: 100%; + margin: 0; + padding: 0; + font-size: 20px; + cursor: pointer; + opacity: 0; + filter: alpha(opacity=0); } + .file-field input[type=file]::-webkit-file-upload-button { + display: none; } + +/* Range + ========================================================================== */ +.range-field { + position: relative; } + +input[type=range], +input[type=range] + .thumb { + cursor: pointer; } + +input[type=range] { + position: relative; + background-color: transparent; + border: none; + outline: none; + width: 100%; + margin: 15px 0; + padding: 0; } + input[type=range]:focus { + outline: none; } + +input[type=range] + .thumb { + position: absolute; + top: 10px; + left: 0; + border: none; + height: 0; + width: 0; + border-radius: 50%; + background-color: #4D9999; + margin-left: 7px; + transform-origin: 50% 50%; + transform: rotate(-45deg); } + input[type=range] + .thumb .value { + display: block; + width: 30px; + text-align: center; + color: #4D9999; + font-size: 0; + transform: rotate(45deg); } + input[type=range] + .thumb.active { + border-radius: 50% 50% 50% 0; } + input[type=range] + .thumb.active .value { + color: #fff; + margin-left: -1px; + margin-top: 8px; + font-size: 10px; } + +input[type=range] { + -webkit-appearance: none; } + +input[type=range]::-webkit-slider-runnable-track { + height: 3px; + background: #c2c0c2; + border: none; } + +input[type=range]::-webkit-slider-thumb { + border: none; + height: 14px; + width: 14px; + border-radius: 50%; + background: #4D9999; + transition: box-shadow .3s; + -webkit-appearance: none; + background-color: #4D9999; + transform-origin: 50% 50%; + margin: -5px 0 0 0; } + +.keyboard-focused input[type=range]:focus:not(.active)::-webkit-slider-thumb { + box-shadow: 0 0 0 10px rgba(77, 153, 153, 0.26); } + +input[type=range] { + /* fix for FF unable to apply focus style bug */ + border: 1px solid white; + /*required for proper track sizing in FF*/ } + +input[type=range]::-moz-range-track { + height: 3px; + background: #c2c0c2; + border: none; } + +input[type=range]::-moz-focus-inner { + border: 0; } + +input[type=range]::-moz-range-thumb { + border: none; + height: 14px; + width: 14px; + border-radius: 50%; + background: #4D9999; + transition: box-shadow .3s; + margin-top: -5px; } + +input[type=range]:-moz-focusring { + outline: 1px solid #fff; + outline-offset: -1px; } + +.keyboard-focused input[type=range]:focus:not(.active)::-moz-range-thumb { + box-shadow: 0 0 0 10px rgba(77, 153, 153, 0.26); } + +input[type=range]::-ms-track { + height: 3px; + background: transparent; + border-color: transparent; + border-width: 6px 0; + /*remove default tick marks*/ + color: transparent; } + +input[type=range]::-ms-fill-lower { + background: #777; } + +input[type=range]::-ms-fill-upper { + background: #ddd; } + +input[type=range]::-ms-thumb { + border: none; + height: 14px; + width: 14px; + border-radius: 50%; + background: #4D9999; + transition: box-shadow .3s; } + +.keyboard-focused input[type=range]:focus:not(.active)::-ms-thumb { + box-shadow: 0 0 0 10px rgba(77, 153, 153, 0.26); } + +/*************** + Nav List +***************/ +.table-of-contents.fixed { + position: fixed; } +.table-of-contents li { + padding: 2px 0; } +.table-of-contents a { + display: inline-block; + font-weight: 300; + color: #757575; + padding-left: 16px; + height: 1.5rem; + line-height: 1.5rem; + letter-spacing: .4; + display: inline-block; } + .table-of-contents a:hover { + color: #a8a8a8; + padding-left: 15px; + border-left: 1px solid #B84000; } + .table-of-contents a.active { + font-weight: 500; + padding-left: 14px; + border-left: 2px solid #B84000; } + +.sidenav { + position: fixed; + width: 300px; + left: 0; + top: 0; + margin: 0; + transform: translateX(-100%); + height: 100%; + height: calc(100% + 60px); + height: -moz-calc(100%); + padding-bottom: 60px; + background-color: #fff; + z-index: 999; + overflow-y: auto; + will-change: transform; + backface-visibility: hidden; + transform: translateX(-105%); } + .sidenav.right-aligned { + right: 0; + transform: translateX(105%); + left: auto; + transform: translateX(100%); } + .sidenav .collapsible { + margin: 0; } + .sidenav li { + float: none; + line-height: 48px; } + .sidenav li.active { + background-color: rgba(0, 0, 0, 0.05); } + .sidenav li > a { + color: rgba(0, 0, 0, 0.87); + display: block; + font-size: 14px; + font-weight: 500; + height: 48px; + line-height: 48px; + padding: 0 32px; } + .sidenav li > a:hover { + background-color: rgba(0, 0, 0, 0.05); } + .sidenav li > a.btn, .sidenav li > a.btn-large, .sidenav li > a.btn-small, .sidenav li > a.btn-large, .sidenav li > a.btn-flat, .sidenav li > a.btn-floating { + margin: 10px 15px; } + .sidenav li > a.btn, .sidenav li > a.btn-large, .sidenav li > a.btn-small, .sidenav li > a.btn-large, .sidenav li > a.btn-floating { + color: #fff; } + .sidenav li > a.btn-flat { + color: #343434; } + .sidenav li > a.btn:hover, .sidenav li > a.btn-large:hover, .sidenav li > a.btn-small:hover, .sidenav li > a.btn-large:hover { + background-color: #56aaaa; } + .sidenav li > a.btn-floating:hover { + background-color: #4D9999; } + .sidenav li > a > i, .sidenav li > a > [class^="mdi-"], .sidenav li > a li > a > [class*="mdi-"], .sidenav li > a > i.material-icons { + float: left; + height: 48px; + line-height: 48px; + margin: 0 32px 0 0; + width: 24px; + color: rgba(0, 0, 0, 0.54); } + .sidenav .divider { + margin: 8px 0 0 0; } + .sidenav .subheader { + cursor: initial; + pointer-events: none; + color: rgba(0, 0, 0, 0.54); + font-size: 14px; + font-weight: 500; + line-height: 48px; } + .sidenav .subheader:hover { + background-color: transparent; } + .sidenav .user-view { + position: relative; + padding: 32px 32px 0; + margin-bottom: 8px; } + .sidenav .user-view > a { + height: auto; + padding: 0; } + .sidenav .user-view > a:hover { + background-color: transparent; } + .sidenav .user-view .background { + overflow: hidden; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: -1; } + .sidenav .user-view .circle, .sidenav .user-view .name, .sidenav .user-view .email { + display: block; } + .sidenav .user-view .circle { + height: 64px; + width: 64px; } + .sidenav .user-view .name, + .sidenav .user-view .email { + font-size: 14px; + line-height: 24px; } + .sidenav .user-view .name { + margin-top: 16px; + font-weight: 500; } + .sidenav .user-view .email { + padding-bottom: 16px; + font-weight: 400; } + +.drag-target { + height: 100%; + width: 10px; + position: fixed; + top: 0; + z-index: 998; } + .drag-target.right-aligned { + right: 0; } + +.sidenav.sidenav-fixed { + left: 0; + transform: translateX(0); + position: fixed; } + .sidenav.sidenav-fixed.right-aligned { + right: 0; + left: auto; } + +@media only screen and (max-width: 992px) { + .sidenav.sidenav-fixed { + transform: translateX(-105%); } + .sidenav.sidenav-fixed.right-aligned { + transform: translateX(105%); } + .sidenav > a { + padding: 0 16px; } + .sidenav .user-view { + padding: 16px 16px 0; } } +.sidenav .collapsible-body > ul:not(.collapsible) > li.active, +.sidenav.sidenav-fixed .collapsible-body > ul:not(.collapsible) > li.active { + background-color: #B84000; } + .sidenav .collapsible-body > ul:not(.collapsible) > li.active a, + .sidenav.sidenav-fixed .collapsible-body > ul:not(.collapsible) > li.active a { + color: #fff; } + +.sidenav .collapsible-body { + padding: 0; } + +.sidenav-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + opacity: 0; + height: 120vh; + background-color: rgba(0, 0, 0, 0.5); + z-index: 997; + display: none; } + +/* + @license + Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt + */ +/**************************/ +/* STYLES FOR THE SPINNER */ +/**************************/ +/* + * Constants: + * STROKEWIDTH = 3px + * ARCSIZE = 270 degrees (amount of circle the arc takes up) + * ARCTIME = 1333ms (time it takes to expand and contract arc) + * ARCSTARTROT = 216 degrees (how much the start location of the arc + * should rotate each time, 216 gives us a + * 5 pointed star shape (it's 360/5 * 3). + * For a 7 pointed star, we might do + * 360/7 * 3 = 154.286) + * CONTAINERWIDTH = 28px + * SHRINK_TIME = 400ms + */ +.preloader-wrapper { + display: inline-block; + position: relative; + width: 50px; + height: 50px; } + .preloader-wrapper.small { + width: 36px; + height: 36px; } + .preloader-wrapper.big { + width: 64px; + height: 64px; } + .preloader-wrapper.active { + /* duration: 360 * ARCTIME / (ARCSTARTROT + (360-ARCSIZE)) */ + -webkit-animation: container-rotate 1568ms linear infinite; + animation: container-rotate 1568ms linear infinite; } + +@-webkit-keyframes container-rotate { + to { + -webkit-transform: rotate(360deg); } } +@keyframes container-rotate { + to { + transform: rotate(360deg); } } +.spinner-layer { + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + border-color: #4D9999; } + +.spinner-blue, +.spinner-blue-only { + border-color: #4285f4; } + +.spinner-red, +.spinner-red-only { + border-color: #db4437; } + +.spinner-yellow, +.spinner-yellow-only { + border-color: #f4b400; } + +.spinner-green, +.spinner-green-only { + border-color: #0f9d58; } + +/** + * IMPORTANT NOTE ABOUT CSS ANIMATION PROPERTIES (keanulee): + * + * iOS Safari (tested on iOS 8.1) does not handle animation-delay very well - it doesn't + * guarantee that the animation will start _exactly_ after that value. So we avoid using + * animation-delay and instead set custom keyframes for each color (as redundant as it + * seems). + * + * We write out each animation in full (instead of separating animation-name, + * animation-duration, etc.) because under the polyfill, Safari does not recognize those + * specific properties properly, treats them as -webkit-animation, and overrides the + * other animation rules. See https://github.com/Polymer/platform/issues/53. + */ +.active .spinner-layer.spinner-blue { + /* durations: 4 * ARCTIME */ + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, blue-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, blue-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +.active .spinner-layer.spinner-red { + /* durations: 4 * ARCTIME */ + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, red-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, red-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +.active .spinner-layer.spinner-yellow { + /* durations: 4 * ARCTIME */ + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, yellow-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, yellow-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +.active .spinner-layer.spinner-green { + /* durations: 4 * ARCTIME */ + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, green-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, green-fade-in-out 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +.active .spinner-layer, +.active .spinner-layer.spinner-blue-only, +.active .spinner-layer.spinner-red-only, +.active .spinner-layer.spinner-yellow-only, +.active .spinner-layer.spinner-green-only { + /* durations: 4 * ARCTIME */ + opacity: 1; + -webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +@-webkit-keyframes fill-unfill-rotate { + 12.5% { + -webkit-transform: rotate(135deg); } + /* 0.5 * ARCSIZE */ + 25% { + -webkit-transform: rotate(270deg); } + /* 1 * ARCSIZE */ + 37.5% { + -webkit-transform: rotate(405deg); } + /* 1.5 * ARCSIZE */ + 50% { + -webkit-transform: rotate(540deg); } + /* 2 * ARCSIZE */ + 62.5% { + -webkit-transform: rotate(675deg); } + /* 2.5 * ARCSIZE */ + 75% { + -webkit-transform: rotate(810deg); } + /* 3 * ARCSIZE */ + 87.5% { + -webkit-transform: rotate(945deg); } + /* 3.5 * ARCSIZE */ + to { + -webkit-transform: rotate(1080deg); } + /* 4 * ARCSIZE */ } +@keyframes fill-unfill-rotate { + 12.5% { + transform: rotate(135deg); } + /* 0.5 * ARCSIZE */ + 25% { + transform: rotate(270deg); } + /* 1 * ARCSIZE */ + 37.5% { + transform: rotate(405deg); } + /* 1.5 * ARCSIZE */ + 50% { + transform: rotate(540deg); } + /* 2 * ARCSIZE */ + 62.5% { + transform: rotate(675deg); } + /* 2.5 * ARCSIZE */ + 75% { + transform: rotate(810deg); } + /* 3 * ARCSIZE */ + 87.5% { + transform: rotate(945deg); } + /* 3.5 * ARCSIZE */ + to { + transform: rotate(1080deg); } + /* 4 * ARCSIZE */ } +@-webkit-keyframes blue-fade-in-out { + from { + opacity: 1; } + 25% { + opacity: 1; } + 26% { + opacity: 0; } + 89% { + opacity: 0; } + 90% { + opacity: 1; } + 100% { + opacity: 1; } } +@keyframes blue-fade-in-out { + from { + opacity: 1; } + 25% { + opacity: 1; } + 26% { + opacity: 0; } + 89% { + opacity: 0; } + 90% { + opacity: 1; } + 100% { + opacity: 1; } } +@-webkit-keyframes red-fade-in-out { + from { + opacity: 0; } + 15% { + opacity: 0; } + 25% { + opacity: 1; } + 50% { + opacity: 1; } + 51% { + opacity: 0; } } +@keyframes red-fade-in-out { + from { + opacity: 0; } + 15% { + opacity: 0; } + 25% { + opacity: 1; } + 50% { + opacity: 1; } + 51% { + opacity: 0; } } +@-webkit-keyframes yellow-fade-in-out { + from { + opacity: 0; } + 40% { + opacity: 0; } + 50% { + opacity: 1; } + 75% { + opacity: 1; } + 76% { + opacity: 0; } } +@keyframes yellow-fade-in-out { + from { + opacity: 0; } + 40% { + opacity: 0; } + 50% { + opacity: 1; } + 75% { + opacity: 1; } + 76% { + opacity: 0; } } +@-webkit-keyframes green-fade-in-out { + from { + opacity: 0; } + 65% { + opacity: 0; } + 75% { + opacity: 1; } + 90% { + opacity: 1; } + 100% { + opacity: 0; } } +@keyframes green-fade-in-out { + from { + opacity: 0; } + 65% { + opacity: 0; } + 75% { + opacity: 1; } + 90% { + opacity: 1; } + 100% { + opacity: 0; } } +/** + * Patch the gap that appear between the two adjacent div.circle-clipper while the + * spinner is rotating (appears on Chrome 38, Safari 7.1, and IE 11). + */ +.gap-patch { + position: absolute; + top: 0; + left: 45%; + width: 10%; + height: 100%; + overflow: hidden; + border-color: inherit; } + +.gap-patch .circle { + width: 1000%; + left: -450%; } + +.circle-clipper { + display: inline-block; + position: relative; + width: 50%; + height: 100%; + overflow: hidden; + border-color: inherit; } + .circle-clipper .circle { + width: 200%; + height: 100%; + border-width: 3px; + /* STROKEWIDTH */ + border-style: solid; + border-color: inherit; + border-bottom-color: transparent !important; + border-radius: 50%; + -webkit-animation: none; + animation: none; + position: absolute; + top: 0; + right: 0; + bottom: 0; } + .circle-clipper.left .circle { + left: 0; + border-right-color: transparent !important; + -webkit-transform: rotate(129deg); + transform: rotate(129deg); } + .circle-clipper.right .circle { + left: -100%; + border-left-color: transparent !important; + -webkit-transform: rotate(-129deg); + transform: rotate(-129deg); } + +.active .circle-clipper.left .circle { + /* duration: ARCTIME */ + -webkit-animation: left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + animation: left-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +.active .circle-clipper.right .circle { + /* duration: ARCTIME */ + -webkit-animation: right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; + animation: right-spin 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both; } + +@-webkit-keyframes left-spin { + from { + -webkit-transform: rotate(130deg); } + 50% { + -webkit-transform: rotate(-5deg); } + to { + -webkit-transform: rotate(130deg); } } +@keyframes left-spin { + from { + transform: rotate(130deg); } + 50% { + transform: rotate(-5deg); } + to { + transform: rotate(130deg); } } +@-webkit-keyframes right-spin { + from { + -webkit-transform: rotate(-130deg); } + 50% { + -webkit-transform: rotate(5deg); } + to { + -webkit-transform: rotate(-130deg); } } +@keyframes right-spin { + from { + transform: rotate(-130deg); } + 50% { + transform: rotate(5deg); } + to { + transform: rotate(-130deg); } } +#spinnerContainer.cooldown { + /* duration: SHRINK_TIME */ + -webkit-animation: container-rotate 1568ms linear infinite, fade-out 400ms cubic-bezier(0.4, 0, 0.2, 1); + animation: container-rotate 1568ms linear infinite, fade-out 400ms cubic-bezier(0.4, 0, 0.2, 1); } + +@-webkit-keyframes fade-out { + from { + opacity: 1; } + to { + opacity: 0; } } +@keyframes fade-out { + from { + opacity: 1; } + to { + opacity: 0; } } +.slider { + position: relative; + height: 400px; + width: 100%; } + .slider.fullscreen { + height: 100%; + width: 100%; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; } + .slider.fullscreen ul.slides { + height: 100%; } + .slider.fullscreen ul.indicators { + z-index: 2; + bottom: 30px; } + .slider .slides { + background-color: #9e9e9e; + margin: 0; + height: 400px; } + .slider .slides li { + opacity: 0; + position: absolute; + top: 0; + left: 0; + z-index: 1; + width: 100%; + height: inherit; + overflow: hidden; } + .slider .slides li img { + height: 100%; + width: 100%; + background-size: cover; + background-position: center; } + .slider .slides li .caption { + color: #fff; + position: absolute; + top: 15%; + left: 15%; + width: 70%; + opacity: 0; } + .slider .slides li .caption p { + color: #e0e0e0; } + .slider .slides li.active { + z-index: 2; } + .slider .indicators { + position: absolute; + text-align: center; + left: 0; + right: 0; + bottom: 0; + margin: 0; } + .slider .indicators .indicator-item { + display: inline-block; + position: relative; + cursor: pointer; + height: 16px; + width: 16px; + margin: 0 12px; + background-color: #e0e0e0; + transition: background-color .3s; + border-radius: 50%; } + .slider .indicators .indicator-item.active { + background-color: #4CAF50; } + +.carousel { + overflow: hidden; + position: relative; + width: 100%; + height: 400px; + perspective: 500px; + transform-style: preserve-3d; + transform-origin: 0% 50%; } + .carousel.carousel-slider { + top: 0; + left: 0; } + .carousel.carousel-slider .carousel-fixed-item { + position: absolute; + left: 0; + right: 0; + bottom: 20px; + z-index: 1; } + .carousel.carousel-slider .carousel-fixed-item.with-indicators { + bottom: 68px; } + .carousel.carousel-slider .carousel-item { + width: 100%; + height: 100%; + min-height: 400px; + position: absolute; + top: 0; + left: 0; } + .carousel.carousel-slider .carousel-item h2 { + font-size: 24px; + font-weight: 500; + line-height: 32px; } + .carousel.carousel-slider .carousel-item p { + font-size: 15px; } + .carousel .carousel-item { + visibility: hidden; + width: 200px; + height: 200px; + position: absolute; + top: 0; + left: 0; } + .carousel .carousel-item > img { + width: 100%; } + .carousel .indicators { + position: absolute; + text-align: center; + left: 0; + right: 0; + bottom: 0; + margin: 0; } + .carousel .indicators .indicator-item { + display: inline-block; + position: relative; + cursor: pointer; + height: 8px; + width: 8px; + margin: 24px 4px; + background-color: rgba(255, 255, 255, 0.5); + transition: background-color .3s; + border-radius: 50%; } + .carousel .indicators .indicator-item.active { + background-color: #fff; } + .carousel.scrolling .carousel-item .materialboxed, + .carousel .carousel-item:not(.active) .materialboxed { + pointer-events: none; } + +.tap-target-wrapper { + width: 800px; + height: 800px; + position: fixed; + z-index: 1000; + visibility: hidden; + transition: visibility 0s .3s; } + +.tap-target-wrapper.open { + visibility: visible; + transition: visibility 0s; } + .tap-target-wrapper.open .tap-target { + transform: scale(1); + opacity: .95; + transition: transform 0.3s cubic-bezier(0.42, 0, 0.58, 1), opacity 0.3s cubic-bezier(0.42, 0, 0.58, 1); } + .tap-target-wrapper.open .tap-target-wave::before { + transform: scale(1); } + .tap-target-wrapper.open .tap-target-wave::after { + visibility: visible; + animation: pulse-animation 1s cubic-bezier(0.24, 0, 0.38, 1) infinite; + transition: opacity .3s, transform .3s, visibility 0s 1s; } + +.tap-target { + position: absolute; + font-size: 1rem; + border-radius: 50%; + background-color: #B84000; + box-shadow: 0 20px 20px 0 rgba(0, 0, 0, 0.14), 0 10px 50px 0 rgba(0, 0, 0, 0.12), 0 30px 10px -20px rgba(0, 0, 0, 0.2); + width: 100%; + height: 100%; + opacity: 0; + transform: scale(0); + transition: transform 0.3s cubic-bezier(0.42, 0, 0.58, 1), opacity 0.3s cubic-bezier(0.42, 0, 0.58, 1); } + +.tap-target-content { + position: relative; + display: table-cell; } + +.tap-target-wave { + position: absolute; + border-radius: 50%; + z-index: 10001; } + .tap-target-wave::before, .tap-target-wave::after { + content: ''; + display: block; + position: absolute; + width: 100%; + height: 100%; + border-radius: 50%; + background-color: #ffffff; } + .tap-target-wave::before { + transform: scale(0); + transition: transform .3s; } + .tap-target-wave::after { + visibility: hidden; + transition: opacity .3s, transform .3s, visibility 0s; + z-index: -1; } + +.tap-target-origin { + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 10002; + position: absolute !important; } + .tap-target-origin:not(.btn):not(.btn-large):not(.btn-small), .tap-target-origin:not(.btn):not(.btn-large):not(.btn-small):hover { + background: none; } + +@media only screen and (max-width: 600px) { + .tap-target, .tap-target-wrapper { + width: 600px; + height: 600px; } } +.pulse { + overflow: visible; + position: relative; } + .pulse::before { + content: ''; + display: block; + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + background-color: inherit; + border-radius: inherit; + transition: opacity .3s, transform .3s; + animation: pulse-animation 1s cubic-bezier(0.24, 0, 0.38, 1) infinite; + z-index: -1; } + +@keyframes pulse-animation { + 0% { + opacity: 1; + transform: scale(1); } + 50% { + opacity: 0; + transform: scale(1.5); } + 100% { + opacity: 0; + transform: scale(1.5); } } +/* Modal */ +.datepicker-modal { + max-width: 325px; + min-width: 300px; + max-height: none; } + +.datepicker-container.modal-content { + display: flex; + flex-direction: column; + padding: 0; } + +.datepicker-controls { + display: flex; + justify-content: space-between; + width: 280px; + margin: 0 auto; } + .datepicker-controls .selects-container { + display: flex; } + .datepicker-controls .select-wrapper input { + border-bottom: none; + text-align: center; + margin: 0; } + .datepicker-controls .select-wrapper input:focus { + border-bottom: none; } + .datepicker-controls .select-wrapper .caret { + display: none; } + .datepicker-controls .select-year input { + width: 50px; } + .datepicker-controls .select-month input { + width: 70px; } + +.month-prev, .month-next { + margin-top: 4px; + cursor: pointer; + background-color: transparent; + border: none; } + +/* Date Display */ +.datepicker-date-display { + flex: 1 auto; + background-color: #4D9999; + color: #fff; + padding: 20px 22px; + font-weight: 500; } + .datepicker-date-display .year-text { + display: block; + font-size: 1.5rem; + line-height: 25px; + color: rgba(255, 255, 255, 0.7); } + .datepicker-date-display .date-text { + display: block; + font-size: 2.8rem; + line-height: 47px; + font-weight: 500; } + +/* Calendar */ +.datepicker-calendar-container { + flex: 2.5 auto; } + +.datepicker-table { + width: 280px; + font-size: 1rem; + margin: 0 auto; } + .datepicker-table thead { + border-bottom: none; } + .datepicker-table th { + padding: 10px 5px; + text-align: center; } + .datepicker-table tr { + border: none; } + .datepicker-table abbr { + text-decoration: none; + color: #999; } + .datepicker-table td { + border-radius: 50%; + padding: 0; } + .datepicker-table td.is-today { + color: #4D9999; } + .datepicker-table td.is-selected { + background-color: #4D9999; + color: #fff; } + .datepicker-table td.is-outside-current-month, .datepicker-table td.is-disabled { + color: rgba(0, 0, 0, 0.3); + pointer-events: none; } + +.datepicker-day-button { + background-color: transparent; + border: none; + line-height: 38px; + display: block; + width: 100%; + border-radius: 50%; + padding: 0 5px; + cursor: pointer; + color: inherit; } + .datepicker-day-button:focus { + background-color: rgba(83, 147, 147, 0.25); } + +/* Footer */ +.datepicker-footer { + width: 280px; + margin: 0 auto; + padding-bottom: 5px; + display: flex; + justify-content: space-between; } + +.datepicker-cancel, +.datepicker-clear, +.datepicker-today, +.datepicker-done { + color: #4D9999; + padding: 0 1rem; } + +.datepicker-clear { + color: #F44336; } + +/* Media Queries */ +@media only screen and (min-width: 601px) { + .datepicker-modal { + max-width: 625px; } + + .datepicker-container.modal-content { + flex-direction: row; } + + .datepicker-date-display { + flex: 0 1 270px; } + + .datepicker-controls, + .datepicker-table, + .datepicker-footer { + width: 320px; } + + .datepicker-day-button { + line-height: 44px; } } +/* Timepicker Containers */ +.timepicker-modal { + max-width: 325px; + max-height: none; } + +.timepicker-container.modal-content { + display: flex; + flex-direction: column; + padding: 0; } + +.text-primary { + color: white; } + +/* Clock Digital Display */ +.timepicker-digital-display { + flex: 1 auto; + background-color: #4D9999; + padding: 10px; + font-weight: 300; } + +.timepicker-text-container { + font-size: 4rem; + font-weight: bold; + text-align: center; + color: rgba(255, 255, 255, 0.6); + font-weight: 400; + position: relative; + user-select: none; } + +.timepicker-span-hours, +.timepicker-span-minutes, +.timepicker-span-am-pm div { + cursor: pointer; } + +.timepicker-span-hours { + margin-right: 3px; } + +.timepicker-span-minutes { + margin-left: 3px; } + +.timepicker-display-am-pm { + font-size: 1.3rem; + position: absolute; + right: 1rem; + bottom: 1rem; + font-weight: 400; } + +/* Analog Clock Display */ +.timepicker-analog-display { + flex: 2.5 auto; } + +.timepicker-plate { + background-color: #eee; + border-radius: 50%; + width: 270px; + height: 270px; + overflow: visible; + position: relative; + margin: auto; + margin-top: 25px; + margin-bottom: 5px; + user-select: none; } + +.timepicker-canvas, +.timepicker-dial { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; } + +.timepicker-minutes { + visibility: hidden; } + +.timepicker-tick { + border-radius: 50%; + color: rgba(0, 0, 0, 0.87); + line-height: 40px; + text-align: center; + width: 40px; + height: 40px; + position: absolute; + cursor: pointer; + font-size: 15px; } + +.timepicker-tick.active, +.timepicker-tick:hover { + background-color: rgba(77, 153, 153, 0.25); } + +.timepicker-dial { + transition: transform 350ms, opacity 350ms; } + +.timepicker-dial-out { + opacity: 0; } + .timepicker-dial-out.timepicker-hours { + transform: scale(1.1, 1.1); } + .timepicker-dial-out.timepicker-minutes { + transform: scale(0.8, 0.8); } + +.timepicker-canvas { + transition: opacity 175ms; } + .timepicker-canvas line { + stroke: #4D9999; + stroke-width: 4; + stroke-linecap: round; } + +.timepicker-canvas-out { + opacity: 0.25; } + +.timepicker-canvas-bearing { + stroke: none; + fill: #4D9999; } + +.timepicker-canvas-bg { + stroke: none; + fill: #4D9999; } + +/* Footer */ +.timepicker-footer { + margin: 0 auto; + padding: 5px 1rem; + display: flex; + justify-content: space-between; } + +.timepicker-clear { + color: #F44336; } + +.timepicker-close { + color: #4D9999; } + +.timepicker-clear, +.timepicker-close { + padding: 0 20px; } + +/* Media Queries */ +@media only screen and (min-width: 601px) { + .timepicker-modal { + max-width: 600px; } + + .timepicker-container.modal-content { + flex-direction: row; } + + .timepicker-text-container { + top: 32%; } + + .timepicker-display-am-pm { + position: relative; + right: auto; + bottom: auto; + text-align: center; + margin-top: 1.2rem; } } +.material-icons { + font-family: 'Material Icons'; + font-weight: normal; + font-style: normal; + font-size: 24px; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + white-space: nowrap; + word-wrap: normal; + direction: ltr; + -webkit-font-feature-settings: 'liga'; + -webkit-font-smoothing: antialiased; } + +.btn.disabled, .disabled.btn-large, .disabled.btn-small { + pointer-events: auto; } + +.grid { + grid-auto-rows: min-content; + display: inline-grid; + width: 100%; } + .grid .ghead, .grid .gbody, .grid .gfoot, .grid .gr { + display: contents; } + .grid .gd, .grid .gh { + display: grid; + grid-auto-columns: 1fr; + justify-content: center; + align-content: center; + text-align: center; + padding: 15px; } + .grid .gh { + align-content: baseline; } + .grid .gh .card { + position: sticky; + top: 15px; + bottom: 15px; } + .grid .ghead { + color: #B2B2B2; } + .grid .ghead .gh { + z-index: 8; + border-bottom: 1px solid #B2B2B2; + max-height: 40px; + line-height: 1em; } + .grid .gbody .gr.spacer { + grid-column: 1 / -1; } + .grid .gbody .separator { + grid-column: 1 / -1; + border-top: 1px solid #B2B2B2; } + .grid .pagination { + grid-column: 1 / -1; } + .grid .gbody > .gr > .gd { + min-height: 70px; } + .grid.striped .gbody > .gr:nth-child(odd) .gd { + background-color: #ffeee6; } + .grid.striped .gbody > .gr:nth-child(odd):hover .gd { + background-color: #f7f2ee; } + .grid.striped .gbody > .gr:nth-child(even):hover .gd { + background-color: #eef6f6; } + .grid .gbody > .gr .gd.action { + grid-auto-flow: column; + grid-gap: 5px; } + .grid .gbody > .gr .gd.action.side .btn, .grid .gbody > .gr .gd.action.side .btn-large, .grid .gbody > .gr .gd.action.side .btn-small { + width: min-content; } + .grid .gbody > .gr > .gr.extendable > .gd.action { + padding-top: 0; + padding-bottom: 0; + transition: padding .3s, max-height .3s; } + .grid .gbody > .gr > .gr.extendable > .gd.action .btn, .grid .gbody > .gr > .gr.extendable > .gd.action .btn-large, .grid .gbody > .gr > .gr.extendable > .gd.action .btn-small { + max-height: 0; + transition: max-height 0.3s; } + .grid .gbody > .gr:focus-within .gd { + background-color: #5cd6d6 !important; } + .grid .gbody > .gr:focus-within > .gr.extendable > .gd.action { + padding-bottom: 15px; } + .grid .gbody > .gr:focus-within > .gr.extendable > .gd.action .btn, .grid .gbody > .gr:focus-within > .gr.extendable > .gd.action .btn-large, .grid .gbody > .gr:focus-within > .gr.extendable > .gd.action .btn-small { + max-height: 36px; } + +#tooltip { + opacity: .75; + transition: opacity .3s, margin-top .3s; + position: fixed; + pointer-events: none; + transform: translate(-50%, -100%); + max-width: 120px; + width: 120px; + background-color: black; + color: #fff; + text-align: center; + padding: 5px; + border-radius: 6px; + margin-top: -7px; + font-size: 11px; + line-height: 13px; + z-index: 1005; } + #tooltip.v-enter, #tooltip.v-leave-to { + margin-top: 3px; + opacity: 0; } + #tooltip::after { + content: " "; + position: absolute; + left: 50%; + bottom: -10px; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: black transparent transparent transparent; } + +#documentation { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + z-index: 2000; + pointer-events: none; + opacity: 1; + transition: opacity .3s; } + #documentation.v-enter, #documentation.v-leave-to { + opacity: 0; } + #documentation.v-enter .overlay, #documentation.v-leave-to .overlay { + width: 0 !important; + height: 0 !important; } + #documentation .overlay { + position: fixed; + border-radius: 10050px; + border: 10000px solid rgba(0, 0, 0, 0.66); + box-sizing: content-box; + transform: translate(-50%, -50%); + transition: all .3s; } + #documentation.first .overlay { + transition: opacity .3s, height .3s, width .3s; } + #documentation .content { + position: absolute; + font-size: 1.5em; + color: white; + max-height: 75%; + max-width: 75%; } + #documentation .content h1 { + text-align: center; } + #documentation .content * { + color: white; } + #documentation .content > *:first-child { + margin-top: 0; } + #documentation .content > *:last-child { + margin-bottom: 0; } + #documentation svg { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + stroke-width: 5px; + fill: none; + stroke: white; } + #documentation .next, #documentation .close { + user-select: none; + pointer-events: all !important; } + #documentation .close { + top: 16px; + right: 6px; + padding-top: 0; } + +.dropdown-button { + position: relative; + display: block; + overflow: visible; + margin: 12px 5px; + line-height: 1; } + .dropdown-button:focus .dropdown-content, .dropdown-button:focus-within .dropdown-content { + display: block; + opacity: 1; } + .dropdown-button .dropdown-content { + overflow: visible; + top: calc(100% + 12px); + left: auto; + right: 0; + min-width: 250px; + width: min-content; } + .dropdown-button .dropdown-content::before { + content: ""; + position: absolute; + top: -20px; + right: 10px; + border-width: 10px; + border-style: solid; + border-color: transparent transparent white transparent; } + .dropdown-button .dropdown-content .dropdown-title { + margin: 0; + padding: 8px; + font-weight: bold; + border-bottom: 1px solid #DDDFE2; } + .dropdown-button .dropdown-content .dropdown-title .option { + position: absolute; + right: 8px; + font-weight: normal; + cursor: pointer; } + .dropdown-button .dropdown-content .dropdown-title .option:hover { + text-decoration: underline; } + .dropdown-button .dropdown-content li:hover { + background-color: initial; } + +.tabs { + display: grid; + background: initial; } + .tabs .tab:not(.disabled) a { + cursor: pointer; + position: relative; } + .tabs .tab:not(.disabled) a::after { + position: absolute; + content: ""; + background: #B84000; + width: 0; + height: 2px; + bottom: 0; + left: 50%; + transform: translateX(-50%); + transition: width 0.3s; } + .tabs .tab:not(.disabled) a:hover::after, .tabs .tab:not(.disabled) a.active::after { + width: 100%; } + .tabs .tab.disabled a { + pointer: default; } + +.arrow { + border: solid black; + border-width: 0 2px 2px 0; + border-top-left-radius: 10px; + display: inline-block; + padding: 3px; + transition: transform .3s; } + .arrow.to-right { + transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); } + .arrow.to-left { + transform: rotate(135deg); + -webkit-transform: rotate(135deg); } + .arrow.to-up { + transform: rotate(-135deg); + -webkit-transform: rotate(-135deg); } + .arrow.to-down { + transform: rotate(45deg); + -webkit-transform: rotate(45deg); } + +.modal-wrapper.v-enter-active, .modal-wrapper.v-leave-active { + transition: all .3s; } +.modal-wrapper.v-enter .modal, .modal-wrapper.v-leave-to .modal { + opacity: 0; + transform: scale(0.5); } + .modal-wrapper.v-enter .modal + .modal-overlay, .modal-wrapper.v-leave-to .modal + .modal-overlay { + opacity: 0; } +.modal-wrapper .modal { + opacity: 1; + transform: none; + display: block; + top: 10%; + z-index: 1003; + min-width: 900px; + max-height: 80vh; + transition: opacity .3s ease-in, transform .3s ease-out; } + .modal-wrapper .modal .dragger { + cursor: move; + position: absolute; + height: 24px; + width: 24px; } + .modal-wrapper .modal .dragger:before { + content: '.'; + color: #aaa; + position: absolute; + left: 4.5px; + top: 1.5px; + font-size: 20px; + line-height: 0; + text-shadow: 0 5px, 0 10px, 5px 0, 5px 5px, 5px 10px, 10px 0, 10px 5px, 10px 10px; } + .modal-wrapper .modal.modal-fixed-footer { + height: auto; + padding-bottom: 56px; + overflow: hidden; } + .modal-wrapper .modal.modal-fixed-footer .modal-content { + position: initial; + max-height: calc(80vh - 56px); } + .modal-wrapper .modal + .modal-overlay { + top: 0; + z-index: 1002; + display: block; + opacity: 0.5; + transition: opacity .3s ease-in; } +.modal-wrapper#confirmDialog .modal { + top: 15%; + z-index: 1005; + width: 50vw; + min-width: 500px; } + .modal-wrapper#confirmDialog .modal + .modal-overlay { + z-index: 1004; } + +.input-field:focus-within > label { + color: #4D9999; + transform: translateY(-14px) scale(0.8); + transform-origin: 0 0; } + +.input-field .helper-text.flash { + animation: blinker 1s linear infinite; } + +@keyframes blinker { + 50% { + opacity: 0; } } +.chips { + padding-top: 7px; } + .chips:focus-within { + border-bottom: 1px solid #4D9999; + box-shadow: 0 1px 0 0 #4D9999; } + .chips:empty ~ label { + font-size: inherit; + transform: none; } + .chips .input { + height: 32px; + vertical-align: middle; } + .chips .input[disabled="disabled"] { + border: none; } + +.chip { + cursor: pointer; + user-select: none; + color: white; + background-color: #B2B2B2; } + .chip.negative { + background-color: #B84000; } + .chip.positive { + background-color: #4D9999; } + .chip.valid { + background-color: #26A96C; } + .chip .close { + height: 24px; + width: 24px; + margin: 4px -7px 4px 4px; + line-height: 24px !important; + border-radius: 20px; + text-align: center; + padding: 0; + transition: background .3s; } + .chip .close:hover { + background: rgba(0, 0, 0, 0.3); } + +.toast { + transition: margin-top .3s, opacity .3s; } + .toast.v-enter { + margin-top: 58px; + opacity: 0 !important; } + .toast.v-leave-to { + margin-top: -48px; + opacity: 0 !important; } + +.materialize-textarea { + line-height: normal; + padding: .8rem 0 .8rem 0; + min-height: 3rem; + border-bottom: 1px solid #B2B2B2; + border-radius: 0; + outline: none; + width: 100%; + font-size: 16px; + transition: box-shadow .3s, border .3s; } + +.materialize-textarea:focus { + outline: none; + border-bottom: 1px solid #4D9999; + box-shadow: 0 1px 0 0 #4D9999; } + +/** alternative modals +.modal { + position: fixed; + top: 0; + left: 0; + background-color: rgba(0, 0, 0, 0.5); + height: 100vh; + width: 100vw; + overflow-y: scroll; +} + +.modal::before, .modal::after { + content: ""; + display: block; + height: 20px; + width: 100%; +} + + +.modal .modal-content { + background: #fafafa; + width: 60%; + margin: auto; +} + +.modal .modal-footer { + position: sticky; + bottom: 20px; + left: 0; + right: 0; + text-align: center; +} +**/ +::-webkit-scrollbar { + width: 12px; + height: 12px; + border-radius: 3px; } + +::-webkit-scrollbar-track { + background-color: #cecece; + border-left: 1px solid #cdc7c2; } + +::-webkit-scrollbar-thumb { + background-color: #7e8182; + border: 3px solid #cecece; + border-radius: 6px; + min-height: 40px; } + +::-webkit-scrollbar-thumb:hover { + background-color: #565b5c; } + +::-webkit-scrollbar-thumb:active { + background-color: #1b6acb; } + +h1 { + color: #B84000; } + +h2 { + color: #B84000; } + +h3 { + color: #000000; } + +h4 { + color: #B84000; } + +h5 { + color: #000000; } + +td, th { + border-radius: 0; } + +strong { + font-weight: bold; } + +textarea { + display: block; } + +.btn, .btn-large, .btn-small { + text-overflow: ellipsis; + white-space: nowrap; } + .btn.primary-color:hover, .primary-color.btn-large:hover, .primary-color.btn-small:hover { + background-color: #B84000; } + +.container { + width: 85% !important; } + +img { + overflow: hidden; + max-width: 100%; + max-height: 100%; } + +.clickable:hover { + cursor: pointer; + text-decoration: underline; } + +.input-field .materialize-textarea { + min-width: 50px; + font-size: inherit; } + .input-field .materialize-textarea:not([contenteditable]), .input-field .materialize-textarea[contenteditable="false"] { + border-color: transparent; } + .input-field .materialize-textarea[placeholder]:empty::before { + content: attr(placeholder); + color: black; + opacity: 0.25; } + +[tabindex]:focus { + outline: none; + cursor: initial; } + +[v-cloak] { + display: none; } + +[unselectable="on"] { + -moz-user-select: -moz-none; + -khtml-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; } + +.search-box > input { + margin-bottom: 0; } + +html body { + min-width: 900px; + overflow-y: scroll; + overflow-x: auto; } + html body #app { + --primary-color-hover: var(--primary-color)10; + --secondary-color-hover: var(--secondary-color)10; + display: flex; + min-height: 100vh; + flex-direction: column; } + html body #app #help { + margin: 0 10px; + cursor: pointer; } + html body #app.help { + cursor: help; } + html body #app.help :not(.documented) { + pointer-events: none; } + html body #app.help .documented { + pointer-events: all; } + html body #app > nav { + height: 64px; + position: sticky; + min-width: 900px; + width: 100%; + top: 0; + left: 0; + z-index: 10; } + html body #app #loading { + position: fixed; + margin: auto; + top: 64px; + border-radius: none; + z-index: 5; } + html body #app .current-view-wrapper { + display: flex; + flex-direction: column; + min-height: calc(100vh - 64px); + padding-bottom: 30px; } + html body #app .current-view-wrapper .current-view { + display: flex; + flex-direction: column; + flex: 1; } + html body #app .current-view-wrapper .current-view > .container { + display: flex; + flex-direction: column; + flex: 1; + width: 85%; } + html body #app .current-view-wrapper .current-view > .container > #header { + position: sticky; + padding: 0 17px; + top: 64px; + background: white; + display: grid; + grid-template-columns: 1fr max-content; + height: 60px; + align-items: center; + z-index: 4; } + html body #app .current-view-wrapper .current-view > .container > #header > div { + display: grid; + grid-column-gap: 0.25em; + grid-template-columns: max-content 1fr max-content max-content; + align-items: center; + margin-right: 15px; + width: fit-content; } + html body #app .current-view-wrapper .current-view > .container > #header > div > h1 { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + margin: 0; } + html body #app .current-view-wrapper .current-view > .container > #header > div .author { + color: #B84000; + font-size: 14px; } + html body #app .current-view-wrapper .current-view > .container > #header > div .details { + margin: 0; + line-height: 1em; } + html body #app .current-view-wrapper .current-view > .container > #header > div .details p { + margin: 0; } + html body #app .current-view-wrapper .current-view > .container > #header #backTo { + position: absolute; + top: 18px; + left: 0; } + html body #app .current-view-wrapper .current-view > .container > .grid { + flex: 1; } + html body #app .current-view-wrapper .current-view > .container > .grid > .ghead .gh { + position: sticky; + top: 124px; + background: white; + z-index: 8; } + html body #app .current-view-wrapper .current-view > .container > .grid .gh > .card { + top: 179px; } + html body #app .page-footer .contributors a { + display: flex; + height: 70px; + align-items: center; + justify-content: center; + float: left; + margin-right: 50px; } + html body #app .page-footer .contributors a img { + max-width: 180px; + max-height: 100%; } + +@media only print { + html body #app > nav { + display: none; } + html body #app .current-view { + padding-top: 0; } + html body #app .current-view > .container { + width: 100%; } + html body #app .current-view > .container > #header { + top: 0; } } +.switch label { + position: relative; } + +.card { + display: block; } + @media only screen and (max-width: 600px) { + .card { + max-width: 120px; } } + @media only screen and (min-width: 601px) { + .card { + max-width: 160px; } } + @media only screen and (min-width: 993px) { + .card { + max-width: 200px; } } + @media only screen and (min-width: 1201px) { + .card { + max-width: 240px; } } + .card h2 { + max-height: 43px; + min-height: 43px; + overflow-y: auto; } + +.card-image { + width: 100%; + margin: auto; } + @media only screen and (max-width: 600px) { + .card-image { + width: 120px; + height: calc(120px / 3 * 2); } } + @media only screen and (min-width: 601px) { + .card-image { + width: 160px; + height: calc(160px / 3 * 2); } } + @media only screen and (min-width: 993px) { + .card-image { + width: 200px; + height: calc(200px / 3 * 2); } } + @media only screen and (min-width: 1201px) { + .card-image { + width: 240px; + height: calc(240px / 3 * 2); } } + .card-image img { + height: auto !important; + width: auto !important; + margin: auto; } + +.light-color { + background: #eef6f6; } + +.primary-color { + background: #B84000; + color: white; } + +nav #logoContainer { + z-index: 1; + float: left; } + nav #logoContainer img { + vertical-align: middle; + margin-bottom: 5px; } +nav .menu a { + position: relative; } + nav .menu a::after { + position: absolute; + content: ""; + background: white; + width: 0; + height: 2px; + bottom: 0; + left: 50%; + transform: translateX(-50%); + transition: width 0.3s; } + nav .menu a:hover::after, nav .menu a.active::after { + width: 100%; } +nav #userSettings .dropdown-content a.btn, nav #userSettings .dropdown-content a.btn-large, nav #userSettings .dropdown-content a.btn-small { + background: #B2B2B2; + color: white; + width: calc(100% - 30px); + margin: 10px 15px; } +nav #userSettings .dropdown-content #changePasswd { + margin: 5px; } + nav #userSettings .dropdown-content #changePasswd .input-field input:not(:focus) { + border-bottom: 1px solid; } +nav #notifications { + position: relative; } + nav #notifications #notificationCount { + position: absolute; + cursor: pointer; + top: 15px; + right: 17px; + border-radius: 2px; + padding: 1px 3px; + line-height: 1.3; + min-height: 1.3em; + min-width: 0; + font-size: 10px; + background-color: #F44336; } + nav #notifications .dropdown-button { + width: 40px; + height: 40px; + padding: 0; + border-radius: 100px; } + nav #notifications .dropdown-button i { + cursor: pointer; + text-align: center; + line-height: 40px; + height: 40px; } + nav #notifications .dropdown-button:focus, nav #notifications .dropdown-button:focus-within { + background-color: rgba(0, 0, 0, 0.1); } + nav #notifications .dropdown-content { + width: 460px; } + nav #notifications .dropdown-content ul { + height: calc(100vh - 112px); + max-height: 600px; + overflow: auto; } + nav #notifications .dropdown-content ul li { + position: relative; + margin-right: 25px; + border-bottom: 1px solid #DDDFE2; } + nav #notifications .dropdown-content ul li.unread { + background-color: #ffeee6; } + nav #notifications .dropdown-content ul li.unread .read-toggle { + border-width: 3px; } + nav #notifications .dropdown-content ul li.unread:hover { + background-color: #f7f2ee; } + nav #notifications .dropdown-content ul li:hover { + background-color: #eef6f6; } + nav #notifications .dropdown-content ul li:hover .read-toggle { + opacity: 1; } + nav #notifications .dropdown-content ul li a { + padding: 5px 16px; + font-size: 14px; } + nav #notifications .dropdown-content ul li a .arg { + font-weight: bold; } + nav #notifications .dropdown-content ul li a:hover { + background-color: initial; } + nav #notifications .dropdown-content ul li .read-toggle { + position: absolute; + opacity: 0; + right: 10px; + top: 10px; + width: 10px; + height: 10px; + padding: 0; + border: 5px solid #B2B2B2; + border-radius: 10px; + transition: opacity .3s; } + nav #notifications .dropdown-content ul li .read-toggle:hover { + border-color: #808080; } + +#login > div { + justify-content: center; } + #login > div #loginForm { + width: 500px; } + +#aafImport .progress { + width: 490px; } + +#home #welcomeCallout { + margin: 0; + color: #B84000; } + #home #welcomeCallout img { + max-height: 100px; } + @media only screen and (min-width: 993px) { + #home #welcomeCallout img { + margin-left: 50px; } } + @media only screen and (max-width: 600px) { + #home #welcomeCallout img { + display: none; } } +#home #categoriesList .col { + display: inline-block; + float: none; } + +#debates .opinion { + height: 16px; + width: 100%; + background-color: #B2B2B2; } + #debates .opinion .for { + height: 100%; + float: left; + background-color: #4D9999; } + #debates .opinion .against { + height: 100%; + float: right; + background-color: #BA4100; } + +#debate .comment-mark, .comment .comment-mark { + display: inline; } + +@media only print { + #debate { + height: auto !important; } + #debate .selection > div { + max-height: none !important; } + #debate .selection::before, #debate .selection::after { + content: none; } + #debate #documentContainer, #debate #commentsContainer { + height: auto !important; } } +#debate .row { + margin: 0; } +#debate #options { + position: sticky; + padding: 0 17px; + top: 124px; + background: white; + z-index: 2; + text-align: right; } + #debate #options .col { + padding: 0; } + #debate #options #sortCommentsBy, #debate #options #leftDisplay { + position: absolute; + bottom: 0; } + #debate #options #sortCommentsBy input + i, #debate #options #leftDisplay input + i { + font-style: normal; } + #debate #options #sortCommentsBy input:checked + i, #debate #options #leftDisplay input:checked + i { + font-weight: bold; } + #debate #options .search-box { + margin: 0; } + #debate #options .search-box > input { + margin-bottom: 5px; + margin-top: -5px; } +#debate #mainContainer { + height: calc(100vh - 170px); } +#debate #documentContainer, #debate #commentsContainer { + width: 50%; + height: 100%; + float: left; } + #debate #documentContainer .scroll-area, #debate #commentsContainer .scroll-area { + height: 100%; + overflow-y: scroll; } +#debate #commentsContainer.loading { + position: relative; + overflow-x: hidden; } + #debate #commentsContainer.loading::before, #debate #commentsContainer.loading::after { + content: ""; + display: block; + top: 0; + left: 0; + width: 100%; + height: 100%; + position: absolute; } + #debate #commentsContainer.loading::before { + background: #e0e0e0; + z-index: 1; } + #debate #commentsContainer.loading::after { + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); + transform: translateX(-100%); + animation: loading 1.5s infinite; + z-index: 1; } +@keyframes loading { + 100% { + transform: translateX(100%); } } +#debate #documentContainer .scroll-area { + direction: rtl; } + #debate #documentContainer .scroll-area > * { + direction: ltr; } +#debate #documentContainer { + z-index: 1; } + #debate #documentContainer .scroll-area { + padding-left: 5px; } + #debate #documentContainer .scroll-area .wrap { + display: flex; + min-height: 100%; } + #debate #documentContainer .scroll-area .wrap #documentDisplay { + text-align: justify; + font-size: 13px; + line-height: 1.42; + width: calc(100% - 60px); + float: left; } + #debate #documentContainer .scroll-area .wrap #documentDisplay::selection, #debate #documentContainer .scroll-area .wrap #documentDisplay ::selection { + background-color: #C6E4E3; } + #debate #documentContainer .scroll-area .wrap .bullets-container { + float: left; } +#debate .selection_popup { + position: absolute; + cursor: pointer; + background: #4D9999; + color: white; + border-radius: 5px; + padding: 0 5px; } + #debate .selection_popup::before { + content: ""; + position: absolute; + border-width: 8px 5px; + border-style: solid; } + #debate .selection_popup.top { + margin-top: -7px; + margin-left: -15px; + transform: translateY(-100%); } + #debate .selection_popup.top::before { + bottom: -16px; + left: 10px; + border-color: #4D9999 transparent transparent transparent; } + #debate .selection_popup.bottom { + margin-top: 7px; + margin-left: 15px; + transform: translateX(-100%); } + #debate .selection_popup.bottom::before { + top: -16px; + right: 10px; + border-color: transparent transparent #4D9999 transparent; } +#debate .comment-container.moderated::after { + content: ""; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + background-color: #F44336; + opacity: 50%; } +#debate .answers-container { + overflow: hidden; } + #debate .answers-container .answers { + overflow-y: hidden; + padding: 0 5px 0 10px; + transition: margin-top .3s; } + #debate .answers-container .answers.v-enter-active { + transition: all 0s; } +#debate .comment-body .selection, #debate .spaghetti-data .selection { + cursor: pointer; } + #debate .comment-body .selection:hover, #debate .comment-body .selection.active, #debate .spaghetti-data .selection:hover, #debate .spaghetti-data .selection.active { + background: #ebecee; + border-left-color: #808080; + border-right-color: #808080; } + #debate .comment-body .selection:hover::before, #debate .comment-body .selection.active::before, #debate .spaghetti-data .selection:hover::before, #debate .spaghetti-data .selection.active::before { + background-image: linear-gradient(#ebecee, transparent); } + #debate .comment-body .selection:hover::after, #debate .comment-body .selection.active::after, #debate .spaghetti-data .selection:hover::after, #debate .spaghetti-data .selection.active::after { + background-image: linear-gradient(transparent, #ebecee); } +#debate .bullets-container { + position: relative; + width: 50px; + margin: 0 5px; } + #debate .bullets-container .bullets-box { + position: absolute; + height: 1em; + width: 100%; + display: flex; + align-items: center; + justify-content: space-evenly; } + #debate .bullets-container .bullets-box .bullet { + height: 10px; + width: 10px; } + #debate .bullets-container .bullets-box .bullet::before { + content: ""; + display: block; + width: 100%; + height: 100%; + box-sizing: border-box; + border-radius: 10px; } + #debate .bullets-container .bullets-box .bullet.for::before { + background: #4D9999; } + #debate .bullets-container .bullets-box .bullet.neutral::before { + background: #B2B2B2; } + #debate .bullets-container .bullets-box .bullet.against::before { + background: #BA4100; } + #debate .bullets-container .bullets-box .bullet:hover { + cursor: pointer; + z-index: 2; + width: 8px; + height: 8px; + margin: 1px; } + #debate .bullets-container .bullets-box .bullets-drop-down { + min-width: 10px; + padding: 5px; + border-radius: 10px; + box-sizing: content-box; + line-height: 10px; + font-size: 10px; + text-align: center; + z-index: 1; + font-weight: bold; + color: white; + transition: box-shadow .3s; } + #debate .bullets-container .bullets-box .bullets-drop-down.for { + background: #4D9999; } + #debate .bullets-container .bullets-box .bullets-drop-down.against { + background: #BA4100; } + #debate .bullets-container .bullets-box .bullets-drop-down.neutral { + background: #B2B2B2; } + #debate .bullets-container .bullets-box .bullets-drop-down > .label { + overflow: hidden; + height: 10px; + transition: height .3s; } + #debate .bullets-container .bullets-box .bullets-drop-down > .body { + transition: height .3s; + overflow: hidden; } + #debate .bullets-container .bullets-box:not(:hover) .bullets-drop-down { + box-shadow: 4px 0 0 -1px #ddd, 4px 0 1px -1px black, 8px 0 0 -2px #bbb, 8px 0 1px -2px black, 12px 0 0 -3px #aaa, 12px 0 1px -3px black; } + #debate .bullets-container .bullets-box:not(:hover) .bullets-drop-down > .body { + height: 0 !important; } + #debate .bullets-container .bullets-box:hover .bullets-drop-down { + z-index: 9999; + background: white !important; + width: 10px; } + #debate .bullets-container .bullets-box:hover .bullets-drop-down > .label { + height: 0; } +#debate .spaghetti-data { + width: 50%; + float: left; } + #debate .spaghetti-data > .theme { + display: grid; + grid-template-columns: min-content 1fr; + align-items: center; } + #debate .spaghetti-data > .theme .close { + cursor: pointer; + margin-bottom: 10px; } +#debate svg.spaghettis { + position: fixed; + pointer-events: none; + top: 0; + left: 0; + width: 100%; + height: 100%; + stroke-width: 3px; } + #debate svg.spaghettis use { + fill: none; + stroke-width: 6px; + cursor: pointer; + pointer-events: initial; } + #debate svg.spaghettis path { + fill: none; + stroke-width: inherit; + pointer-events: initial; } + #debate svg.spaghettis path.trigger { + stroke-width: 20px; } + #debate svg.spaghettis > g { + transition: opacity .3s; } + #debate svg.spaghettis.hover > g { + opacity: 0.25; } + +.comment { + position: relative; + font-size: 13px; + padding: 3px 5px; + margin-bottom: 5px; + box-sizing: border-box; + border-left: 3px solid; + outline-width: 3px; + outline-offset: -3px; } + .comment .close { + position: absolute; + cursor: pointer; + top: 0; + right: .5em; } + .comment.for { + border-color: #4D9999; + outline-color: #4D9999; } + .comment.for .comment-header * { + color: #4D9999; } + .comment.neutral { + border-color: #B2B2B2; + outline-color: #B2B2B2; } + .comment.neutral .comment-header * { + color: #B2B2B2; } + .comment.against { + border-color: #BA4100; + outline-color: #BA4100; } + .comment.against .comment-header * { + color: #BA4100; } + .comment:focus-within { + outline-style: solid; + outline-width: 3px; } + .comment .comment-header .username { + display: inline-block; + margin-right: 10px; + margin-top: 0; } + .comment .comment-header .comment-count { + cursor: pointer; } + .comment .comment-body .reformulation-wrapper, .comment .comment-body .argumentation-wrapper { + display: grid; + grid-template-columns: 20px 1fr 60px; } + .comment .comment-body .reformulation-wrapper > i, .comment .comment-body .reformulation-wrapper > .tags > i, .comment .comment-body .argumentation-wrapper > i, .comment .comment-body .argumentation-wrapper > .tags > i { + font-size: 18px; + margin-top: 1px; } + .comment .comment-body .reformulation-wrapper .reformulation { + white-space: pre-wrap; } + .comment .comment-body .reformulation-wrapper .tags { + margin: 0 20px; } + .comment .comment-body .reformulation-wrapper .tags i { + cursor: pointer; + text-shadow: 0 0 1px black, 0 0 1px black, 0 0 1px black, 0 0 1px black; + color: white; } + .comment .comment-body .reformulation-wrapper .tags.disabled i { + cursor: default; + opacity: .5; } + .comment .comment-body .argumentation-wrapper .argumentation { + white-space: pre-wrap; } + .comment .comment-body .argumentation-wrapper .argumentation::selection { + background-color: #C6E4E3; } + +.selection { + overflow: hidden; + position: relative; + background: #DDDFE2; + border-left: 3px solid #B2B2B2; + border-right: 3px solid #B2B2B2; + border-radius: 5px; + transition: background .3s, border-color .3s; + text-align: justify; + font-size: 13px; + line-height: 1.42; + margin-bottom: 10px; } + .selection > div > *:nth-last-child(1) { + margin-bottom: 0; } + .selection::after, .selection::before { + position: absolute; + content: ""; + width: 100%; + height: 10px; + background-image: linear-gradient(transparent, #DDDFE2); + left: 0; + bottom: 0; } + .selection::before { + background-image: linear-gradient(#DDDFE2, transparent); + top: 0; } + .selection > div { + max-height: 100px; + overflow: auto; + padding: 5px; } + .selection > div *:nth-child(1) { + margin-top: 0; } + .selection > div *:nth-last-child(1) { + margin-bottom: 0; } + +#commentModal .modal { + resize: horizontal; + min-width: 500px; } +#commentModal #argumentation .materialize-textarea { + min-height: 6em; } +#commentModal .input-field:focus-within > #reformulationCheck svg .line { + stroke: #4D9999; + stroke-width: 2px; } +#commentModal #reformulationCheck { + display: flex; + align-items: center; + background: #fafafa; + position: absolute; + right: 0; + bottom: -19px; } +@keyframes spin { + from { + transform: rotate(0deg) translate(-3px) rotate(0deg); } + to { + transform: rotate(360deg) translate(-3px) rotate(-360deg); } } + #commentModal #reformulationCheck.loading svg .pupil { + animation: spin 2s linear infinite; } + #commentModal #reformulationCheck svg { + fill: none; + stroke: none; } + #commentModal #reformulationCheck svg .eye { + stroke: #e5e5e5; } + #commentModal #reformulationCheck svg .eyelid { + fill: #e5e5e5; } + #commentModal #reformulationCheck svg .pupil { + fill: #666666; } + #commentModal #reformulationCheck svg .line, #commentModal #reformulationCheck svg .mouth { + stroke: #9e9e9e; + transition: stroke .3s, stroke-width .3s; } + #commentModal #reformulationCheck svg + span { + font-size: 10px; + border: 1px solid #9e9e9e; + margin-left: 7px; + margin-bottom: 5px; + padding: 0 5px; } + #commentModal #reformulationCheck svg + span::before { + content: ""; + position: absolute; + top: 10px; + left: 36px; + border: solid #9e9e9e; + border-width: 0 1px 1px 0; + padding: 3px; + background: #fafafa; + transform: rotate(135deg); } +#commentModal #opinion { + padding-bottom: 1rem; } + #commentModal #opinion input + span { + padding-left: 16px; } + #commentModal #opinion input + span::before { + display: none; } + #commentModal #opinion input + span::after { + display: none; } + #commentModal #opinion input:checked + span { + box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.14) inset, 0 1px 7px 0 rgba(0, 0, 0, 0.12) inset, 0 3px 1px -1px rgba(0, 0, 0, 0.2) inset; } + #commentModal #opinion input:not(:checked) + span:not(:hover) { + opacity: 0.5; } + #commentModal #opinion label > .against { + background-color: #BA4100; } + #commentModal #opinion label > .neutral { + background-color: #B2B2B2; } + #commentModal #opinion label > .for { + background-color: #4D9999; } +#commentModal #hypostase .list { + display: grid; + width: 100%; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr; + transition: height .3s; + height: 27px; } + #commentModal #hypostase .list.expert { + height: 219px; } + #commentModal #hypostase .list input[type="checkbox"] { + display: none; } + #commentModal #hypostase .list > div > .btn, #commentModal #hypostase .list > div > .btn-large, #commentModal #hypostase .list > div > .btn-small { + display: block; + height: auto; + line-height: initial; + text-align: center; + padding: 0; + cursor: pointer; + margin: 3px; + padding: 2px 5px !important; + text-transform: none; } + #commentModal #hypostase .list > div > .btn:first-of-type, #commentModal #hypostase .list > div > .btn-large:first-of-type, #commentModal #hypostase .list > div > .btn-small:first-of-type { + font-weight: bold; } + #commentModal #hypostase .list > div > .btn:not(:hover), #commentModal #hypostase .list > div > .btn-large:not(:hover), #commentModal #hypostase .list > div > .btn-small:not(:hover) { + opacity: 0.75; } + #commentModal #hypostase .list > div input:checked + .btn, #commentModal #hypostase .list > div input:checked + .btn-large, #commentModal #hypostase .list > div input:checked + .btn-small { + background: #4D9999 linear-gradient(0deg, #4D9999 0%, #4D9999 100%); + box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.14) inset, 0 1px 7px 0 rgba(0, 0, 0, 0.12) inset, 0 3px 1px -1px rgba(0, 0, 0, 0.2) inset; + opacity: 1; } + +#documents .grid .gr.header .gh:hover { + background-color: #eef6f6; } +#documents .grid .gr.header .card-action { + line-height: 0; + padding-top: 0; + padding-bottom: 0; + border: none; + transition: all .3s; } + #documents .grid .gr.header .card-action .btn, #documents .grid .gr.header .card-action .btn-large, #documents .grid .gr.header .card-action .btn-small { + max-height: 0; } +#documents .grid .gr.header:focus-within .gh { + background-color: #5cd6d6 !important; } +#documents .grid .gr.header:focus-within .card-action { + padding-bottom: 15px; } + #documents .grid .gr.header:focus-within .card-action .btn, #documents .grid .gr.header:focus-within .card-action .btn-large, #documents .grid .gr.header:focus-within .card-action .btn-small { + max-height: 36px; } + +#document .input-field.inline { + margin: 0; } +#document .input-field { + margin-bottom: 1px; } +#document .ql-toolbar { + position: sticky; + top: 124px; + background: white; + z-index: 10; + height: 42px; + overflow: hidden; + transition: height .3s, padding .3s; } +#document .ql-container { + margin-top: -1px; + background: white; + border-top: 1px solid #ccc; + transition: margin-top .3s; } + #document .ql-container .ql-editor { + margin-bottom: 10px; + text-align: justify; + transition: height .3s; } +#document #documentDisplay:not(.in-edition) .ql-toolbar { + height: 0; + padding-top: 0; + padding-bottom: 0; + border-bottom-width: 0; } + +#createDebate .steps > .tabs { + position: sticky; + top: 75px; + z-index: 9; + display: block; + margin-top: -50px; + text-align: center; + border: none; + height: auto; + background: white; } + #createDebate .steps > .tabs .tab { + height: auto; } + #createDebate .steps > .tabs .tab a { + text-transform: capitalize; + line-height: 1em; } + #createDebate .steps > .tabs .tab a::after { + content: none; } + #createDebate .steps > .tabs .tab:not(.disabled) a.active img, #createDebate .steps > .tabs .tab:not(.disabled) a:hover img { + border: 1px solid #5cd6d6; + border-radius: 200px; + margin: 0 -1px; } + #createDebate .steps > .tabs .tab.disabled a img { + filter: grayscale(100%); } +#createDebate .steps .grid > .ghead .gh { + position: sticky; + top: 202px; + background: white; + z-index: 8; } +#createDebate .steps .grid .gh .card { + top: 242px; } +#createDebate .steps #contributors > div > .tabs { + position: sticky; + top: 202px; + background: white; + z-index: 8; } +#createDebate .steps #contributors .grid > .ghead .gh { + position: sticky; + top: 250px; + background: white; + z-index: 8; } +#createDebate .steps .collection-item > span { + display: inline-block; + max-width: calc(100% - 40px); } +#createDebate .steps .collection-item .close { + cursor: pointer; } +#createDebate #advancedOptions > li { + cursor: pointer; } + #createDebate #advancedOptions > li .arrow { + right: 20px; + position: absolute; } +#createDebate #advancedOptions #advancedOptionsBody { + overflow: hidden; } + #createDebate #advancedOptions #advancedOptionsBody > ul { + transition: margin-top .3s; } + +#contributors .search-box { + width: 20em; + margin: 0; } + +#sort-options { + height: 46px; } + #sort-options select { + width: 50%; + float: left; + margin: 0; } + #sort-options .input-field { + width: 20em; + max-width: 50%; + float: right; + margin: 0; } + +#teams #header > div > select { + text-overflow: ellipsis; + color: #B84000; } +#teams .search-box { + margin: 0; } + +#restitution .detail { + background: white; + margin-right: 10px; + margin-bottom: 10px; } + #restitution .detail .document { + padding: 1px 10px; + text-align: justify; + font-size: 13px; + line-height: 1.42; } +#restitution .D3_tree { + width: 100%; + overflow: auto; + height: calc(100vh - 172px); + position: relative; } + #restitution .D3_tree .detail { + background: white; + position: sticky; + height: min-content; + width: 50%; + top: 10px; + left: calc(50% - 10px); } + #restitution .D3_tree svg { + position: absolute; + pointer-events: all; } + #restitution .D3_tree svg .nodes text { + font: 12px sans-serif; } + #restitution .D3_tree svg .nodes .bullet { + cursor: pointer; } + #restitution .D3_tree svg .nodes .bullet:hover { + r: 4px; } + #restitution .D3_tree svg .nodes .with-children text { + cursor: pointer; } + #restitution .D3_tree svg .nodes .with-children .bullet:hover { + r: 3px; } + #restitution .D3_tree svg .links { + fill: none; + stroke: black; + stroke-width: 0.5px; + stroke-opacity: 0.5; } +#restitution .D3_pie { + width: 100%; + height: calc(100vh - 172px); + position: relative; + display: grid; + grid-template-rows: 40px 1fr; + grid-template-columns: 50% 50%; } + #restitution .D3_pie svg { + pointer-events: all; } + #restitution .D3_pie svg .detailsCircle { + fill-opacity: 0.35; + fill: none; } + #restitution .D3_pie svg .detailsText { + text-anchor: middle; } +#restitution .D3_sunburst { + width: 100%; + height: calc(100vh - 172px); + overflow: auto; + display: grid; + grid-template-rows: 40px 1fr; + grid-template-columns: 50% 50%; } + #restitution .D3_sunburst svg { + position: sticky; + top: 40px; + pointer-events: all; } + #restitution .D3_sunburst svg .slices path { + stroke: none; + cursor: pointer; } +#restitution .D3_pie .switch, #restitution .D3_sunburst .switch { + padding: 9px 0; + align-self: center; + background: white; + position: sticky; + top: 0; } +#restitution .D3_pie .legend, #restitution .D3_sunburst .legend { + height: 100%; + overflow: auto; + display: flex; + flex-flow: column wrap; + align-content: flex-start; } + #restitution .D3_pie .legend > div, #restitution .D3_sunburst .legend > div { + cursor: default; + padding-right: 10px; + height: 1.4em; + overflow: hidden; + transition: height .3s ease, opacity .3s ease; } + #restitution .D3_pie .legend > div.v-enter, #restitution .D3_pie .legend > div.v-leave-to, #restitution .D3_sunburst .legend > div.v-enter, #restitution .D3_sunburst .legend > div.v-leave-to { + opacity: 0; + height: 0; } + #restitution .D3_pie .legend > div:hover, #restitution .D3_pie .legend > div.active, #restitution .D3_sunburst .legend > div:hover, #restitution .D3_sunburst .legend > div.active { + background: #eef6f6; } + #restitution .D3_pie .legend > div .square, #restitution .D3_sunburst .legend > div .square { + display: inline-block; + vertical-align: middle; + width: 1em; + height: 1em; + border: 1px solid black; + margin-right: 5px; } +#restitution #tagsRestitution { + margin: 0; + height: calc(100vh - 194px); } + #restitution #tagsRestitution > .col { + height: 100%; + margin: 0; + padding: 15px 0; + overflow: auto; } + #restitution #tagsRestitution > .col .chip { + opacity: 0.5; + padding-left: 5px; + transition: opacity 0.3s; } + #restitution #tagsRestitution > .col .chip.active { + opacity: 1; } + #restitution #tagsRestitution > .col .chip [type="checkbox"] { + display: none; } + #restitution #tagsRestitution > .col .chip [type="checkbox"] + span { + font-size: inherit; + padding-left: 25px; } + #restitution #tagsRestitution > .col .chip [type="checkbox"] + span::before, #restitution #tagsRestitution > .col .chip [type="checkbox"] + span::after { + content: ''; + position: absolute; + left: 0; + top: 0; + margin: 4px; + width: 16px; + height: 16px; + z-index: 0; + -webkit-transition: .28s ease; + transition: .28s ease; + border-radius: 50%; } + #restitution #tagsRestitution > .col .chip [type="checkbox"]:checked + span::before { + border-color: white; + transform: none; } + #restitution #tagsRestitution > .col .chip [type="checkbox"]:checked + span::after { + transform: scale(0.5); + background-color: white; } + +/*# sourceMappingURL=app.css.map */ diff --git a/src/main/webapp/assets/css/app.css.map b/src/main/webapp/assets/css/app.css.map new file mode 100644 index 0000000..d71e9a9 --- /dev/null +++ b/src/main/webapp/assets/css/app.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["../../WEB-INF/sass/_variables.scss","../../WEB-INF/sass/components/_color-classes.scss","../../WEB-INF/sass/components/_normalize.scss","../../WEB-INF/sass/components/_global.scss","../../WEB-INF/sass/components/_variables.scss","../../WEB-INF/sass/components/_badges.scss","../../WEB-INF/sass/components/_color-variables.scss","../../WEB-INF/sass/components/_icons-material-design.scss","../../WEB-INF/sass/components/_grid.scss","../../WEB-INF/sass/components/_navbar.scss","../../WEB-INF/sass/components/_typography.scss","../../WEB-INF/sass/components/_transitions.scss","../../WEB-INF/sass/components/_cards.scss","../../WEB-INF/sass/components/_toast.scss","../../WEB-INF/sass/components/_tabs.scss","../../WEB-INF/sass/components/_tooltip.scss","../../WEB-INF/sass/components/_buttons.scss","../../WEB-INF/sass/components/_dropdown.scss","../../WEB-INF/sass/components/_waves.scss","../../WEB-INF/sass/components/_modal.scss","../../WEB-INF/sass/components/_collapsible.scss","../../WEB-INF/sass/components/_chips.scss","../../WEB-INF/sass/components/_materialbox.scss","../../WEB-INF/sass/components/forms/_forms.scss","../../WEB-INF/sass/components/forms/_input-fields.scss","../../WEB-INF/sass/components/forms/_radio-buttons.scss","../../WEB-INF/sass/components/forms/_checkboxes.scss","../../WEB-INF/sass/components/forms/_switches.scss","../../WEB-INF/sass/components/forms/_select.scss","../../WEB-INF/sass/components/forms/_file-input.scss","../../WEB-INF/sass/components/forms/_range.scss","../../WEB-INF/sass/components/_table_of_contents.scss","../../WEB-INF/sass/components/_sidenav.scss","../../WEB-INF/sass/components/_preloader.scss","../../WEB-INF/sass/components/_slider.scss","../../WEB-INF/sass/components/_carousel.scss","../../WEB-INF/sass/components/_tapTarget.scss","../../WEB-INF/sass/components/_pulse.scss","../../WEB-INF/sass/components/_datepicker.scss","../../WEB-INF/sass/components/_timepicker.scss","../../WEB-INF/sass/_components.scss","../../WEB-INF/sass/app.scss"], +"names": [], +"file": "app.css" +} diff --git a/src/main/webapp/assets/css/app.min.css b/src/main/webapp/assets/css/app.min.css new file mode 100644 index 0000000..afebe58 --- /dev/null +++ b/src/main/webapp/assets/css/app.min.css @@ -0,0 +1,8 @@ +@font-face{font-family:"Seravek";src:url("../font/seravek-light-webfont.woff") format("woff");font-weight:100}@font-face{font-family:"Seravek";src:url("../font/seravek-regular-webfont.woff") format("woff");font-weight:400}@font-face{font-family:"Seravek";src:url("../font/seravek-medium-webfont.woff") format("woff");font-weight:700}@font-face{font-family:"Seravek";src:url("../font/seravek-bold-webfont.woff") format("woff");font-weight:900}@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url("../font/material-icons.woff") format("woff2")}:root{--blue-color:#4d9999;--red-color:#ba4100;--green-color:#26a96c;--grey-color:#b2b2b2}.materialize-red{background-color:#e51c23!important}.materialize-red-text{color:#e51c23!important}.materialize-red.lighten-5{background-color:#fdeaeb!important}.materialize-red-text.text-lighten-5{color:#fdeaeb!important}.materialize-red.lighten-4{background-color:#f8c1c3!important}.materialize-red-text.text-lighten-4{color:#f8c1c3!important}.materialize-red.lighten-3{background-color:#f3989b!important}.materialize-red-text.text-lighten-3{color:#f3989b!important}.materialize-red.lighten-2{background-color:#ee6e73!important}.materialize-red-text.text-lighten-2{color:#ee6e73!important}.materialize-red.lighten-1{background-color:#ea454b!important}.materialize-red-text.text-lighten-1{color:#ea454b!important}.materialize-red.darken-1{background-color:#d0181e!important}.materialize-red-text.text-darken-1{color:#d0181e!important}.materialize-red.darken-2{background-color:#b9151b!important}.materialize-red-text.text-darken-2{color:#b9151b!important}.materialize-red.darken-3{background-color:#a21318!important}.materialize-red-text.text-darken-3{color:#a21318!important}.materialize-red.darken-4{background-color:#8b1014!important}.materialize-red-text.text-darken-4{color:#8b1014!important}.red{background-color:#f44336!important}.red-text{color:#f44336!important}.red.lighten-5{background-color:#ffebee!important}.red-text.text-lighten-5{color:#ffebee!important}.red.lighten-4{background-color:#ffcdd2!important}.red-text.text-lighten-4{color:#ffcdd2!important}.red.lighten-3{background-color:#ef9a9a!important}.red-text.text-lighten-3{color:#ef9a9a!important}.red.lighten-2{background-color:#e57373!important}.red-text.text-lighten-2{color:#e57373!important}.red.lighten-1{background-color:#ef5350!important}.red-text.text-lighten-1{color:#ef5350!important}.red.darken-1{background-color:#e53935!important}.red-text.text-darken-1{color:#e53935!important}.red.darken-2{background-color:#d32f2f!important}.red-text.text-darken-2{color:#d32f2f!important}.red.darken-3{background-color:#c62828!important}.red-text.text-darken-3{color:#c62828!important}.red.darken-4{background-color:#b71c1c!important}.red-text.text-darken-4{color:#b71c1c!important}.red.accent-1{background-color:#ff8a80!important}.red-text.text-accent-1{color:#ff8a80!important}.red.accent-2{background-color:#ff5252!important}.red-text.text-accent-2{color:#ff5252!important}.red.accent-3{background-color:#ff1744!important}.red-text.text-accent-3{color:#ff1744!important}.red.accent-4{background-color:#d50000!important}.red-text.text-accent-4{color:#d50000!important}.pink{background-color:#e91e63!important}.pink-text{color:#e91e63!important}.pink.lighten-5{background-color:#fce4ec!important}.pink-text.text-lighten-5{color:#fce4ec!important}.pink.lighten-4{background-color:#f8bbd0!important}.pink-text.text-lighten-4{color:#f8bbd0!important}.pink.lighten-3{background-color:#f48fb1!important}.pink-text.text-lighten-3{color:#f48fb1!important}.pink.lighten-2{background-color:#f06292!important}.pink-text.text-lighten-2{color:#f06292!important}.pink.lighten-1{background-color:#ec407a!important}.pink-text.text-lighten-1{color:#ec407a!important}.pink.darken-1{background-color:#d81b60!important}.pink-text.text-darken-1{color:#d81b60!important}.pink.darken-2{background-color:#c2185b!important}.pink-text.text-darken-2{color:#c2185b!important}.pink.darken-3{background-color:#ad1457!important}.pink-text.text-darken-3{color:#ad1457!important}.pink.darken-4{background-color:#880e4f!important}.pink-text.text-darken-4{color:#880e4f!important}.pink.accent-1{background-color:#ff80ab!important}.pink-text.text-accent-1{color:#ff80ab!important}.pink.accent-2{background-color:#ff4081!important}.pink-text.text-accent-2{color:#ff4081!important}.pink.accent-3{background-color:#f50057!important}.pink-text.text-accent-3{color:#f50057!important}.pink.accent-4{background-color:#c51162!important}.pink-text.text-accent-4{color:#c51162!important}.purple{background-color:#9c27b0!important}.purple-text{color:#9c27b0!important}.purple.lighten-5{background-color:#f3e5f5!important}.purple-text.text-lighten-5{color:#f3e5f5!important}.purple.lighten-4{background-color:#e1bee7!important}.purple-text.text-lighten-4{color:#e1bee7!important}.purple.lighten-3{background-color:#ce93d8!important}.purple-text.text-lighten-3{color:#ce93d8!important}.purple.lighten-2{background-color:#ba68c8!important}.purple-text.text-lighten-2{color:#ba68c8!important}.purple.lighten-1{background-color:#ab47bc!important}.purple-text.text-lighten-1{color:#ab47bc!important}.purple.darken-1{background-color:#8e24aa!important}.purple-text.text-darken-1{color:#8e24aa!important}.purple.darken-2{background-color:#7b1fa2!important}.purple-text.text-darken-2{color:#7b1fa2!important}.purple.darken-3{background-color:#6a1b9a!important}.purple-text.text-darken-3{color:#6a1b9a!important}.purple.darken-4{background-color:#4a148c!important}.purple-text.text-darken-4{color:#4a148c!important}.purple.accent-1{background-color:#ea80fc!important}.purple-text.text-accent-1{color:#ea80fc!important}.purple.accent-2{background-color:#e040fb!important}.purple-text.text-accent-2{color:#e040fb!important}.purple.accent-3{background-color:#d500f9!important}.purple-text.text-accent-3{color:#d500f9!important}.purple.accent-4{background-color:#a0f!important}.purple-text.text-accent-4{color:#a0f!important}.deep-purple{background-color:#673ab7!important}.deep-purple-text{color:#673ab7!important}.deep-purple.lighten-5{background-color:#ede7f6!important}.deep-purple-text.text-lighten-5{color:#ede7f6!important}.deep-purple.lighten-4{background-color:#d1c4e9!important}.deep-purple-text.text-lighten-4{color:#d1c4e9!important}.deep-purple.lighten-3{background-color:#b39ddb!important}.deep-purple-text.text-lighten-3{color:#b39ddb!important}.deep-purple.lighten-2{background-color:#9575cd!important}.deep-purple-text.text-lighten-2{color:#9575cd!important}.deep-purple.lighten-1{background-color:#7e57c2!important}.deep-purple-text.text-lighten-1{color:#7e57c2!important}.deep-purple.darken-1{background-color:#5e35b1!important}.deep-purple-text.text-darken-1{color:#5e35b1!important}.deep-purple.darken-2{background-color:#512da8!important}.deep-purple-text.text-darken-2{color:#512da8!important}.deep-purple.darken-3{background-color:#4527a0!important}.deep-purple-text.text-darken-3{color:#4527a0!important}.deep-purple.darken-4{background-color:#311b92!important}.deep-purple-text.text-darken-4{color:#311b92!important}.deep-purple.accent-1{background-color:#b388ff!important}.deep-purple-text.text-accent-1{color:#b388ff!important}.deep-purple.accent-2{background-color:#7c4dff!important}.deep-purple-text.text-accent-2{color:#7c4dff!important}.deep-purple.accent-3{background-color:#651fff!important}.deep-purple-text.text-accent-3{color:#651fff!important}.deep-purple.accent-4{background-color:#6200ea!important}.deep-purple-text.text-accent-4{color:#6200ea!important}.indigo{background-color:#3f51b5!important}.indigo-text{color:#3f51b5!important}.indigo.lighten-5{background-color:#e8eaf6!important}.indigo-text.text-lighten-5{color:#e8eaf6!important}.indigo.lighten-4{background-color:#c5cae9!important}.indigo-text.text-lighten-4{color:#c5cae9!important}.indigo.lighten-3{background-color:#9fa8da!important}.indigo-text.text-lighten-3{color:#9fa8da!important}.indigo.lighten-2{background-color:#7986cb!important}.indigo-text.text-lighten-2{color:#7986cb!important}.indigo.lighten-1{background-color:#5c6bc0!important}.indigo-text.text-lighten-1{color:#5c6bc0!important}.indigo.darken-1{background-color:#3949ab!important}.indigo-text.text-darken-1{color:#3949ab!important}.indigo.darken-2{background-color:#303f9f!important}.indigo-text.text-darken-2{color:#303f9f!important}.indigo.darken-3{background-color:#283593!important}.indigo-text.text-darken-3{color:#283593!important}.indigo.darken-4{background-color:#1a237e!important}.indigo-text.text-darken-4{color:#1a237e!important}.indigo.accent-1{background-color:#8c9eff!important}.indigo-text.text-accent-1{color:#8c9eff!important}.indigo.accent-2{background-color:#536dfe!important}.indigo-text.text-accent-2{color:#536dfe!important}.indigo.accent-3{background-color:#3d5afe!important}.indigo-text.text-accent-3{color:#3d5afe!important}.indigo.accent-4{background-color:#304ffe!important}.indigo-text.text-accent-4{color:#304ffe!important}.blue{background-color:#2196f3!important}.blue-text{color:#2196f3!important}.blue.lighten-5{background-color:#e3f2fd!important}.blue-text.text-lighten-5{color:#e3f2fd!important}.blue.lighten-4{background-color:#bbdefb!important}.blue-text.text-lighten-4{color:#bbdefb!important}.blue.lighten-3{background-color:#90caf9!important}.blue-text.text-lighten-3{color:#90caf9!important}.blue.lighten-2{background-color:#64b5f6!important}.blue-text.text-lighten-2{color:#64b5f6!important}.blue.lighten-1{background-color:#42a5f5!important}.blue-text.text-lighten-1{color:#42a5f5!important}.blue.darken-1{background-color:#1e88e5!important}.blue-text.text-darken-1{color:#1e88e5!important}.blue.darken-2{background-color:#1976d2!important}.blue-text.text-darken-2{color:#1976d2!important}.blue.darken-3{background-color:#1565c0!important}.blue-text.text-darken-3{color:#1565c0!important}.blue.darken-4{background-color:#0d47a1!important}.blue-text.text-darken-4{color:#0d47a1!important}.blue.accent-1{background-color:#82b1ff!important}.blue-text.text-accent-1{color:#82b1ff!important}.blue.accent-2{background-color:#448aff!important}.blue-text.text-accent-2{color:#448aff!important}.blue.accent-3{background-color:#2979ff!important}.blue-text.text-accent-3{color:#2979ff!important}.blue.accent-4{background-color:#2962ff!important}.blue-text.text-accent-4{color:#2962ff!important}.light-blue{background-color:#03a9f4!important}.light-blue-text{color:#03a9f4!important}.light-blue.lighten-5{background-color:#e1f5fe!important}.light-blue-text.text-lighten-5{color:#e1f5fe!important}.light-blue.lighten-4{background-color:#b3e5fc!important}.light-blue-text.text-lighten-4{color:#b3e5fc!important}.light-blue.lighten-3{background-color:#81d4fa!important}.light-blue-text.text-lighten-3{color:#81d4fa!important}.light-blue.lighten-2{background-color:#4fc3f7!important}.light-blue-text.text-lighten-2{color:#4fc3f7!important}.light-blue.lighten-1{background-color:#29b6f6!important}.light-blue-text.text-lighten-1{color:#29b6f6!important}.light-blue.darken-1{background-color:#039be5!important}.light-blue-text.text-darken-1{color:#039be5!important}.light-blue.darken-2{background-color:#0288d1!important}.light-blue-text.text-darken-2{color:#0288d1!important}.light-blue.darken-3{background-color:#0277bd!important}.light-blue-text.text-darken-3{color:#0277bd!important}.light-blue.darken-4{background-color:#01579b!important}.light-blue-text.text-darken-4{color:#01579b!important}.light-blue.accent-1{background-color:#80d8ff!important}.light-blue-text.text-accent-1{color:#80d8ff!important}.light-blue.accent-2{background-color:#40c4ff!important}.light-blue-text.text-accent-2{color:#40c4ff!important}.light-blue.accent-3{background-color:#00b0ff!important}.light-blue-text.text-accent-3{color:#00b0ff!important}.light-blue.accent-4{background-color:#0091ea!important}.light-blue-text.text-accent-4{color:#0091ea!important}.cyan{background-color:#00bcd4!important}.cyan-text{color:#00bcd4!important}.cyan.lighten-5{background-color:#e0f7fa!important}.cyan-text.text-lighten-5{color:#e0f7fa!important}.cyan.lighten-4{background-color:#b2ebf2!important}.cyan-text.text-lighten-4{color:#b2ebf2!important}.cyan.lighten-3{background-color:#80deea!important}.cyan-text.text-lighten-3{color:#80deea!important}.cyan.lighten-2{background-color:#4dd0e1!important}.cyan-text.text-lighten-2{color:#4dd0e1!important}.cyan.lighten-1{background-color:#26c6da!important}.cyan-text.text-lighten-1{color:#26c6da!important}.cyan.darken-1{background-color:#00acc1!important}.cyan-text.text-darken-1{color:#00acc1!important}.cyan.darken-2{background-color:#0097a7!important}.cyan-text.text-darken-2{color:#0097a7!important}.cyan.darken-3{background-color:#00838f!important}.cyan-text.text-darken-3{color:#00838f!important}.cyan.darken-4{background-color:#006064!important}.cyan-text.text-darken-4{color:#006064!important}.cyan.accent-1{background-color:#84ffff!important}.cyan-text.text-accent-1{color:#84ffff!important}.cyan.accent-2{background-color:#18ffff!important}.cyan-text.text-accent-2{color:#18ffff!important}.cyan.accent-3{background-color:#00e5ff!important}.cyan-text.text-accent-3{color:#00e5ff!important}.cyan.accent-4{background-color:#00b8d4!important}.cyan-text.text-accent-4{color:#00b8d4!important}.teal{background-color:#009688!important}.teal-text{color:#009688!important}.teal.lighten-5{background-color:#e0f2f1!important}.teal-text.text-lighten-5{color:#e0f2f1!important}.teal.lighten-4{background-color:#b2dfdb!important}.teal-text.text-lighten-4{color:#b2dfdb!important}.teal.lighten-3{background-color:#80cbc4!important}.teal-text.text-lighten-3{color:#80cbc4!important}.teal.lighten-2{background-color:#4db6ac!important}.teal-text.text-lighten-2{color:#4db6ac!important}.teal.lighten-1{background-color:#26a69a!important}.teal-text.text-lighten-1{color:#26a69a!important}.teal.darken-1{background-color:#00897b!important}.teal-text.text-darken-1{color:#00897b!important}.teal.darken-2{background-color:#00796b!important}.teal-text.text-darken-2{color:#00796b!important}.teal.darken-3{background-color:#00695c!important}.teal-text.text-darken-3{color:#00695c!important}.teal.darken-4{background-color:#004d40!important}.teal-text.text-darken-4{color:#004d40!important}.teal.accent-1{background-color:#a7ffeb!important}.teal-text.text-accent-1{color:#a7ffeb!important}.teal.accent-2{background-color:#64ffda!important}.teal-text.text-accent-2{color:#64ffda!important}.teal.accent-3{background-color:#1de9b6!important}.teal-text.text-accent-3{color:#1de9b6!important}.teal.accent-4{background-color:#00bfa5!important}.teal-text.text-accent-4{color:#00bfa5!important}.green{background-color:#4caf50!important}.green-text{color:#4caf50!important}.green.lighten-5{background-color:#e8f5e9!important}.green-text.text-lighten-5{color:#e8f5e9!important}.green.lighten-4{background-color:#c8e6c9!important}.green-text.text-lighten-4{color:#c8e6c9!important}.green.lighten-3{background-color:#a5d6a7!important}.green-text.text-lighten-3{color:#a5d6a7!important}.green.lighten-2{background-color:#81c784!important}.green-text.text-lighten-2{color:#81c784!important}.green.lighten-1{background-color:#66bb6a!important}.green-text.text-lighten-1{color:#66bb6a!important}.green.darken-1{background-color:#43a047!important}.green-text.text-darken-1{color:#43a047!important}.green.darken-2{background-color:#388e3c!important}.green-text.text-darken-2{color:#388e3c!important}.green.darken-3{background-color:#2e7d32!important}.green-text.text-darken-3{color:#2e7d32!important}.green.darken-4{background-color:#1b5e20!important}.green-text.text-darken-4{color:#1b5e20!important}.green.accent-1{background-color:#b9f6ca!important}.green-text.text-accent-1{color:#b9f6ca!important}.green.accent-2{background-color:#69f0ae!important}.green-text.text-accent-2{color:#69f0ae!important}.green.accent-3{background-color:#00e676!important}.green-text.text-accent-3{color:#00e676!important}.green.accent-4{background-color:#00c853!important}.green-text.text-accent-4{color:#00c853!important}.light-green{background-color:#8bc34a!important}.light-green-text{color:#8bc34a!important}.light-green.lighten-5{background-color:#f1f8e9!important}.light-green-text.text-lighten-5{color:#f1f8e9!important}.light-green.lighten-4{background-color:#dcedc8!important}.light-green-text.text-lighten-4{color:#dcedc8!important}.light-green.lighten-3{background-color:#c5e1a5!important}.light-green-text.text-lighten-3{color:#c5e1a5!important}.light-green.lighten-2{background-color:#aed581!important}.light-green-text.text-lighten-2{color:#aed581!important}.light-green.lighten-1{background-color:#9ccc65!important}.light-green-text.text-lighten-1{color:#9ccc65!important}.light-green.darken-1{background-color:#7cb342!important}.light-green-text.text-darken-1{color:#7cb342!important}.light-green.darken-2{background-color:#689f38!important}.light-green-text.text-darken-2{color:#689f38!important}.light-green.darken-3{background-color:#558b2f!important}.light-green-text.text-darken-3{color:#558b2f!important}.light-green.darken-4{background-color:#33691e!important}.light-green-text.text-darken-4{color:#33691e!important}.light-green.accent-1{background-color:#ccff90!important}.light-green-text.text-accent-1{color:#ccff90!important}.light-green.accent-2{background-color:#b2ff59!important}.light-green-text.text-accent-2{color:#b2ff59!important}.light-green.accent-3{background-color:#76ff03!important}.light-green-text.text-accent-3{color:#76ff03!important}.light-green.accent-4{background-color:#64dd17!important}.light-green-text.text-accent-4{color:#64dd17!important}.lime{background-color:#cddc39!important}.lime-text{color:#cddc39!important}.lime.lighten-5{background-color:#f9fbe7!important}.lime-text.text-lighten-5{color:#f9fbe7!important}.lime.lighten-4{background-color:#f0f4c3!important}.lime-text.text-lighten-4{color:#f0f4c3!important}.lime.lighten-3{background-color:#e6ee9c!important}.lime-text.text-lighten-3{color:#e6ee9c!important}.lime.lighten-2{background-color:#dce775!important}.lime-text.text-lighten-2{color:#dce775!important}.lime.lighten-1{background-color:#d4e157!important}.lime-text.text-lighten-1{color:#d4e157!important}.lime.darken-1{background-color:#c0ca33!important}.lime-text.text-darken-1{color:#c0ca33!important}.lime.darken-2{background-color:#afb42b!important}.lime-text.text-darken-2{color:#afb42b!important}.lime.darken-3{background-color:#9e9d24!important}.lime-text.text-darken-3{color:#9e9d24!important}.lime.darken-4{background-color:#827717!important}.lime-text.text-darken-4{color:#827717!important}.lime.accent-1{background-color:#f4ff81!important}.lime-text.text-accent-1{color:#f4ff81!important}.lime.accent-2{background-color:#eeff41!important}.lime-text.text-accent-2{color:#eeff41!important}.lime.accent-3{background-color:#c6ff00!important}.lime-text.text-accent-3{color:#c6ff00!important}.lime.accent-4{background-color:#aeea00!important}.lime-text.text-accent-4{color:#aeea00!important}.yellow{background-color:#ffeb3b!important}.yellow-text{color:#ffeb3b!important}.yellow.lighten-5{background-color:#fffde7!important}.yellow-text.text-lighten-5{color:#fffde7!important}.yellow.lighten-4{background-color:#fff9c4!important}.yellow-text.text-lighten-4{color:#fff9c4!important}.yellow.lighten-3{background-color:#fff59d!important}.yellow-text.text-lighten-3{color:#fff59d!important}.yellow.lighten-2{background-color:#fff176!important}.yellow-text.text-lighten-2{color:#fff176!important}.yellow.lighten-1{background-color:#ffee58!important}.yellow-text.text-lighten-1{color:#ffee58!important}.yellow.darken-1{background-color:#fdd835!important}.yellow-text.text-darken-1{color:#fdd835!important}.yellow.darken-2{background-color:#fbc02d!important}.yellow-text.text-darken-2{color:#fbc02d!important}.yellow.darken-3{background-color:#f9a825!important}.yellow-text.text-darken-3{color:#f9a825!important}.yellow.darken-4{background-color:#f57f17!important}.yellow-text.text-darken-4{color:#f57f17!important}.yellow.accent-1{background-color:#ffff8d!important}.yellow-text.text-accent-1{color:#ffff8d!important}.yellow.accent-2{background-color:#ff0!important}.yellow-text.text-accent-2{color:#ff0!important}.yellow.accent-3{background-color:#ffea00!important}.yellow-text.text-accent-3{color:#ffea00!important}.yellow.accent-4{background-color:#ffd600!important}.yellow-text.text-accent-4{color:#ffd600!important}.amber{background-color:#ffc107!important}.amber-text{color:#ffc107!important}.amber.lighten-5{background-color:#fff8e1!important}.amber-text.text-lighten-5{color:#fff8e1!important}.amber.lighten-4{background-color:#ffecb3!important}.amber-text.text-lighten-4{color:#ffecb3!important}.amber.lighten-3{background-color:#ffe082!important}.amber-text.text-lighten-3{color:#ffe082!important}.amber.lighten-2{background-color:#ffd54f!important}.amber-text.text-lighten-2{color:#ffd54f!important}.amber.lighten-1{background-color:#ffca28!important}.amber-text.text-lighten-1{color:#ffca28!important}.amber.darken-1{background-color:#ffb300!important}.amber-text.text-darken-1{color:#ffb300!important}.amber.darken-2{background-color:#ffa000!important}.amber-text.text-darken-2{color:#ffa000!important}.amber.darken-3{background-color:#ff8f00!important}.amber-text.text-darken-3{color:#ff8f00!important}.amber.darken-4{background-color:#ff6f00!important}.amber-text.text-darken-4{color:#ff6f00!important}.amber.accent-1{background-color:#ffe57f!important}.amber-text.text-accent-1{color:#ffe57f!important}.amber.accent-2{background-color:#ffd740!important}.amber-text.text-accent-2{color:#ffd740!important}.amber.accent-3{background-color:#ffc400!important}.amber-text.text-accent-3{color:#ffc400!important}.amber.accent-4{background-color:#ffab00!important}.amber-text.text-accent-4{color:#ffab00!important}.orange{background-color:#ff9800!important}.orange-text{color:#ff9800!important}.orange.lighten-5{background-color:#fff3e0!important}.orange-text.text-lighten-5{color:#fff3e0!important}.orange.lighten-4{background-color:#ffe0b2!important}.orange-text.text-lighten-4{color:#ffe0b2!important}.orange.lighten-3{background-color:#ffcc80!important}.orange-text.text-lighten-3{color:#ffcc80!important}.orange.lighten-2{background-color:#ffb74d!important}.orange-text.text-lighten-2{color:#ffb74d!important}.orange.lighten-1{background-color:#ffa726!important}.orange-text.text-lighten-1{color:#ffa726!important}.orange.darken-1{background-color:#fb8c00!important}.orange-text.text-darken-1{color:#fb8c00!important}.orange.darken-2{background-color:#f57c00!important}.orange-text.text-darken-2{color:#f57c00!important}.orange.darken-3{background-color:#ef6c00!important}.orange-text.text-darken-3{color:#ef6c00!important}.orange.darken-4{background-color:#e65100!important}.orange-text.text-darken-4{color:#e65100!important}.orange.accent-1{background-color:#ffd180!important}.orange-text.text-accent-1{color:#ffd180!important}.orange.accent-2{background-color:#ffab40!important}.orange-text.text-accent-2{color:#ffab40!important}.orange.accent-3{background-color:#ff9100!important}.orange-text.text-accent-3{color:#ff9100!important}.orange.accent-4{background-color:#ff6d00!important}.orange-text.text-accent-4{color:#ff6d00!important}.deep-orange{background-color:#ff5722!important}.deep-orange-text{color:#ff5722!important}.deep-orange.lighten-5{background-color:#fbe9e7!important}.deep-orange-text.text-lighten-5{color:#fbe9e7!important}.deep-orange.lighten-4{background-color:#ffccbc!important}.deep-orange-text.text-lighten-4{color:#ffccbc!important}.deep-orange.lighten-3{background-color:#ffab91!important}.deep-orange-text.text-lighten-3{color:#ffab91!important}.deep-orange.lighten-2{background-color:#ff8a65!important}.deep-orange-text.text-lighten-2{color:#ff8a65!important}.deep-orange.lighten-1{background-color:#ff7043!important}.deep-orange-text.text-lighten-1{color:#ff7043!important}.deep-orange.darken-1{background-color:#f4511e!important}.deep-orange-text.text-darken-1{color:#f4511e!important}.deep-orange.darken-2{background-color:#e64a19!important}.deep-orange-text.text-darken-2{color:#e64a19!important}.deep-orange.darken-3{background-color:#d84315!important}.deep-orange-text.text-darken-3{color:#d84315!important}.deep-orange.darken-4{background-color:#bf360c!important}.deep-orange-text.text-darken-4{color:#bf360c!important}.deep-orange.accent-1{background-color:#ff9e80!important}.deep-orange-text.text-accent-1{color:#ff9e80!important}.deep-orange.accent-2{background-color:#ff6e40!important}.deep-orange-text.text-accent-2{color:#ff6e40!important}.deep-orange.accent-3{background-color:#ff3d00!important}.deep-orange-text.text-accent-3{color:#ff3d00!important}.deep-orange.accent-4{background-color:#dd2c00!important}.deep-orange-text.text-accent-4{color:#dd2c00!important}.brown{background-color:#795548!important}.brown-text{color:#795548!important}.brown.lighten-5{background-color:#efebe9!important}.brown-text.text-lighten-5{color:#efebe9!important}.brown.lighten-4{background-color:#d7ccc8!important}.brown-text.text-lighten-4{color:#d7ccc8!important}.brown.lighten-3{background-color:#bcaaa4!important}.brown-text.text-lighten-3{color:#bcaaa4!important}.brown.lighten-2{background-color:#a1887f!important}.brown-text.text-lighten-2{color:#a1887f!important}.brown.lighten-1{background-color:#8d6e63!important}.brown-text.text-lighten-1{color:#8d6e63!important}.brown.darken-1{background-color:#6d4c41!important}.brown-text.text-darken-1{color:#6d4c41!important}.brown.darken-2{background-color:#5d4037!important}.brown-text.text-darken-2{color:#5d4037!important}.brown.darken-3{background-color:#4e342e!important}.brown-text.text-darken-3{color:#4e342e!important}.brown.darken-4{background-color:#3e2723!important}.brown-text.text-darken-4{color:#3e2723!important}.blue-grey{background-color:#607d8b!important}.blue-grey-text{color:#607d8b!important}.blue-grey.lighten-5{background-color:#eceff1!important}.blue-grey-text.text-lighten-5{color:#eceff1!important}.blue-grey.lighten-4{background-color:#cfd8dc!important}.blue-grey-text.text-lighten-4{color:#cfd8dc!important}.blue-grey.lighten-3{background-color:#b0bec5!important}.blue-grey-text.text-lighten-3{color:#b0bec5!important}.blue-grey.lighten-2{background-color:#90a4ae!important}.blue-grey-text.text-lighten-2{color:#90a4ae!important}.blue-grey.lighten-1{background-color:#78909c!important}.blue-grey-text.text-lighten-1{color:#78909c!important}.blue-grey.darken-1{background-color:#546e7a!important}.blue-grey-text.text-darken-1{color:#546e7a!important}.blue-grey.darken-2{background-color:#455a64!important}.blue-grey-text.text-darken-2{color:#455a64!important}.blue-grey.darken-3{background-color:#37474f!important}.blue-grey-text.text-darken-3{color:#37474f!important}.blue-grey.darken-4{background-color:#263238!important}.blue-grey-text.text-darken-4{color:#263238!important}.grey{background-color:#9e9e9e!important}.grey-text{color:#9e9e9e!important}.grey.lighten-5{background-color:#fafafa!important}.grey-text.text-lighten-5{color:#fafafa!important}.grey.lighten-4{background-color:#f5f5f5!important}.grey-text.text-lighten-4{color:#f5f5f5!important}.grey.lighten-3{background-color:#eee!important}.grey-text.text-lighten-3{color:#eee!important}.grey.lighten-2{background-color:#e0e0e0!important}.grey-text.text-lighten-2{color:#e0e0e0!important}.grey.lighten-1{background-color:#bdbdbd!important}.grey-text.text-lighten-1{color:#bdbdbd!important}.grey.darken-1{background-color:#757575!important}.grey-text.text-darken-1{color:#757575!important}.grey.darken-2{background-color:#616161!important}.grey-text.text-darken-2{color:#616161!important}.grey.darken-3{background-color:#424242!important}.grey-text.text-darken-3{color:#424242!important}.grey.darken-4{background-color:#212121!important}.grey-text.text-darken-4{color:#212121!important}.black{background-color:#000!important}.black-text{color:#000!important}.white{background-color:#fff!important}.white-text{color:#fff!important}.transparent{background-color:transparent!important}.transparent-text{color:transparent!important}/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:0;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}button,input,optgroup,select,textarea{font-family:Seravek,Helvetica,Roboto,Arial,sans-serif}ul:not(.browser-default){padding-left:0;list-style-type:none}ul:not(.browser-default)>li{list-style-type:none}a{color:#336362;text-decoration:none;-webkit-tap-highlight-color:transparent}.valign-wrapper{display:flex;align-items:center}.clearfix{clear:both}.z-depth-0{box-shadow:none!important}.z-depth-1,nav,.card-panel,.card,.toast,.btn,.btn-large,.btn-small,.btn-floating,.dropdown-content,.collapsible,.sidenav{box-shadow:0 2px 2px 0 rgba(0,0,0,0.14),0 3px 1px -2px rgba(0,0,0,0.12),0 1px 5px 0 rgba(0,0,0,0.2)}.z-depth-1-half,.btn:hover,.btn-large:hover,.btn-small:hover,.btn-floating:hover{box-shadow:0 3px 3px 0 rgba(0,0,0,0.14),0 1px 7px 0 rgba(0,0,0,0.12),0 3px 1px -1px rgba(0,0,0,0.2)}.z-depth-2{box-shadow:0 4px 5px 0 rgba(0,0,0,0.14),0 1px 10px 0 rgba(0,0,0,0.12),0 2px 4px -1px rgba(0,0,0,0.3)}.z-depth-3{box-shadow:0 8px 17px 2px rgba(0,0,0,0.14),0 3px 14px 2px rgba(0,0,0,0.12),0 5px 5px -3px rgba(0,0,0,0.2)}.z-depth-4{box-shadow:0 16px 24px 2px rgba(0,0,0,0.14),0 6px 30px 5px rgba(0,0,0,0.12),0 8px 10px -7px rgba(0,0,0,0.2)}.z-depth-5,.modal{box-shadow:0 24px 38px 3px rgba(0,0,0,0.14),0 9px 46px 8px rgba(0,0,0,0.12),0 11px 15px -7px rgba(0,0,0,0.2)}.hoverable{transition:box-shadow .25s}.hoverable:hover{box-shadow:0 8px 17px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}.divider{height:1px;overflow:hidden;background-color:#e0e0e0}blockquote{margin:20px 0;padding-left:1.5rem;border-left:5px solid #b84000}i{line-height:inherit}i.left{float:left;margin-right:15px}i.right{float:right;margin-left:15px}i.tiny{font-size:1rem}i.small{font-size:2rem}i.medium{font-size:4rem}i.large{font-size:6rem}img.responsive-img,video.responsive-video{max-width:100%;height:auto}.pagination li{display:inline-block;border-radius:2px;text-align:center;vertical-align:top;height:30px}.pagination li a{color:#444;display:inline-block;font-size:1.2rem;padding:0 10px;line-height:30px}.pagination li.active a{color:#fff}.pagination li.active{background-color:#b84000}.pagination li.disabled a{cursor:default;color:#999}.pagination li i{font-size:2rem}.pagination li.pages ul li{display:inline-block;float:none}@media only screen and (max-width:992px){.pagination{width:100%}.pagination li.prev,.pagination li.next{width:10%}.pagination li.pages{width:80%;overflow:hidden;white-space:nowrap}}.breadcrumb{font-size:18px;color:rgba(255,255,255,0.7)}.breadcrumb i,.breadcrumb [class^="mdi-"],.breadcrumb [class*="mdi-"],.breadcrumb i.material-icons{display:inline-block;float:left;font-size:24px}.breadcrumb:before{content:'\E5CC';color:rgba(255,255,255,0.7);vertical-align:top;display:inline-block;font-family:'Material Icons';font-weight:normal;font-style:normal;font-size:25px;margin:0 10px 0 8px;-webkit-font-smoothing:antialiased}.breadcrumb:first-child:before{display:none}.breadcrumb:last-child{color:#fff}.parallax-container{position:relative;overflow:hidden;height:500px}.parallax-container .parallax{position:absolute;top:0;left:0;right:0;bottom:0;z-index:-1}.parallax-container .parallax img{opacity:0;position:absolute;left:50%;bottom:0;min-width:100%;min-height:100%;transform:translate3d(0,0,0);transform:translateX(-50%)}.pin-top,.pin-bottom{position:relative}.pinned{position:fixed!important}ul.staggered-list li{opacity:0}.fade-in{opacity:0;transform-origin:0 50%}@media only screen and (max-width:600px){.hide-on-small-only,.hide-on-small-and-down{display:none!important}}@media only screen and (max-width:992px){.hide-on-med-and-down{display:none!important}}@media only screen and (min-width:601px){.hide-on-med-and-up{display:none!important}}@media only screen and (min-width:600px) and (max-width:992px){.hide-on-med-only{display:none!important}}@media only screen and (min-width:993px){.hide-on-large-only{display:none!important}}@media only screen and (min-width:1201px){.hide-on-extra-large-only{display:none!important}}@media only screen and (min-width:1201px){.show-on-extra-large{display:block!important}}@media only screen and (min-width:993px){.show-on-large{display:block!important}}@media only screen and (min-width:600px) and (max-width:992px){.show-on-medium{display:block!important}}@media only screen and (max-width:600px){.show-on-small{display:block!important}}@media only screen and (min-width:601px){.show-on-medium-and-up{display:block!important}}@media only screen and (max-width:992px){.show-on-medium-and-down{display:block!important}}@media only screen and (max-width:600px){.center-on-small-only{text-align:center}}.page-footer{padding-top:20px;color:#fff;background-color:#b84000}.page-footer .footer-copyright{overflow:hidden;min-height:50px;display:flex;align-items:center;justify-content:space-between;padding:10px 0;color:rgba(255,255,255,0.8);background-color:rgba(51,51,51,0.08)}table,th,td{border:0}table{width:100%;display:table;border-collapse:collapse;border-spacing:0}table.striped tr{border-bottom:0}table.striped>tbody>tr:nth-child(odd){background-color:rgba(242,242,242,0.5)}table.striped>tbody>tr>td{border-radius:0}table.highlight>tbody>tr{transition:background-color .25s ease}table.highlight>tbody>tr:hover{background-color:rgba(242,242,242,0.5)}table.centered thead tr th,table.centered tbody tr td{text-align:center}tr{border-bottom:1px solid rgba(0,0,0,0.12)}td,th{padding:15px 5px;display:table-cell;text-align:left;vertical-align:middle;border-radius:2px}@media only screen and (max-width:992px){table.responsive-table{width:100%;border-collapse:collapse;border-spacing:0;display:block;position:relative}table.responsive-table td:empty:before{content:'\00a0'}table.responsive-table th,table.responsive-table td{margin:0;vertical-align:top}table.responsive-table th{text-align:left}table.responsive-table thead{display:block;float:left}table.responsive-table thead tr{display:block;padding:0 10px 0 0}table.responsive-table thead tr th::before{content:"\00a0"}table.responsive-table tbody{display:block;width:auto;position:relative;overflow-x:auto;white-space:nowrap}table.responsive-table tbody tr{display:inline-block;vertical-align:top}table.responsive-table th{display:block;text-align:right}table.responsive-table td{display:block;min-height:1.25em;text-align:left}table.responsive-table tr{border-bottom:0;padding:0 10px}table.responsive-table thead{border:0;border-right:1px solid rgba(0,0,0,0.12)}}.collection{margin:.5rem 0 1rem 0;border:1px solid #e0e0e0;border-radius:2px;overflow:hidden;position:relative}.collection .collection-item{background-color:#fff;line-height:1.5rem;padding:10px 20px;margin:0;border-bottom:1px solid #e0e0e0}.collection .collection-item.avatar{min-height:84px;padding-left:72px;position:relative}.collection .collection-item.avatar:not(.circle-clipper)>.circle,.collection .collection-item.avatar :not(.circle-clipper)>.circle{position:absolute;width:42px;height:42px;overflow:hidden;left:15px;display:inline-block;vertical-align:middle}.collection .collection-item.avatar i.circle{font-size:18px;line-height:42px;color:#fff;background-color:#999;text-align:center}.collection .collection-item.avatar .title{font-size:16px}.collection .collection-item.avatar p{margin:0}.collection .collection-item.avatar .secondary-content{position:absolute;top:16px;right:16px}.collection .collection-item:last-child{border-bottom:0}.collection .collection-item.active{background-color:#4d9999;color:white}.collection .collection-item.active .secondary-content{color:#fff}.collection a.collection-item{display:block;transition:.25s;color:#4d9999}.collection a.collection-item:not(.active):hover{background-color:#ddd}.collection.with-header .collection-header{background-color:#fff;border-bottom:1px solid #e0e0e0;padding:10px 20px}.collection.with-header .collection-item{padding-left:30px}.collection.with-header .collection-item.avatar{padding-left:72px}.secondary-content{float:right;color:#4d9999}.collapsible .collection{margin:0;border:0}.video-container{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}.video-container iframe,.video-container object,.video-container embed{position:absolute;top:0;left:0;width:100%;height:100%}.progress{position:relative;height:4px;display:block;width:100%;background-color:#cce6e6;border-radius:2px;margin:.5rem 0 1rem 0;overflow:hidden}.progress .determinate{position:absolute;top:0;left:0;bottom:0;background-color:#4d9999;transition:width .3s linear}.progress .indeterminate{background-color:#4d9999}.progress .indeterminate:before{content:'';position:absolute;background-color:inherit;top:0;left:0;bottom:0;will-change:left,right;animation:indeterminate 2.1s cubic-bezier(0.65,0.815,0.735,0.395) infinite}.progress .indeterminate:after{content:'';position:absolute;background-color:inherit;top:0;left:0;bottom:0;will-change:left,right;animation:indeterminate-short 2.1s cubic-bezier(0.165,0.84,0.44,1) infinite;animation-delay:1.15s}@keyframes indeterminate{0%{left:-35%;right:100%}60%{left:100%;right:-90%}100%{left:100%;right:-90%}}@keyframes indeterminate-short{0%{left:-200%;right:100%}60%{left:107%;right:-8%}100%{left:107%;right:-8%}}.hide{display:none!important}.left-align{text-align:left}.right-align{text-align:right}.center,.center-align{text-align:center}.left{float:left!important}.right{float:right!important}.no-select,input[type=range],input[type=range]+.thumb{user-select:none}.circle{border-radius:50%}.center-block{display:block;margin-left:auto;margin-right:auto}.truncate{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.no-padding{padding:0!important}span.badge{min-width:3rem;padding:0 6px;margin-left:14px;text-align:center;font-size:1rem;line-height:22px;height:22px;color:#757575;float:right;box-sizing:border-box}span.badge.new{font-weight:300;font-size:.8rem;color:#fff;background-color:#4d9999;border-radius:2px}span.badge.new:after{content:" new"}span.badge[data-badge-caption]::after{content:" " attr(data-badge-caption)}nav ul a span.badge{display:inline-block;float:none;margin-left:4px;line-height:22px;height:22px;-webkit-font-smoothing:auto}.collection-item span.badge{margin-top:calc(0.75rem - 11px)}.collapsible span.badge{margin-left:auto}.sidenav span.badge{margin-top:calc(24px - 11px)}table span.badge{display:inline-block;float:none;margin-left:auto}.material-icons{text-rendering:optimizeLegibility;font-feature-settings:'liga'}.container{margin:0 auto;max-width:1280px;width:90%}@media only screen and (min-width:601px){.container{width:85%}}@media only screen and (min-width:993px){.container{width:70%}}.col .row{margin-left:-0.75rem;margin-right:-0.75rem}.section{padding-top:1rem;padding-bottom:1rem}.section.no-pad{padding:0}.section.no-pad-bot{padding-bottom:0}.section.no-pad-top{padding-top:0}.row{margin-left:auto;margin-right:auto;margin-bottom:20px}.row:after{content:"";display:table;clear:both}.row .col{float:left;box-sizing:border-box;padding:0 .75rem;min-height:1px}.row .col[class*="push-"],.row .col[class*="pull-"]{position:relative}.row .col.s1{width:8.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.s2{width:16.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.s3{width:25%;margin-left:auto;left:auto;right:auto}.row .col.s4{width:33.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.s5{width:41.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.s6{width:50%;margin-left:auto;left:auto;right:auto}.row .col.s7{width:58.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.s8{width:66.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.s9{width:75%;margin-left:auto;left:auto;right:auto}.row .col.s10{width:83.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.s11{width:91.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.s12{width:100%;margin-left:auto;left:auto;right:auto}.row .col.offset-s1{margin-left:8.3333333333%}.row .col.pull-s1{right:8.3333333333%}.row .col.push-s1{left:8.3333333333%}.row .col.offset-s2{margin-left:16.6666666667%}.row .col.pull-s2{right:16.6666666667%}.row .col.push-s2{left:16.6666666667%}.row .col.offset-s3{margin-left:25%}.row .col.pull-s3{right:25%}.row .col.push-s3{left:25%}.row .col.offset-s4{margin-left:33.3333333333%}.row .col.pull-s4{right:33.3333333333%}.row .col.push-s4{left:33.3333333333%}.row .col.offset-s5{margin-left:41.6666666667%}.row .col.pull-s5{right:41.6666666667%}.row .col.push-s5{left:41.6666666667%}.row .col.offset-s6{margin-left:50%}.row .col.pull-s6{right:50%}.row .col.push-s6{left:50%}.row .col.offset-s7{margin-left:58.3333333333%}.row .col.pull-s7{right:58.3333333333%}.row .col.push-s7{left:58.3333333333%}.row .col.offset-s8{margin-left:66.6666666667%}.row .col.pull-s8{right:66.6666666667%}.row .col.push-s8{left:66.6666666667%}.row .col.offset-s9{margin-left:75%}.row .col.pull-s9{right:75%}.row .col.push-s9{left:75%}.row .col.offset-s10{margin-left:83.3333333333%}.row .col.pull-s10{right:83.3333333333%}.row .col.push-s10{left:83.3333333333%}.row .col.offset-s11{margin-left:91.6666666667%}.row .col.pull-s11{right:91.6666666667%}.row .col.push-s11{left:91.6666666667%}.row .col.offset-s12{margin-left:100%}.row .col.pull-s12{right:100%}.row .col.push-s12{left:100%}@media only screen and (min-width:601px){.row .col.m1{width:8.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.m2{width:16.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.m3{width:25%;margin-left:auto;left:auto;right:auto}.row .col.m4{width:33.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.m5{width:41.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.m6{width:50%;margin-left:auto;left:auto;right:auto}.row .col.m7{width:58.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.m8{width:66.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.m9{width:75%;margin-left:auto;left:auto;right:auto}.row .col.m10{width:83.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.m11{width:91.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.m12{width:100%;margin-left:auto;left:auto;right:auto}.row .col.offset-m1{margin-left:8.3333333333%}.row .col.pull-m1{right:8.3333333333%}.row .col.push-m1{left:8.3333333333%}.row .col.offset-m2{margin-left:16.6666666667%}.row .col.pull-m2{right:16.6666666667%}.row .col.push-m2{left:16.6666666667%}.row .col.offset-m3{margin-left:25%}.row .col.pull-m3{right:25%}.row .col.push-m3{left:25%}.row .col.offset-m4{margin-left:33.3333333333%}.row .col.pull-m4{right:33.3333333333%}.row .col.push-m4{left:33.3333333333%}.row .col.offset-m5{margin-left:41.6666666667%}.row .col.pull-m5{right:41.6666666667%}.row .col.push-m5{left:41.6666666667%}.row .col.offset-m6{margin-left:50%}.row .col.pull-m6{right:50%}.row .col.push-m6{left:50%}.row .col.offset-m7{margin-left:58.3333333333%}.row .col.pull-m7{right:58.3333333333%}.row .col.push-m7{left:58.3333333333%}.row .col.offset-m8{margin-left:66.6666666667%}.row .col.pull-m8{right:66.6666666667%}.row .col.push-m8{left:66.6666666667%}.row .col.offset-m9{margin-left:75%}.row .col.pull-m9{right:75%}.row .col.push-m9{left:75%}.row .col.offset-m10{margin-left:83.3333333333%}.row .col.pull-m10{right:83.3333333333%}.row .col.push-m10{left:83.3333333333%}.row .col.offset-m11{margin-left:91.6666666667%}.row .col.pull-m11{right:91.6666666667%}.row .col.push-m11{left:91.6666666667%}.row .col.offset-m12{margin-left:100%}.row .col.pull-m12{right:100%}.row .col.push-m12{left:100%}}@media only screen and (min-width:993px){.row .col.l1{width:8.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.l2{width:16.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.l3{width:25%;margin-left:auto;left:auto;right:auto}.row .col.l4{width:33.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.l5{width:41.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.l6{width:50%;margin-left:auto;left:auto;right:auto}.row .col.l7{width:58.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.l8{width:66.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.l9{width:75%;margin-left:auto;left:auto;right:auto}.row .col.l10{width:83.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.l11{width:91.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.l12{width:100%;margin-left:auto;left:auto;right:auto}.row .col.offset-l1{margin-left:8.3333333333%}.row .col.pull-l1{right:8.3333333333%}.row .col.push-l1{left:8.3333333333%}.row .col.offset-l2{margin-left:16.6666666667%}.row .col.pull-l2{right:16.6666666667%}.row .col.push-l2{left:16.6666666667%}.row .col.offset-l3{margin-left:25%}.row .col.pull-l3{right:25%}.row .col.push-l3{left:25%}.row .col.offset-l4{margin-left:33.3333333333%}.row .col.pull-l4{right:33.3333333333%}.row .col.push-l4{left:33.3333333333%}.row .col.offset-l5{margin-left:41.6666666667%}.row .col.pull-l5{right:41.6666666667%}.row .col.push-l5{left:41.6666666667%}.row .col.offset-l6{margin-left:50%}.row .col.pull-l6{right:50%}.row .col.push-l6{left:50%}.row .col.offset-l7{margin-left:58.3333333333%}.row .col.pull-l7{right:58.3333333333%}.row .col.push-l7{left:58.3333333333%}.row .col.offset-l8{margin-left:66.6666666667%}.row .col.pull-l8{right:66.6666666667%}.row .col.push-l8{left:66.6666666667%}.row .col.offset-l9{margin-left:75%}.row .col.pull-l9{right:75%}.row .col.push-l9{left:75%}.row .col.offset-l10{margin-left:83.3333333333%}.row .col.pull-l10{right:83.3333333333%}.row .col.push-l10{left:83.3333333333%}.row .col.offset-l11{margin-left:91.6666666667%}.row .col.pull-l11{right:91.6666666667%}.row .col.push-l11{left:91.6666666667%}.row .col.offset-l12{margin-left:100%}.row .col.pull-l12{right:100%}.row .col.push-l12{left:100%}}@media only screen and (min-width:1201px){.row .col.xl1{width:8.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.xl2{width:16.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.xl3{width:25%;margin-left:auto;left:auto;right:auto}.row .col.xl4{width:33.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.xl5{width:41.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.xl6{width:50%;margin-left:auto;left:auto;right:auto}.row .col.xl7{width:58.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.xl8{width:66.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.xl9{width:75%;margin-left:auto;left:auto;right:auto}.row .col.xl10{width:83.3333333333%;margin-left:auto;left:auto;right:auto}.row .col.xl11{width:91.6666666667%;margin-left:auto;left:auto;right:auto}.row .col.xl12{width:100%;margin-left:auto;left:auto;right:auto}.row .col.offset-xl1{margin-left:8.3333333333%}.row .col.pull-xl1{right:8.3333333333%}.row .col.push-xl1{left:8.3333333333%}.row .col.offset-xl2{margin-left:16.6666666667%}.row .col.pull-xl2{right:16.6666666667%}.row .col.push-xl2{left:16.6666666667%}.row .col.offset-xl3{margin-left:25%}.row .col.pull-xl3{right:25%}.row .col.push-xl3{left:25%}.row .col.offset-xl4{margin-left:33.3333333333%}.row .col.pull-xl4{right:33.3333333333%}.row .col.push-xl4{left:33.3333333333%}.row .col.offset-xl5{margin-left:41.6666666667%}.row .col.pull-xl5{right:41.6666666667%}.row .col.push-xl5{left:41.6666666667%}.row .col.offset-xl6{margin-left:50%}.row .col.pull-xl6{right:50%}.row .col.push-xl6{left:50%}.row .col.offset-xl7{margin-left:58.3333333333%}.row .col.pull-xl7{right:58.3333333333%}.row .col.push-xl7{left:58.3333333333%}.row .col.offset-xl8{margin-left:66.6666666667%}.row .col.pull-xl8{right:66.6666666667%}.row .col.push-xl8{left:66.6666666667%}.row .col.offset-xl9{margin-left:75%}.row .col.pull-xl9{right:75%}.row .col.push-xl9{left:75%}.row .col.offset-xl10{margin-left:83.3333333333%}.row .col.pull-xl10{right:83.3333333333%}.row .col.push-xl10{left:83.3333333333%}.row .col.offset-xl11{margin-left:91.6666666667%}.row .col.pull-xl11{right:91.6666666667%}.row .col.push-xl11{left:91.6666666667%}.row .col.offset-xl12{margin-left:100%}.row .col.pull-xl12{right:100%}.row .col.push-xl12{left:100%}}nav{color:#fff;background-color:#b84000;width:100%;height:56px;line-height:56px}nav.nav-extended{height:auto}nav.nav-extended .nav-wrapper{min-height:56px;height:auto}nav.nav-extended .nav-content{position:relative;line-height:normal}nav a{color:#fff}nav i,nav [class^="mdi-"],nav [class*="mdi-"],nav i.material-icons{display:block;font-size:24px;height:56px;line-height:56px}nav .nav-wrapper{position:relative;height:100%}@media only screen and (min-width:993px){nav a.sidenav-trigger{display:none}}nav .sidenav-trigger{float:left;position:relative;z-index:1;height:56px;margin:0 18px}nav .sidenav-trigger i{height:56px;line-height:56px}nav .brand-logo{position:absolute;color:#fff;display:inline-block;font-size:2.1rem;padding:0}nav .brand-logo.center{left:50%;transform:translateX(-50%)}@media only screen and (max-width:992px){nav .brand-logo{left:50%;transform:translateX(-50%)}nav .brand-logo.left,nav .brand-logo.right{padding:0;transform:none}nav .brand-logo.left{left:.5rem}nav .brand-logo.right{right:.5rem;left:auto}}nav .brand-logo.right{right:.5rem;padding:0}nav .brand-logo i,nav .brand-logo [class^="mdi-"],nav .brand-logo [class*="mdi-"],nav .brand-logo i.material-icons{float:left;margin-right:15px}nav .nav-title{display:inline-block;font-size:32px;padding:28px 0}nav ul{margin:0}nav ul li{transition:background-color .3s;float:left;padding:0}nav ul li.active{background-color:rgba(0,0,0,0.1)}nav ul a{transition:background-color .3s;font-size:1rem;color:#fff;display:block;padding:0 15px;cursor:pointer}nav ul a.btn,nav ul a.btn-large,nav ul a.btn-small,nav ul a.btn-large,nav ul a.btn-flat,nav ul a.btn-floating{margin-top:-2px;margin-left:15px;margin-right:15px}nav ul a.btn>.material-icons,nav ul a.btn-large>.material-icons,nav ul a.btn-small>.material-icons,nav ul a.btn-large>.material-icons,nav ul a.btn-flat>.material-icons,nav ul a.btn-floating>.material-icons{height:inherit;line-height:inherit}nav ul a:hover{background-color:rgba(0,0,0,0.1)}nav ul.left{float:left}nav form{height:100%}nav .input-field{margin:0;height:100%}nav .input-field input{height:100%;font-size:1.2rem;border:0;padding-left:2rem}nav .input-field input:focus,nav .input-field input[type=text]:valid,nav .input-field input[type=password]:valid,nav .input-field input[type=email]:valid,nav .input-field input[type=url]:valid,nav .input-field input[type=date]:valid{border:0;box-shadow:none}nav .input-field label{top:0;left:0}nav .input-field label i{color:rgba(255,255,255,0.7);transition:color .3s}nav .input-field label.active i{color:#fff}.navbar-fixed{position:relative;height:56px;z-index:997}.navbar-fixed nav{position:fixed}@media only screen and (min-width:601px){nav.nav-extended .nav-wrapper{min-height:64px}nav,nav .nav-wrapper i,nav a.sidenav-trigger,nav a.sidenav-trigger i{height:64px;line-height:64px}.navbar-fixed{height:64px}}a{text-decoration:none}html{line-height:1.5;font-family:Seravek,Helvetica,Roboto,Arial,sans-serif;font-weight:normal;color:rgba(0,0,0,0.87)}@media only screen and (min-width:0){html{font-size:14px}}@media only screen and (min-width:992px){html{font-size:14.5px}}@media only screen and (min-width:1200px){html{font-size:15px}}h1,h2,h3,h4,h5,h6{font-weight:400;line-height:1.3}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{font-weight:inherit}h1{font-size:1.4em;line-height:110%;margin:.9333333333em 0 .56em 0}h2{font-size:1.2em;line-height:110%;margin:.8em 0 .48em 0}h3{font-size:1em;line-height:110%;margin:.6666666667em 0 .4em 0}h4{font-size:.8em;line-height:110%;margin:.5333333333em 0 .32em 0}h5{font-size:.8em;line-height:110%;margin:.5333333333em 0 .32em 0}h6{font-size:1.15rem;line-height:110%;margin:.7666666667rem 0 .46rem 0}em{font-style:italic}strong{font-weight:500}small{font-size:75%}.light{font-weight:300}.thin{font-weight:200}@media only screen and (min-width:360px){.flow-text{font-size:1.2rem}}@media only screen and (min-width:390px){.flow-text{font-size:1.224rem}}@media only screen and (min-width:420px){.flow-text{font-size:1.248rem}}@media only screen and (min-width:450px){.flow-text{font-size:1.272rem}}@media only screen and (min-width:480px){.flow-text{font-size:1.296rem}}@media only screen and (min-width:510px){.flow-text{font-size:1.32rem}}@media only screen and (min-width:540px){.flow-text{font-size:1.344rem}}@media only screen and (min-width:570px){.flow-text{font-size:1.368rem}}@media only screen and (min-width:600px){.flow-text{font-size:1.392rem}}@media only screen and (min-width:630px){.flow-text{font-size:1.416rem}}@media only screen and (min-width:660px){.flow-text{font-size:1.44rem}}@media only screen and (min-width:690px){.flow-text{font-size:1.464rem}}@media only screen and (min-width:720px){.flow-text{font-size:1.488rem}}@media only screen and (min-width:750px){.flow-text{font-size:1.512rem}}@media only screen and (min-width:780px){.flow-text{font-size:1.536rem}}@media only screen and (min-width:810px){.flow-text{font-size:1.56rem}}@media only screen and (min-width:840px){.flow-text{font-size:1.584rem}}@media only screen and (min-width:870px){.flow-text{font-size:1.608rem}}@media only screen and (min-width:900px){.flow-text{font-size:1.632rem}}@media only screen and (min-width:930px){.flow-text{font-size:1.656rem}}@media only screen and (min-width:960px){.flow-text{font-size:1.68rem}}@media only screen and (max-width:360px){.flow-text{font-size:1.2rem}}.scale-transition{transition:transform .3s cubic-bezier(0.53,0.01,0.36,1.63)!important}.scale-transition.scale-out{transform:scale(0);transition:transform .2s!important}.scale-transition.scale-in{transform:scale(1)}.card-panel{transition:box-shadow .25s;padding:24px;margin:.5rem 0 1rem 0;border-radius:2px;background-color:#fff}.card{position:relative;margin:.5rem 0 1rem 0;background-color:#fff;transition:box-shadow .25s;border-radius:2px}.card .card-title{font-size:24px;font-weight:300}.card .card-title.activator{cursor:pointer}.card.small,.card.medium,.card.large{position:relative}.card.small .card-image,.card.medium .card-image,.card.large .card-image{max-height:60%;overflow:hidden}.card.small .card-image+.card-content,.card.medium .card-image+.card-content,.card.large .card-image+.card-content{max-height:40%}.card.small .card-content,.card.medium .card-content,.card.large .card-content{max-height:100%;overflow:hidden}.card.small .card-action,.card.medium .card-action,.card.large .card-action{position:absolute;bottom:0;left:0;right:0}.card.small{height:300px}.card.medium{height:400px}.card.large{height:500px}.card.horizontal{display:flex}.card.horizontal.small .card-image,.card.horizontal.medium .card-image,.card.horizontal.large .card-image{height:100%;max-height:none;overflow:visible}.card.horizontal.small .card-image img,.card.horizontal.medium .card-image img,.card.horizontal.large .card-image img{height:100%}.card.horizontal .card-image{max-width:50%}.card.horizontal .card-image img{border-radius:2px 0 0 2px;max-width:100%;width:auto}.card.horizontal .card-stacked{display:flex;flex-direction:column;flex:1;position:relative}.card.horizontal .card-stacked .card-content{flex-grow:1}.card.sticky-action .card-action{z-index:2}.card.sticky-action .card-reveal{z-index:1;padding-bottom:64px}.card .card-image{position:relative}.card .card-image img{display:block;border-radius:2px 2px 0 0;position:relative;left:0;right:0;top:0;bottom:0;width:100%}.card .card-image .card-title{color:#fff;position:absolute;bottom:0;left:0;max-width:100%;padding:24px}.card .card-content{padding:24px;border-radius:0 0 2px 2px}.card .card-content p{margin:0}.card .card-content .card-title{display:block;line-height:32px;margin-bottom:8px}.card .card-content .card-title i{line-height:32px}.card .card-action{background-color:inherit;border-top:1px solid rgba(160,160,160,0.2);position:relative;padding:16px 24px}.card .card-action:last-child{border-radius:0 0 2px 2px}.card .card-action a:not(.btn):not(.btn-large):not(.btn-small):not(.btn-large):not(.btn-floating){color:#ffab40;margin-right:24px;transition:color .3s ease;text-transform:uppercase}.card .card-action a:not(.btn):not(.btn-large):not(.btn-small):not(.btn-large):not(.btn-floating):hover{color:#ffd8a6}.card .card-reveal{padding:24px;position:absolute;background-color:#fff;width:100%;overflow-y:auto;left:0;top:100%;height:100%;z-index:3;display:none}.card .card-reveal .card-title{cursor:pointer;display:block}#toast-container{display:block;position:fixed;z-index:10000}@media only screen and (max-width:600px){#toast-container{min-width:100%;bottom:0}}@media only screen and (min-width:601px) and (max-width:992px){#toast-container{left:5%;bottom:7%;max-width:90%}}@media only screen and (min-width:993px){#toast-container{top:10%;right:7%;max-width:86%}}.toast{border-radius:2px;top:35px;width:auto;margin-top:10px;position:relative;max-width:100%;height:auto;min-height:48px;line-height:1.5em;background-color:#323232;padding:10px 25px;font-size:1.1rem;font-weight:300;color:#fff;display:flex;align-items:center;justify-content:space-between;cursor:default}.toast .toast-action{color:#eeff41;font-weight:500;margin-right:-25px;margin-left:3rem}.toast.rounded{border-radius:24px}@media only screen and (max-width:600px){.toast{width:100%;border-radius:0}}.tabs{position:relative;overflow-x:auto;overflow-y:hidden;height:48px;width:100%;background-color:#fff;margin:0 auto;white-space:nowrap}.tabs.tabs-transparent{background-color:transparent}.tabs.tabs-transparent .tab a,.tabs.tabs-transparent .tab.disabled a,.tabs.tabs-transparent .tab.disabled a:hover{color:rgba(255,255,255,0.7)}.tabs.tabs-transparent .tab a:hover,.tabs.tabs-transparent .tab a.active{color:#fff}.tabs.tabs-transparent .indicator{background-color:#fff}.tabs.tabs-fixed-width{display:flex}.tabs.tabs-fixed-width .tab{flex-grow:1}.tabs .tab{display:inline-block;text-align:center;line-height:48px;height:48px;padding:0;margin:0;text-transform:uppercase}.tabs .tab a{color:rgba(184,64,0,0.7);display:block;width:100%;height:100%;padding:0 24px;font-size:14px;text-overflow:ellipsis;overflow:hidden;transition:color .28s ease,background-color .28s ease}.tabs .tab a:focus,.tabs .tab a:focus.active{background-color:rgba(255,238,230,0.2);outline:0}.tabs .tab a:hover,.tabs .tab a.active{background-color:transparent;color:#b84000}.tabs .tab.disabled a,.tabs .tab.disabled a:hover{color:rgba(184,64,0,0.4);cursor:default}.tabs .indicator{position:absolute;bottom:0;height:2px;background-color:#ffeee6;will-change:left,right}@media only screen and (max-width:992px){.tabs{display:flex}.tabs .tab{flex-grow:1}.tabs .tab a{padding:0 12px}}.material-tooltip{padding:10px 8px;font-size:1rem;z-index:2000;background-color:transparent;border-radius:2px;color:#fff;min-height:36px;line-height:120%;opacity:0;position:absolute;text-align:center;max-width:calc(100% - 4px);overflow:hidden;left:0;top:0;pointer-events:none;visibility:hidden;background-color:#323232}.backdrop{position:absolute;opacity:0;height:7px;width:14px;border-radius:0 0 50% 50%;background-color:#323232;z-index:-1;transform-origin:50% 0;visibility:hidden}.btn,.btn-large,.btn-small,.btn-flat{border:0;border-radius:2px;display:inline-block;height:36px;line-height:36px;padding:0 16px;text-transform:uppercase;vertical-align:middle;-webkit-tap-highlight-color:transparent}.btn.disabled,.disabled.btn-large,.disabled.btn-small,.btn-floating.disabled,.btn-large.disabled,.btn-small.disabled,.btn-flat.disabled,.btn:disabled,.btn-large:disabled,.btn-small:disabled,.btn-floating:disabled,.btn-large:disabled,.btn-small:disabled,.btn-flat:disabled,.btn[disabled],[disabled].btn-large,[disabled].btn-small,.btn-floating[disabled],.btn-large[disabled],.btn-small[disabled],.btn-flat[disabled]{pointer-events:none;background-color:#dfdfdf!important;box-shadow:none;color:#9f9f9f!important;cursor:default}.btn.disabled:hover,.disabled.btn-large:hover,.disabled.btn-small:hover,.btn-floating.disabled:hover,.btn-large.disabled:hover,.btn-small.disabled:hover,.btn-flat.disabled:hover,.btn:disabled:hover,.btn-large:disabled:hover,.btn-small:disabled:hover,.btn-floating:disabled:hover,.btn-large:disabled:hover,.btn-small:disabled:hover,.btn-flat:disabled:hover,.btn[disabled]:hover,[disabled].btn-large:hover,[disabled].btn-small:hover,.btn-floating[disabled]:hover,.btn-large[disabled]:hover,.btn-small[disabled]:hover,.btn-flat[disabled]:hover{background-color:#dfdfdf!important;color:#9f9f9f!important}.btn,.btn-large,.btn-small,.btn-floating,.btn-large,.btn-small,.btn-flat{font-size:14px;outline:0}.btn i,.btn-large i,.btn-small i,.btn-floating i,.btn-large i,.btn-small i,.btn-flat i{font-size:1.3rem;line-height:inherit}.btn:focus,.btn-large:focus,.btn-small:focus,.btn-floating:focus{background-color:#3c7777}.btn,.btn-large,.btn-small{text-decoration:none;color:#fff;background-color:#4d9999;text-align:center;letter-spacing:.5px;transition:background-color .2s ease-out;cursor:pointer}.btn:hover,.btn-large:hover,.btn-small:hover{background-color:#56aaaa}.btn-floating{display:inline-block;color:#fff;position:relative;overflow:hidden;z-index:1;width:40px;height:40px;line-height:40px;padding:0;background-color:#4d9999;border-radius:50%;transition:background-color .3s;cursor:pointer;vertical-align:middle}.btn-floating:hover{background-color:#4d9999}.btn-floating:before{border-radius:0}.btn-floating.btn-large{width:56px;height:56px;padding:0}.btn-floating.btn-large.halfway-fab{bottom:-28px}.btn-floating.btn-large i{line-height:56px}.btn-floating.btn-small{width:32.4px;height:32.4px}.btn-floating.btn-small.halfway-fab{bottom:-16.2px}.btn-floating.btn-small i{line-height:32.4px}.btn-floating.halfway-fab{position:absolute;right:24px;bottom:-20px}.btn-floating.halfway-fab.left{right:auto;left:24px}.btn-floating i{width:inherit;display:inline-block;text-align:center;color:#fff;font-size:1.6rem;line-height:40px}button.btn-floating{border:0}.fixed-action-btn{position:fixed;right:23px;bottom:23px;padding-top:15px;margin-bottom:0;z-index:997}.fixed-action-btn.active ul{visibility:visible}.fixed-action-btn.direction-left,.fixed-action-btn.direction-right{padding:0 0 0 15px}.fixed-action-btn.direction-left ul,.fixed-action-btn.direction-right ul{text-align:right;right:64px;top:50%;transform:translateY(-50%);height:100%;left:auto;width:500px}.fixed-action-btn.direction-left ul li,.fixed-action-btn.direction-right ul li{display:inline-block;margin:7.5px 15px 0 0}.fixed-action-btn.direction-right{padding:0 15px 0 0}.fixed-action-btn.direction-right ul{text-align:left;direction:rtl;left:64px;right:auto}.fixed-action-btn.direction-right ul li{margin:7.5px 0 0 15px}.fixed-action-btn.direction-bottom{padding:0 0 15px 0}.fixed-action-btn.direction-bottom ul{top:64px;bottom:auto;display:flex;flex-direction:column-reverse}.fixed-action-btn.direction-bottom ul li{margin:15px 0 0 0}.fixed-action-btn.toolbar{padding:0;height:56px}.fixed-action-btn.toolbar.active>a i{opacity:0}.fixed-action-btn.toolbar ul{display:flex;top:0;bottom:0;z-index:1}.fixed-action-btn.toolbar ul li{flex:1;display:inline-block;margin:0;height:100%;transition:none}.fixed-action-btn.toolbar ul li a{display:block;overflow:hidden;position:relative;width:100%;height:100%;background-color:transparent;box-shadow:none;color:#fff;line-height:56px;z-index:1}.fixed-action-btn.toolbar ul li a i{line-height:inherit}.fixed-action-btn ul{left:0;right:0;text-align:center;position:absolute;bottom:64px;margin:0;visibility:hidden}.fixed-action-btn ul li{margin-bottom:15px}.fixed-action-btn ul a.btn-floating{opacity:0}.fixed-action-btn .fab-backdrop{position:absolute;top:0;left:0;z-index:-1;width:40px;height:40px;background-color:#4d9999;border-radius:50%;transform:scale(0)}.btn-flat{box-shadow:none;background-color:transparent;color:#343434;cursor:pointer;transition:background-color .2s}.btn-flat:focus,.btn-flat:hover{box-shadow:none}.btn-flat:focus{background-color:rgba(0,0,0,0.1)}.btn-flat.disabled,.btn-flat.btn-flat[disabled]{background-color:transparent!important;color:#b3b3b3!important;cursor:default}.btn-large{height:54px;line-height:54px;font-size:15px;padding:0 28px}.btn-large i{font-size:1.6rem}.btn-small{height:32.4px;line-height:32.4px;font-size:13px}.btn-small i{font-size:1.2rem}.btn-block{display:block}.dropdown-content{background-color:#fff;margin:0;display:none;min-width:100px;overflow-y:auto;opacity:0;position:absolute;left:0;top:0;z-index:9999;transform-origin:0 0}.dropdown-content:focus{outline:0}.dropdown-content li{clear:both;color:rgba(0,0,0,0.87);cursor:pointer;min-height:50px;line-height:1.5rem;width:100%;text-align:left}.dropdown-content li:hover,.dropdown-content li.active{background-color:#eee}.dropdown-content li:focus{outline:0}.dropdown-content li.divider{min-height:0;height:1px}.dropdown-content li>a,.dropdown-content li>span{font-size:16px;color:#4d9999;display:block;line-height:22px;padding:14px 16px}.dropdown-content li>span>label{top:1px;left:0;height:18px}.dropdown-content li>a>i{height:inherit;line-height:inherit;float:left;margin:0 24px 0 0;width:24px}body.keyboard-focused .dropdown-content li:focus{background-color:#dadada}.input-field.col .dropdown-content [type="checkbox"]+label{top:1px;left:0;height:18px;transform:none}.dropdown-trigger{cursor:pointer}/*! + * Waves v0.6.0 + * http://fian.my.id/Waves + * + * Copyright 2014 Alfiana E. Sibuea and other contributors + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + */.waves-effect{position:relative;cursor:pointer;display:inline-block;overflow:hidden;user-select:none;-webkit-tap-highlight-color:transparent;vertical-align:middle;z-index:1;transition:.3s ease-out}.waves-effect .waves-ripple{position:absolute;border-radius:50%;width:20px;height:20px;margin-top:-10px;margin-left:-10px;opacity:0;background:rgba(0,0,0,0.2);transition:all .7s ease-out;transition-property:transform,opacity;transform:scale(0);pointer-events:none}.waves-effect.waves-light .waves-ripple{background-color:rgba(255,255,255,0.45)}.waves-effect.waves-red .waves-ripple{background-color:rgba(244,67,54,0.7)}.waves-effect.waves-yellow .waves-ripple{background-color:rgba(255,235,59,0.7)}.waves-effect.waves-orange .waves-ripple{background-color:rgba(255,152,0,0.7)}.waves-effect.waves-purple .waves-ripple{background-color:rgba(156,39,176,0.7)}.waves-effect.waves-green .waves-ripple{background-color:rgba(76,175,80,0.7)}.waves-effect.waves-teal .waves-ripple{background-color:rgba(0,150,136,0.7)}.waves-effect input[type="button"],.waves-effect input[type="reset"],.waves-effect input[type="submit"]{border:0;font-style:normal;font-size:inherit;text-transform:inherit;background:0}.waves-effect img{position:relative;z-index:-1}.waves-notransition{transition:none!important}.waves-circle{transform:translateZ(0);-webkit-mask-image:-webkit-radial-gradient(circle,white 100%,black 100%)}.waves-input-wrapper{border-radius:.2em;vertical-align:bottom}.waves-input-wrapper .waves-button-input{position:relative;top:0;left:0;z-index:1}.waves-circle{text-align:center;width:2.5em;height:2.5em;line-height:2.5em;border-radius:50%;-webkit-mask-image:none}.waves-block{display:block}.waves-effect .waves-ripple{z-index:-1}.modal{display:none;position:fixed;left:0;right:0;background-color:#fafafa;padding:0;max-height:70%;width:55%;margin:auto;overflow-y:auto;border-radius:2px;will-change:top,opacity}.modal:focus{outline:0}@media only screen and (max-width:992px){.modal{width:80%}}.modal h1,.modal h2,.modal h3,.modal h4{margin-top:0}.modal .modal-content{padding:24px}.modal .modal-close{cursor:pointer}.modal .modal-footer{border-radius:0 0 2px 2px;background-color:#fafafa;padding:4px 6px;height:56px;width:100%;text-align:right}.modal .modal-footer .btn,.modal .modal-footer .btn-large,.modal .modal-footer .btn-small,.modal .modal-footer .btn-flat{margin:6px 0}.modal-overlay{position:fixed;z-index:999;top:-25%;left:0;bottom:0;right:0;height:125%;width:100%;background:#000;display:none;will-change:opacity}.modal.modal-fixed-footer{padding:0;height:70%}.modal.modal-fixed-footer .modal-content{position:absolute;height:calc(100% - 56px);max-height:100%;width:100%;overflow-y:auto}.modal.modal-fixed-footer .modal-footer{border-top:1px solid rgba(0,0,0,0.1);position:absolute;bottom:0}.modal.bottom-sheet{top:auto;bottom:-100%;margin:0;width:100%;max-height:45%;border-radius:0;will-change:bottom,opacity}.collapsible{border-top:1px solid #ddd;border-right:1px solid #ddd;border-left:1px solid #ddd;margin:.5rem 0 1rem 0}.collapsible-header{display:flex;cursor:pointer;-webkit-tap-highlight-color:transparent;line-height:1.5;padding:1rem;background-color:#fff;border-bottom:1px solid #ddd}.collapsible-header:focus{outline:0}.collapsible-header i{width:2rem;font-size:1.6rem;display:inline-block;text-align:center;margin-right:1rem}.keyboard-focused .collapsible-header:focus{background-color:#eee}.collapsible-body{display:none;border-bottom:1px solid #ddd;box-sizing:border-box;padding:2rem}.sidenav .collapsible,.sidenav.fixed .collapsible{border:0;box-shadow:none}.sidenav .collapsible li,.sidenav.fixed .collapsible li{padding:0}.sidenav .collapsible-header,.sidenav.fixed .collapsible-header{background-color:transparent;border:0;line-height:inherit;height:inherit;padding:0 16px}.sidenav .collapsible-header:hover,.sidenav.fixed .collapsible-header:hover{background-color:rgba(0,0,0,0.05)}.sidenav .collapsible-header i,.sidenav.fixed .collapsible-header i{line-height:inherit}.sidenav .collapsible-body,.sidenav.fixed .collapsible-body{border:0;background-color:#fff}.sidenav .collapsible-body li a,.sidenav.fixed .collapsible-body li a{padding:0 23.5px 0 31px}.collapsible.popout{border:0;box-shadow:none}.collapsible.popout>li{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12);margin:0 24px;transition:margin .35s cubic-bezier(0.25,0.46,0.45,0.94)}.collapsible.popout>li.active{box-shadow:0 5px 11px 0 rgba(0,0,0,0.18),0 4px 15px 0 rgba(0,0,0,0.15);margin:16px 0}.chip{display:inline-block;height:32px;font-size:13px;font-weight:500;color:rgba(0,0,0,0.6);line-height:32px;padding:0 12px;border-radius:16px;background-color:#e4e4e4;margin-bottom:5px;margin-right:5px}.chip:focus{outline:0;background-color:#26a69a;color:#fff}.chip>img{float:left;margin:0 8px 0 -12px;height:32px;width:32px;border-radius:50%}.chip .close{cursor:pointer;float:right;font-size:16px;line-height:32px;padding-left:8px}.chips{border:0;border-bottom:1px solid #9e9e9e;box-shadow:none;margin:0 0 8px 0;min-height:45px;outline:0;transition:all .3s}.chips.focus{border-bottom:1px solid #26a69a;box-shadow:0 1px 0 0 #26a69a}.chips:hover{cursor:text}.chips .input{background:0;border:0;color:rgba(0,0,0,0.6);display:inline-block;font-size:16px;height:3rem;line-height:32px;outline:0;margin:0;padding:0!important;width:120px!important}.chips .input:focus{border:0!important;box-shadow:none!important}.chips .autocomplete-content{margin-top:0;margin-bottom:0}.prefix ~ .chips{margin-left:3rem;width:92%;width:calc(100% - 3rem)}.chips:empty ~ label{font-size:.8rem;transform:translateY(-140%)}.materialboxed{display:block;cursor:zoom-in;position:relative;transition:opacity .4s;-webkit-backface-visibility:hidden}.materialboxed:hover:not(.active){opacity:.8}.materialboxed.active{cursor:zoom-out}#materialbox-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background-color:#292929;z-index:1000;will-change:opacity}.materialbox-caption{position:fixed;display:none;color:#fff;line-height:50px;bottom:0;left:0;width:100%;text-align:center;padding:0 15%;height:50px;z-index:1000;-webkit-font-smoothing:antialiased}select:focus{outline:1px solid #e4f2f2}button:focus{outline:0;background-color:#54a7a7}label{font-size:.8rem;color:#9e9e9e}::placeholder{color:#d1d1d1}input:not([type]),input[type=text]:not(.browser-default),input[type=password]:not(.browser-default),input[type=email]:not(.browser-default),input[type=url]:not(.browser-default),input[type=time]:not(.browser-default),input[type=date]:not(.browser-default),input[type=datetime]:not(.browser-default),input[type=datetime-local]:not(.browser-default),input[type=tel]:not(.browser-default),input[type=number]:not(.browser-default),input[type=search]:not(.browser-default),textarea.materialize-textarea{background-color:transparent;border:0;border-bottom:1px solid #9e9e9e;border-radius:0;outline:0;height:3rem;width:100%;font-size:16px;margin:0 0 8px 0;padding:0;box-shadow:none;box-sizing:content-box;transition:box-shadow .3s,border .3s}input:not([type]):disabled,input:not([type])[readonly="readonly"],input[type=text]:not(.browser-default):disabled,input[type=text]:not(.browser-default)[readonly="readonly"],input[type=password]:not(.browser-default):disabled,input[type=password]:not(.browser-default)[readonly="readonly"],input[type=email]:not(.browser-default):disabled,input[type=email]:not(.browser-default)[readonly="readonly"],input[type=url]:not(.browser-default):disabled,input[type=url]:not(.browser-default)[readonly="readonly"],input[type=time]:not(.browser-default):disabled,input[type=time]:not(.browser-default)[readonly="readonly"],input[type=date]:not(.browser-default):disabled,input[type=date]:not(.browser-default)[readonly="readonly"],input[type=datetime]:not(.browser-default):disabled,input[type=datetime]:not(.browser-default)[readonly="readonly"],input[type=datetime-local]:not(.browser-default):disabled,input[type=datetime-local]:not(.browser-default)[readonly="readonly"],input[type=tel]:not(.browser-default):disabled,input[type=tel]:not(.browser-default)[readonly="readonly"],input[type=number]:not(.browser-default):disabled,input[type=number]:not(.browser-default)[readonly="readonly"],input[type=search]:not(.browser-default):disabled,input[type=search]:not(.browser-default)[readonly="readonly"],textarea.materialize-textarea:disabled,textarea.materialize-textarea[readonly="readonly"]{color:rgba(0,0,0,0.42);border-bottom:1px dotted rgba(0,0,0,0.42)}input:not([type]):disabled+label,input:not([type])[readonly="readonly"]+label,input[type=text]:not(.browser-default):disabled+label,input[type=text]:not(.browser-default)[readonly="readonly"]+label,input[type=password]:not(.browser-default):disabled+label,input[type=password]:not(.browser-default)[readonly="readonly"]+label,input[type=email]:not(.browser-default):disabled+label,input[type=email]:not(.browser-default)[readonly="readonly"]+label,input[type=url]:not(.browser-default):disabled+label,input[type=url]:not(.browser-default)[readonly="readonly"]+label,input[type=time]:not(.browser-default):disabled+label,input[type=time]:not(.browser-default)[readonly="readonly"]+label,input[type=date]:not(.browser-default):disabled+label,input[type=date]:not(.browser-default)[readonly="readonly"]+label,input[type=datetime]:not(.browser-default):disabled+label,input[type=datetime]:not(.browser-default)[readonly="readonly"]+label,input[type=datetime-local]:not(.browser-default):disabled+label,input[type=datetime-local]:not(.browser-default)[readonly="readonly"]+label,input[type=tel]:not(.browser-default):disabled+label,input[type=tel]:not(.browser-default)[readonly="readonly"]+label,input[type=number]:not(.browser-default):disabled+label,input[type=number]:not(.browser-default)[readonly="readonly"]+label,input[type=search]:not(.browser-default):disabled+label,input[type=search]:not(.browser-default)[readonly="readonly"]+label,textarea.materialize-textarea:disabled+label,textarea.materialize-textarea[readonly="readonly"]+label{color:rgba(0,0,0,0.42)}input:not([type]):focus:not([readonly]),input[type=text]:not(.browser-default):focus:not([readonly]),input[type=password]:not(.browser-default):focus:not([readonly]),input[type=email]:not(.browser-default):focus:not([readonly]),input[type=url]:not(.browser-default):focus:not([readonly]),input[type=time]:not(.browser-default):focus:not([readonly]),input[type=date]:not(.browser-default):focus:not([readonly]),input[type=datetime]:not(.browser-default):focus:not([readonly]),input[type=datetime-local]:not(.browser-default):focus:not([readonly]),input[type=tel]:not(.browser-default):focus:not([readonly]),input[type=number]:not(.browser-default):focus:not([readonly]),input[type=search]:not(.browser-default):focus:not([readonly]),textarea.materialize-textarea:focus:not([readonly]){border-bottom:1px solid #4d9999;box-shadow:0 1px 0 0 #4d9999}input:not([type]):focus:not([readonly])+label,input[type=text]:not(.browser-default):focus:not([readonly])+label,input[type=password]:not(.browser-default):focus:not([readonly])+label,input[type=email]:not(.browser-default):focus:not([readonly])+label,input[type=url]:not(.browser-default):focus:not([readonly])+label,input[type=time]:not(.browser-default):focus:not([readonly])+label,input[type=date]:not(.browser-default):focus:not([readonly])+label,input[type=datetime]:not(.browser-default):focus:not([readonly])+label,input[type=datetime-local]:not(.browser-default):focus:not([readonly])+label,input[type=tel]:not(.browser-default):focus:not([readonly])+label,input[type=number]:not(.browser-default):focus:not([readonly])+label,input[type=search]:not(.browser-default):focus:not([readonly])+label,textarea.materialize-textarea:focus:not([readonly])+label{color:#4d9999}input:not([type]):focus.valid ~ label,input[type=text]:not(.browser-default):focus.valid ~ label,input[type=password]:not(.browser-default):focus.valid ~ label,input[type=email]:not(.browser-default):focus.valid ~ label,input[type=url]:not(.browser-default):focus.valid ~ label,input[type=time]:not(.browser-default):focus.valid ~ label,input[type=date]:not(.browser-default):focus.valid ~ label,input[type=datetime]:not(.browser-default):focus.valid ~ label,input[type=datetime-local]:not(.browser-default):focus.valid ~ label,input[type=tel]:not(.browser-default):focus.valid ~ label,input[type=number]:not(.browser-default):focus.valid ~ label,input[type=search]:not(.browser-default):focus.valid ~ label,textarea.materialize-textarea:focus.valid ~ label{color:#26a96c}input:not([type]):focus.invalid ~ label,input[type=text]:not(.browser-default):focus.invalid ~ label,input[type=password]:not(.browser-default):focus.invalid ~ label,input[type=email]:not(.browser-default):focus.invalid ~ label,input[type=url]:not(.browser-default):focus.invalid ~ label,input[type=time]:not(.browser-default):focus.invalid ~ label,input[type=date]:not(.browser-default):focus.invalid ~ label,input[type=datetime]:not(.browser-default):focus.invalid ~ label,input[type=datetime-local]:not(.browser-default):focus.invalid ~ label,input[type=tel]:not(.browser-default):focus.invalid ~ label,input[type=number]:not(.browser-default):focus.invalid ~ label,input[type=search]:not(.browser-default):focus.invalid ~ label,textarea.materialize-textarea:focus.invalid ~ label{color:#f44336}input:not([type]).validate+label,input[type=text]:not(.browser-default).validate+label,input[type=password]:not(.browser-default).validate+label,input[type=email]:not(.browser-default).validate+label,input[type=url]:not(.browser-default).validate+label,input[type=time]:not(.browser-default).validate+label,input[type=date]:not(.browser-default).validate+label,input[type=datetime]:not(.browser-default).validate+label,input[type=datetime-local]:not(.browser-default).validate+label,input[type=tel]:not(.browser-default).validate+label,input[type=number]:not(.browser-default).validate+label,input[type=search]:not(.browser-default).validate+label,textarea.materialize-textarea.validate+label{width:100%}input.valid:not([type]),input.valid:not([type]):focus,input[type=text].valid:not(.browser-default),input[type=text].valid:not(.browser-default):focus,input[type=password].valid:not(.browser-default),input[type=password].valid:not(.browser-default):focus,input[type=email].valid:not(.browser-default),input[type=email].valid:not(.browser-default):focus,input[type=url].valid:not(.browser-default),input[type=url].valid:not(.browser-default):focus,input[type=time].valid:not(.browser-default),input[type=time].valid:not(.browser-default):focus,input[type=date].valid:not(.browser-default),input[type=date].valid:not(.browser-default):focus,input[type=datetime].valid:not(.browser-default),input[type=datetime].valid:not(.browser-default):focus,input[type=datetime-local].valid:not(.browser-default),input[type=datetime-local].valid:not(.browser-default):focus,input[type=tel].valid:not(.browser-default),input[type=tel].valid:not(.browser-default):focus,input[type=number].valid:not(.browser-default),input[type=number].valid:not(.browser-default):focus,input[type=search].valid:not(.browser-default),input[type=search].valid:not(.browser-default):focus,textarea.materialize-textarea.valid,textarea.materialize-textarea.valid:focus,.select-wrapper.valid>input.select-dropdown{border-bottom:1px solid #26a96c;box-shadow:0 1px 0 0 #26a96c}input.invalid:not([type]),input.invalid:not([type]):focus,input[type=text].invalid:not(.browser-default),input[type=text].invalid:not(.browser-default):focus,input[type=password].invalid:not(.browser-default),input[type=password].invalid:not(.browser-default):focus,input[type=email].invalid:not(.browser-default),input[type=email].invalid:not(.browser-default):focus,input[type=url].invalid:not(.browser-default),input[type=url].invalid:not(.browser-default):focus,input[type=time].invalid:not(.browser-default),input[type=time].invalid:not(.browser-default):focus,input[type=date].invalid:not(.browser-default),input[type=date].invalid:not(.browser-default):focus,input[type=datetime].invalid:not(.browser-default),input[type=datetime].invalid:not(.browser-default):focus,input[type=datetime-local].invalid:not(.browser-default),input[type=datetime-local].invalid:not(.browser-default):focus,input[type=tel].invalid:not(.browser-default),input[type=tel].invalid:not(.browser-default):focus,input[type=number].invalid:not(.browser-default),input[type=number].invalid:not(.browser-default):focus,input[type=search].invalid:not(.browser-default),input[type=search].invalid:not(.browser-default):focus,textarea.materialize-textarea.invalid,textarea.materialize-textarea.invalid:focus,.select-wrapper.invalid>input.select-dropdown,.select-wrapper.invalid>input.select-dropdown:focus{border-bottom:1px solid #f44336;box-shadow:0 1px 0 0 #f44336}input:not([type]).valid ~ .helper-text[data-success],input:not([type]):focus.valid ~ .helper-text[data-success],input:not([type]).invalid ~ .helper-text[data-error],input:not([type]):focus.invalid ~ .helper-text[data-error],input[type=text]:not(.browser-default).valid ~ .helper-text[data-success],input[type=text]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=text]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=text]:not(.browser-default):focus.invalid ~ .helper-text[data-error],input[type=password]:not(.browser-default).valid ~ .helper-text[data-success],input[type=password]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=password]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=password]:not(.browser-default):focus.invalid ~ .helper-text[data-error],input[type=email]:not(.browser-default).valid ~ .helper-text[data-success],input[type=email]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=email]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=email]:not(.browser-default):focus.invalid ~ .helper-text[data-error],input[type=url]:not(.browser-default).valid ~ .helper-text[data-success],input[type=url]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=url]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=url]:not(.browser-default):focus.invalid ~ .helper-text[data-error],input[type=time]:not(.browser-default).valid ~ .helper-text[data-success],input[type=time]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=time]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=time]:not(.browser-default):focus.invalid ~ .helper-text[data-error],input[type=date]:not(.browser-default).valid ~ .helper-text[data-success],input[type=date]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=date]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=date]:not(.browser-default):focus.invalid ~ .helper-text[data-error],input[type=datetime]:not(.browser-default).valid ~ .helper-text[data-success],input[type=datetime]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=datetime]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=datetime]:not(.browser-default):focus.invalid ~ .helper-text[data-error],input[type=datetime-local]:not(.browser-default).valid ~ .helper-text[data-success],input[type=datetime-local]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=datetime-local]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=datetime-local]:not(.browser-default):focus.invalid ~ .helper-text[data-error],input[type=tel]:not(.browser-default).valid ~ .helper-text[data-success],input[type=tel]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=tel]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=tel]:not(.browser-default):focus.invalid ~ .helper-text[data-error],input[type=number]:not(.browser-default).valid ~ .helper-text[data-success],input[type=number]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=number]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=number]:not(.browser-default):focus.invalid ~ .helper-text[data-error],input[type=search]:not(.browser-default).valid ~ .helper-text[data-success],input[type=search]:not(.browser-default):focus.valid ~ .helper-text[data-success],input[type=search]:not(.browser-default).invalid ~ .helper-text[data-error],input[type=search]:not(.browser-default):focus.invalid ~ .helper-text[data-error],textarea.materialize-textarea.valid ~ .helper-text[data-success],textarea.materialize-textarea:focus.valid ~ .helper-text[data-success],textarea.materialize-textarea.invalid ~ .helper-text[data-error],textarea.materialize-textarea:focus.invalid ~ .helper-text[data-error],.select-wrapper.valid .helper-text[data-success],.select-wrapper.invalid ~ .helper-text[data-error]{color:transparent;user-select:none;pointer-events:none}input:not([type]).valid ~ .helper-text:after,input:not([type]):focus.valid ~ .helper-text:after,input[type=text]:not(.browser-default).valid ~ .helper-text:after,input[type=text]:not(.browser-default):focus.valid ~ .helper-text:after,input[type=password]:not(.browser-default).valid ~ .helper-text:after,input[type=password]:not(.browser-default):focus.valid ~ .helper-text:after,input[type=email]:not(.browser-default).valid ~ .helper-text:after,input[type=email]:not(.browser-default):focus.valid ~ .helper-text:after,input[type=url]:not(.browser-default).valid ~ .helper-text:after,input[type=url]:not(.browser-default):focus.valid ~ .helper-text:after,input[type=time]:not(.browser-default).valid ~ .helper-text:after,input[type=time]:not(.browser-default):focus.valid ~ .helper-text:after,input[type=date]:not(.browser-default).valid ~ .helper-text:after,input[type=date]:not(.browser-default):focus.valid ~ .helper-text:after,input[type=datetime]:not(.browser-default).valid ~ .helper-text:after,input[type=datetime]:not(.browser-default):focus.valid ~ .helper-text:after,input[type=datetime-local]:not(.browser-default).valid ~ .helper-text:after,input[type=datetime-local]:not(.browser-default):focus.valid ~ .helper-text:after,input[type=tel]:not(.browser-default).valid ~ .helper-text:after,input[type=tel]:not(.browser-default):focus.valid ~ .helper-text:after,input[type=number]:not(.browser-default).valid ~ .helper-text:after,input[type=number]:not(.browser-default):focus.valid ~ .helper-text:after,input[type=search]:not(.browser-default).valid ~ .helper-text:after,input[type=search]:not(.browser-default):focus.valid ~ .helper-text:after,textarea.materialize-textarea.valid ~ .helper-text:after,textarea.materialize-textarea:focus.valid ~ .helper-text:after,.select-wrapper.valid ~ .helper-text:after{content:attr(data-success);color:#26a96c}input:not([type]).invalid ~ .helper-text:after,input:not([type]):focus.invalid ~ .helper-text:after,input[type=text]:not(.browser-default).invalid ~ .helper-text:after,input[type=text]:not(.browser-default):focus.invalid ~ .helper-text:after,input[type=password]:not(.browser-default).invalid ~ .helper-text:after,input[type=password]:not(.browser-default):focus.invalid ~ .helper-text:after,input[type=email]:not(.browser-default).invalid ~ .helper-text:after,input[type=email]:not(.browser-default):focus.invalid ~ .helper-text:after,input[type=url]:not(.browser-default).invalid ~ .helper-text:after,input[type=url]:not(.browser-default):focus.invalid ~ .helper-text:after,input[type=time]:not(.browser-default).invalid ~ .helper-text:after,input[type=time]:not(.browser-default):focus.invalid ~ .helper-text:after,input[type=date]:not(.browser-default).invalid ~ .helper-text:after,input[type=date]:not(.browser-default):focus.invalid ~ .helper-text:after,input[type=datetime]:not(.browser-default).invalid ~ .helper-text:after,input[type=datetime]:not(.browser-default):focus.invalid ~ .helper-text:after,input[type=datetime-local]:not(.browser-default).invalid ~ .helper-text:after,input[type=datetime-local]:not(.browser-default):focus.invalid ~ .helper-text:after,input[type=tel]:not(.browser-default).invalid ~ .helper-text:after,input[type=tel]:not(.browser-default):focus.invalid ~ .helper-text:after,input[type=number]:not(.browser-default).invalid ~ .helper-text:after,input[type=number]:not(.browser-default):focus.invalid ~ .helper-text:after,input[type=search]:not(.browser-default).invalid ~ .helper-text:after,input[type=search]:not(.browser-default):focus.invalid ~ .helper-text:after,textarea.materialize-textarea.invalid ~ .helper-text:after,textarea.materialize-textarea:focus.invalid ~ .helper-text:after,.select-wrapper.invalid ~ .helper-text:after{content:attr(data-error);color:#f44336}input:not([type])+label:after,input[type=text]:not(.browser-default)+label:after,input[type=password]:not(.browser-default)+label:after,input[type=email]:not(.browser-default)+label:after,input[type=url]:not(.browser-default)+label:after,input[type=time]:not(.browser-default)+label:after,input[type=date]:not(.browser-default)+label:after,input[type=datetime]:not(.browser-default)+label:after,input[type=datetime-local]:not(.browser-default)+label:after,input[type=tel]:not(.browser-default)+label:after,input[type=number]:not(.browser-default)+label:after,input[type=search]:not(.browser-default)+label:after,textarea.materialize-textarea+label:after,.select-wrapper+label:after{display:block;content:"";position:absolute;top:100%;left:0;opacity:0;transition:.2s opacity ease-out,.2s color ease-out}.input-field{position:relative;margin-top:1rem;margin-bottom:1rem}.input-field.inline{display:inline-block;vertical-align:middle;margin-left:5px}.input-field.inline input,.input-field.inline .select-dropdown{margin-bottom:1rem}.input-field.col label{left:.75rem}.input-field.col .prefix ~ label,.input-field.col .prefix ~ .validate ~ label{width:calc(100% - 3rem - 1.5rem)}.input-field>label{color:#9e9e9e;position:absolute;top:0;left:0;font-size:1rem;cursor:text;transition:transform .2s ease-out,color .2s ease-out;transform-origin:0 100%;text-align:initial;transform:translateY(12px)}.input-field>label:not(.label-icon).active{transform:translateY(-14px) scale(0.8);transform-origin:0 0}.input-field>input[type]:-webkit-autofill:not(.browser-default):not([type="search"])+label,.input-field>input[type=date]:not(.browser-default)+label,.input-field>input[type=time]:not(.browser-default)+label{transform:translateY(-14px) scale(0.8);transform-origin:0 0}.input-field .helper-text{position:relative;min-height:18px;display:block;font-size:12px;color:rgba(0,0,0,0.54)}.input-field .helper-text::after{opacity:1;position:absolute;top:0;left:0}.input-field .prefix{position:absolute;width:3rem;font-size:2rem;transition:color .2s;top:.5rem}.input-field .prefix.active{color:#4d9999}.input-field .prefix ~ input,.input-field .prefix ~ textarea,.input-field .prefix ~ label,.input-field .prefix ~ .validate ~ label,.input-field .prefix ~ .helper-text,.input-field .prefix ~ .autocomplete-content{margin-left:3rem;width:92%;width:calc(100% - 3rem)}.input-field .prefix ~ label{margin-left:3rem}@media only screen and (max-width:992px){.input-field .prefix ~ input{width:86%;width:calc(100% - 3rem)}}@media only screen and (max-width:600px){.input-field .prefix ~ input{width:80%;width:calc(100% - 3rem)}}.input-field input[type=search]{display:block;line-height:inherit;transition:.3s background-color}.nav-wrapper .input-field input[type=search]{height:inherit;padding-left:4rem;width:calc(100% - 4rem);border:0;box-shadow:none}.input-field input[type=search]:focus:not(.browser-default){background-color:#fff;border:0;box-shadow:none;color:#444}.input-field input[type=search]:focus:not(.browser-default)+label i,.input-field input[type=search]:focus:not(.browser-default) ~ .mdi-navigation-close,.input-field input[type=search]:focus:not(.browser-default) ~ .material-icons{color:#444}.input-field input[type=search]+.label-icon{transform:none;left:1rem}.input-field input[type=search] ~ .mdi-navigation-close,.input-field input[type=search] ~ .material-icons{position:absolute;top:0;right:1rem;color:transparent;cursor:pointer;font-size:2rem;transition:.3s color}textarea{width:100%;height:3rem;background-color:transparent}textarea.materialize-textarea{line-height:normal;overflow-y:hidden;padding:.8rem 0 .8rem 0;resize:none;min-height:3rem;box-sizing:border-box}.hiddendiv{visibility:hidden;white-space:pre-wrap;word-wrap:break-word;overflow-wrap:break-word;padding-top:1.2rem;position:absolute;top:0;z-index:-1}.autocomplete-content li .highlight{color:#444}.autocomplete-content li img{height:40px;width:40px;margin:5px 15px}.character-counter{min-height:18px}[type="radio"]:not(:checked),[type="radio"]:checked{position:absolute;opacity:0;pointer-events:none}[type="radio"]:not(:checked)+span,[type="radio"]:checked+span{position:relative;padding-left:35px;cursor:pointer;display:inline-block;height:25px;line-height:25px;font-size:1rem;transition:.28s ease;user-select:none}[type="radio"]+span:before,[type="radio"]+span:after{content:'';position:absolute;left:0;top:0;margin:4px;width:16px;height:16px;z-index:0;transition:.28s ease}[type="radio"]:not(:checked)+span:before,[type="radio"]:not(:checked)+span:after,[type="radio"]:checked+span:before,[type="radio"]:checked+span:after,[type="radio"].with-gap:checked+span:before,[type="radio"].with-gap:checked+span:after{border-radius:50%}[type="radio"]:not(:checked)+span:before,[type="radio"]:not(:checked)+span:after{border:2px solid #5a5a5a}[type="radio"]:not(:checked)+span:after{transform:scale(0)}[type="radio"]:checked+span:before{border:2px solid transparent}[type="radio"]:checked+span:after,[type="radio"].with-gap:checked+span:before,[type="radio"].with-gap:checked+span:after{border:2px solid #4d9999}[type="radio"]:checked+span:after,[type="radio"].with-gap:checked+span:after{background-color:#4d9999}[type="radio"]:checked+span:after{transform:scale(1.02)}[type="radio"].with-gap:checked+span:after{transform:scale(0.5)}[type="radio"].tabbed:focus+span:before{box-shadow:0 0 0 10px rgba(0,0,0,0.1)}[type="radio"].with-gap:disabled:checked+span:before{border:2px solid rgba(0,0,0,0.42)}[type="radio"].with-gap:disabled:checked+span:after{border:0;background-color:rgba(0,0,0,0.42)}[type="radio"]:disabled:not(:checked)+span:before,[type="radio"]:disabled:checked+span:before{background-color:transparent;border-color:rgba(0,0,0,0.42)}[type="radio"]:disabled+span{color:rgba(0,0,0,0.42)}[type="radio"]:disabled:not(:checked)+span:before{border-color:rgba(0,0,0,0.42)}[type="radio"]:disabled:checked+span:after{background-color:rgba(0,0,0,0.42);border-color:#949494}[type="checkbox"]:not(:checked),[type="checkbox"]:checked{position:absolute;opacity:0;pointer-events:none}[type="checkbox"]+span:not(.lever){position:relative;padding-left:35px;cursor:pointer;display:inline-block;height:25px;line-height:25px;font-size:1rem;user-select:none}[type="checkbox"]+span:not(.lever):before,[type="checkbox"]:not(.filled-in)+span:not(.lever):after{content:'';position:absolute;top:0;left:0;width:18px;height:18px;z-index:0;border:2px solid #5a5a5a;border-radius:1px;margin-top:3px;transition:.2s}[type="checkbox"]:not(.filled-in)+span:not(.lever):after{border:0;transform:scale(0)}[type="checkbox"]:not(:checked):disabled+span:not(.lever):before{border:0;background-color:rgba(0,0,0,0.42)}[type="checkbox"].tabbed:focus+span:not(.lever):after{transform:scale(1);border:0;border-radius:50%;box-shadow:0 0 0 10px rgba(0,0,0,0.1);background-color:rgba(0,0,0,0.1)}[type="checkbox"]:checked+span:not(.lever):before{top:-4px;left:-5px;width:12px;height:22px;border-top:2px solid transparent;border-left:2px solid transparent;border-right:2px solid #4d9999;border-bottom:2px solid #4d9999;transform:rotate(40deg);backface-visibility:hidden;transform-origin:100% 100%}[type="checkbox"]:checked:disabled+span:before{border-right:2px solid rgba(0,0,0,0.42);border-bottom:2px solid rgba(0,0,0,0.42)}[type="checkbox"]:indeterminate+span:not(.lever):before{top:-11px;left:-12px;width:10px;height:22px;border-top:0;border-left:none;border-right:2px solid #4d9999;border-bottom:0;transform:rotate(90deg);backface-visibility:hidden;transform-origin:100% 100%}[type="checkbox"]:indeterminate:disabled+span:not(.lever):before{border-right:2px solid rgba(0,0,0,0.42);background-color:transparent}[type="checkbox"].filled-in+span:not(.lever):after{border-radius:2px}[type="checkbox"].filled-in+span:not(.lever):before,[type="checkbox"].filled-in+span:not(.lever):after{content:'';left:0;position:absolute;transition:border .25s,background-color .25s,width .20s .1s,height .20s .1s,top .20s .1s,left .20s .1s;z-index:1}[type="checkbox"].filled-in:not(:checked)+span:not(.lever):before{width:0;height:0;border:3px solid transparent;left:6px;top:10px;transform:rotateZ(37deg);transform-origin:100% 100%}[type="checkbox"].filled-in:not(:checked)+span:not(.lever):after{height:20px;width:20px;background-color:transparent;border:2px solid #5a5a5a;top:0;z-index:0}[type="checkbox"].filled-in:checked+span:not(.lever):before{top:0;left:1px;width:8px;height:13px;border-top:2px solid transparent;border-left:2px solid transparent;border-right:2px solid #fff;border-bottom:2px solid #fff;transform:rotateZ(37deg);transform-origin:100% 100%}[type="checkbox"].filled-in:checked+span:not(.lever):after{top:0;width:20px;height:20px;border:2px solid #4d9999;background-color:#4d9999;z-index:0}[type="checkbox"].filled-in.tabbed:focus+span:not(.lever):after{border-radius:2px;border-color:#5a5a5a;background-color:rgba(0,0,0,0.1)}[type="checkbox"].filled-in.tabbed:checked:focus+span:not(.lever):after{border-radius:2px;background-color:#4d9999;border-color:#4d9999}[type="checkbox"].filled-in:disabled:not(:checked)+span:not(.lever):before{background-color:transparent;border:2px solid transparent}[type="checkbox"].filled-in:disabled:not(:checked)+span:not(.lever):after{border-color:transparent;background-color:#949494}[type="checkbox"].filled-in:disabled:checked+span:not(.lever):before{background-color:transparent}[type="checkbox"].filled-in:disabled:checked+span:not(.lever):after{background-color:#949494;border-color:#949494}.switch,.switch *{-webkit-tap-highlight-color:transparent;user-select:none}.switch label{cursor:pointer}.switch label input[type=checkbox]{opacity:0;width:0;height:0}.switch label input[type=checkbox]:checked+.lever{background-color:#adb9b9}.switch label input[type=checkbox]:checked+.lever:before,.switch label input[type=checkbox]:checked+.lever:after{left:18px}.switch label input[type=checkbox]:checked+.lever:after{background-color:#4d9999}.switch label .lever{content:"";display:inline-block;position:relative;width:36px;height:14px;background-color:rgba(0,0,0,0.38);border-radius:15px;margin-right:10px;transition:background .3s ease;vertical-align:middle;margin:0 16px}.switch label .lever:before,.switch label .lever:after{content:"";position:absolute;display:inline-block;width:20px;height:20px;border-radius:50%;left:0;top:-3px;transition:left .3s ease,background .3s ease,box-shadow .1s ease,transform .1s ease}.switch label .lever:before{background-color:rgba(77,153,153,0.15)}.switch label .lever:after{background-color:#f1f1f1;box-shadow:0 3px 1px -2px rgba(0,0,0,0.2),0px 2px 2px 0 rgba(0,0,0,0.14),0px 1px 5px 0 rgba(0,0,0,0.12)}input[type=checkbox]:checked:not(:disabled) ~ .lever:active::before,input[type=checkbox]:checked:not(:disabled).tabbed:focus ~ .lever::before{transform:scale(2.4);background-color:rgba(77,153,153,0.15)}input[type=checkbox]:not(:disabled) ~ .lever:active:before,input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::before{transform:scale(2.4);background-color:rgba(0,0,0,0.08)}.switch input[type=checkbox][disabled]+.lever{cursor:default;background-color:rgba(0,0,0,0.12)}.switch label input[type=checkbox][disabled]+.lever:after,.switch label input[type=checkbox][disabled]:checked+.lever:after{background-color:#949494}select{display:none}select.browser-default{display:block}select{background-color:rgba(255,255,255,0.9);width:100%;padding:5px;border:1px solid #f2f2f2;border-radius:2px;height:3rem}.select-label{position:absolute}.select-wrapper{position:relative}.select-wrapper.valid+label,.select-wrapper.invalid+label{width:100%;pointer-events:none}.select-wrapper input.select-dropdown{position:relative;cursor:pointer;background-color:transparent;border:0;border-bottom:1px solid #9e9e9e;outline:0;height:3rem;line-height:3rem;width:100%;font-size:16px;margin:0 0 8px 0;padding:0;display:block;user-select:none;z-index:1}.select-wrapper input.select-dropdown:focus{border-bottom:1px solid #4d9999}.select-wrapper .caret{position:absolute;right:0;top:0;bottom:0;margin:auto 0;z-index:0;fill:rgba(0,0,0,0.87)}.select-wrapper+label{position:absolute;top:-26px;font-size:.8rem}select:disabled{color:rgba(0,0,0,0.42)}.select-wrapper.disabled+label{color:rgba(0,0,0,0.42)}.select-wrapper.disabled .caret{fill:rgba(0,0,0,0.42)}.select-wrapper input.select-dropdown:disabled{color:rgba(0,0,0,0.42);cursor:default;user-select:none}.select-wrapper i{color:rgba(0,0,0,0.3)}.select-dropdown li.disabled,.select-dropdown li.disabled>span,.select-dropdown li.optgroup{color:rgba(0,0,0,0.3);background-color:transparent}body.keyboard-focused .select-dropdown.dropdown-content li:focus{background-color:rgba(0,0,0,0.08)}.select-dropdown.dropdown-content li:hover{background-color:rgba(0,0,0,0.08)}.select-dropdown.dropdown-content li.selected{background-color:rgba(0,0,0,0.03)}.prefix ~ .select-wrapper{margin-left:3rem;width:92%;width:calc(100% - 3rem)}.prefix ~ label{margin-left:3rem}.select-dropdown li img{height:40px;width:40px;margin:5px 15px;float:right}.select-dropdown li.optgroup{border-top:1px solid #eee}.select-dropdown li.optgroup.selected>span{color:rgba(0,0,0,0.7)}.select-dropdown li.optgroup>span{color:rgba(0,0,0,0.4)}.select-dropdown li.optgroup ~ li.optgroup-option{padding-left:1rem}.file-field{position:relative}.file-field .file-path-wrapper{overflow:hidden;padding-left:10px}.file-field input.file-path{width:100%}.file-field .btn,.file-field .btn-large,.file-field .btn-small{float:left;height:3rem;line-height:3rem}.file-field span{cursor:pointer}.file-field input[type=file]{position:absolute;top:0;right:0;left:0;bottom:0;width:100%;margin:0;padding:0;font-size:20px;cursor:pointer;opacity:0;filter:alpha(opacity=0)}.file-field input[type=file]::-webkit-file-upload-button{display:none}.range-field{position:relative}input[type=range],input[type=range]+.thumb{cursor:pointer}input[type=range]{position:relative;background-color:transparent;border:0;outline:0;width:100%;margin:15px 0;padding:0}input[type=range]:focus{outline:0}input[type=range]+.thumb{position:absolute;top:10px;left:0;border:0;height:0;width:0;border-radius:50%;background-color:#4d9999;margin-left:7px;transform-origin:50% 50%;transform:rotate(-45deg)}input[type=range]+.thumb .value{display:block;width:30px;text-align:center;color:#4d9999;font-size:0;transform:rotate(45deg)}input[type=range]+.thumb.active{border-radius:50% 50% 50% 0}input[type=range]+.thumb.active .value{color:#fff;margin-left:-1px;margin-top:8px;font-size:10px}input[type=range]{-webkit-appearance:none}input[type=range]::-webkit-slider-runnable-track{height:3px;background:#c2c0c2;border:0}input[type=range]::-webkit-slider-thumb{border:0;height:14px;width:14px;border-radius:50%;background:#4d9999;transition:box-shadow .3s;-webkit-appearance:none;background-color:#4d9999;transform-origin:50% 50%;margin:-5px 0 0 0}.keyboard-focused input[type=range]:focus:not(.active)::-webkit-slider-thumb{box-shadow:0 0 0 10px rgba(77,153,153,0.26)}input[type=range]{border:1px solid white}input[type=range]::-moz-range-track{height:3px;background:#c2c0c2;border:0}input[type=range]::-moz-focus-inner{border:0}input[type=range]::-moz-range-thumb{border:0;height:14px;width:14px;border-radius:50%;background:#4d9999;transition:box-shadow .3s;margin-top:-5px}input[type=range]:-moz-focusring{outline:1px solid #fff;outline-offset:-1px}.keyboard-focused input[type=range]:focus:not(.active)::-moz-range-thumb{box-shadow:0 0 0 10px rgba(77,153,153,0.26)}input[type=range]::-ms-track{height:3px;background:transparent;border-color:transparent;border-width:6px 0;color:transparent}input[type=range]::-ms-fill-lower{background:#777}input[type=range]::-ms-fill-upper{background:#ddd}input[type=range]::-ms-thumb{border:0;height:14px;width:14px;border-radius:50%;background:#4d9999;transition:box-shadow .3s}.keyboard-focused input[type=range]:focus:not(.active)::-ms-thumb{box-shadow:0 0 0 10px rgba(77,153,153,0.26)}.table-of-contents.fixed{position:fixed}.table-of-contents li{padding:2px 0}.table-of-contents a{display:inline-block;font-weight:300;color:#757575;padding-left:16px;height:1.5rem;line-height:1.5rem;letter-spacing:.4;display:inline-block}.table-of-contents a:hover{color:#a8a8a8;padding-left:15px;border-left:1px solid #b84000}.table-of-contents a.active{font-weight:500;padding-left:14px;border-left:2px solid #b84000}.sidenav{position:fixed;width:300px;left:0;top:0;margin:0;transform:translateX(-100%);height:100%;height:calc(100% + 60px);height:-moz-calc(100%);padding-bottom:60px;background-color:#fff;z-index:999;overflow-y:auto;will-change:transform;backface-visibility:hidden;transform:translateX(-105%)}.sidenav.right-aligned{right:0;transform:translateX(105%);left:auto;transform:translateX(100%)}.sidenav .collapsible{margin:0}.sidenav li{float:none;line-height:48px}.sidenav li.active{background-color:rgba(0,0,0,0.05)}.sidenav li>a{color:rgba(0,0,0,0.87);display:block;font-size:14px;font-weight:500;height:48px;line-height:48px;padding:0 32px}.sidenav li>a:hover{background-color:rgba(0,0,0,0.05)}.sidenav li>a.btn,.sidenav li>a.btn-large,.sidenav li>a.btn-small,.sidenav li>a.btn-large,.sidenav li>a.btn-flat,.sidenav li>a.btn-floating{margin:10px 15px}.sidenav li>a.btn,.sidenav li>a.btn-large,.sidenav li>a.btn-small,.sidenav li>a.btn-large,.sidenav li>a.btn-floating{color:#fff}.sidenav li>a.btn-flat{color:#343434}.sidenav li>a.btn:hover,.sidenav li>a.btn-large:hover,.sidenav li>a.btn-small:hover,.sidenav li>a.btn-large:hover{background-color:#56aaaa}.sidenav li>a.btn-floating:hover{background-color:#4d9999}.sidenav li>a>i,.sidenav li>a>[class^="mdi-"],.sidenav li>a li>a>[class*="mdi-"],.sidenav li>a>i.material-icons{float:left;height:48px;line-height:48px;margin:0 32px 0 0;width:24px;color:rgba(0,0,0,0.54)}.sidenav .divider{margin:8px 0 0 0}.sidenav .subheader{cursor:initial;pointer-events:none;color:rgba(0,0,0,0.54);font-size:14px;font-weight:500;line-height:48px}.sidenav .subheader:hover{background-color:transparent}.sidenav .user-view{position:relative;padding:32px 32px 0;margin-bottom:8px}.sidenav .user-view>a{height:auto;padding:0}.sidenav .user-view>a:hover{background-color:transparent}.sidenav .user-view .background{overflow:hidden;position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1}.sidenav .user-view .circle,.sidenav .user-view .name,.sidenav .user-view .email{display:block}.sidenav .user-view .circle{height:64px;width:64px}.sidenav .user-view .name,.sidenav .user-view .email{font-size:14px;line-height:24px}.sidenav .user-view .name{margin-top:16px;font-weight:500}.sidenav .user-view .email{padding-bottom:16px;font-weight:400}.drag-target{height:100%;width:10px;position:fixed;top:0;z-index:998}.drag-target.right-aligned{right:0}.sidenav.sidenav-fixed{left:0;transform:translateX(0);position:fixed}.sidenav.sidenav-fixed.right-aligned{right:0;left:auto}@media only screen and (max-width:992px){.sidenav.sidenav-fixed{transform:translateX(-105%)}.sidenav.sidenav-fixed.right-aligned{transform:translateX(105%)}.sidenav>a{padding:0 16px}.sidenav .user-view{padding:16px 16px 0}}.sidenav .collapsible-body>ul:not(.collapsible)>li.active,.sidenav.sidenav-fixed .collapsible-body>ul:not(.collapsible)>li.active{background-color:#b84000}.sidenav .collapsible-body>ul:not(.collapsible)>li.active a,.sidenav.sidenav-fixed .collapsible-body>ul:not(.collapsible)>li.active a{color:#fff}.sidenav .collapsible-body{padding:0}.sidenav-overlay{position:fixed;top:0;left:0;right:0;opacity:0;height:120vh;background-color:rgba(0,0,0,0.5);z-index:997;display:none}.preloader-wrapper{display:inline-block;position:relative;width:50px;height:50px}.preloader-wrapper.small{width:36px;height:36px}.preloader-wrapper.big{width:64px;height:64px}.preloader-wrapper.active{-webkit-animation:container-rotate 1568ms linear infinite;animation:container-rotate 1568ms linear infinite}@-webkit-keyframes container-rotate{to{-webkit-transform:rotate(360deg)}}@keyframes container-rotate{to{transform:rotate(360deg)}}.spinner-layer{position:absolute;width:100%;height:100%;opacity:0;border-color:#4d9999}.spinner-blue,.spinner-blue-only{border-color:#4285f4}.spinner-red,.spinner-red-only{border-color:#db4437}.spinner-yellow,.spinner-yellow-only{border-color:#f4b400}.spinner-green,.spinner-green-only{border-color:#0f9d58}.active .spinner-layer.spinner-blue{-webkit-animation:fill-unfill-rotate 5332ms cubic-bezier(0.4,0,0.2,1) infinite both,blue-fade-in-out 5332ms cubic-bezier(0.4,0,0.2,1) infinite both;animation:fill-unfill-rotate 5332ms cubic-bezier(0.4,0,0.2,1) infinite both,blue-fade-in-out 5332ms cubic-bezier(0.4,0,0.2,1) infinite both}.active .spinner-layer.spinner-red{-webkit-animation:fill-unfill-rotate 5332ms cubic-bezier(0.4,0,0.2,1) infinite both,red-fade-in-out 5332ms cubic-bezier(0.4,0,0.2,1) infinite both;animation:fill-unfill-rotate 5332ms cubic-bezier(0.4,0,0.2,1) infinite both,red-fade-in-out 5332ms cubic-bezier(0.4,0,0.2,1) infinite both}.active .spinner-layer.spinner-yellow{-webkit-animation:fill-unfill-rotate 5332ms cubic-bezier(0.4,0,0.2,1) infinite both,yellow-fade-in-out 5332ms cubic-bezier(0.4,0,0.2,1) infinite both;animation:fill-unfill-rotate 5332ms cubic-bezier(0.4,0,0.2,1) infinite both,yellow-fade-in-out 5332ms cubic-bezier(0.4,0,0.2,1) infinite both}.active .spinner-layer.spinner-green{-webkit-animation:fill-unfill-rotate 5332ms cubic-bezier(0.4,0,0.2,1) infinite both,green-fade-in-out 5332ms cubic-bezier(0.4,0,0.2,1) infinite both;animation:fill-unfill-rotate 5332ms cubic-bezier(0.4,0,0.2,1) infinite both,green-fade-in-out 5332ms cubic-bezier(0.4,0,0.2,1) infinite both}.active .spinner-layer,.active .spinner-layer.spinner-blue-only,.active .spinner-layer.spinner-red-only,.active .spinner-layer.spinner-yellow-only,.active .spinner-layer.spinner-green-only{opacity:1;-webkit-animation:fill-unfill-rotate 5332ms cubic-bezier(0.4,0,0.2,1) infinite both;animation:fill-unfill-rotate 5332ms cubic-bezier(0.4,0,0.2,1) infinite both}@-webkit-keyframes fill-unfill-rotate{12.5%{-webkit-transform:rotate(135deg)}25%{-webkit-transform:rotate(270deg)}37.5%{-webkit-transform:rotate(405deg)}50%{-webkit-transform:rotate(540deg)}62.5%{-webkit-transform:rotate(675deg)}75%{-webkit-transform:rotate(810deg)}87.5%{-webkit-transform:rotate(945deg)}to{-webkit-transform:rotate(1080deg)}}@keyframes fill-unfill-rotate{12.5%{transform:rotate(135deg)}25%{transform:rotate(270deg)}37.5%{transform:rotate(405deg)}50%{transform:rotate(540deg)}62.5%{transform:rotate(675deg)}75%{transform:rotate(810deg)}87.5%{transform:rotate(945deg)}to{transform:rotate(1080deg)}}@-webkit-keyframes blue-fade-in-out{from{opacity:1}25%{opacity:1}26%{opacity:0}89%{opacity:0}90%{opacity:1}100%{opacity:1}}@keyframes blue-fade-in-out{from{opacity:1}25%{opacity:1}26%{opacity:0}89%{opacity:0}90%{opacity:1}100%{opacity:1}}@-webkit-keyframes red-fade-in-out{from{opacity:0}15%{opacity:0}25%{opacity:1}50%{opacity:1}51%{opacity:0}}@keyframes red-fade-in-out{from{opacity:0}15%{opacity:0}25%{opacity:1}50%{opacity:1}51%{opacity:0}}@-webkit-keyframes yellow-fade-in-out{from{opacity:0}40%{opacity:0}50%{opacity:1}75%{opacity:1}76%{opacity:0}}@keyframes yellow-fade-in-out{from{opacity:0}40%{opacity:0}50%{opacity:1}75%{opacity:1}76%{opacity:0}}@-webkit-keyframes green-fade-in-out{from{opacity:0}65%{opacity:0}75%{opacity:1}90%{opacity:1}100%{opacity:0}}@keyframes green-fade-in-out{from{opacity:0}65%{opacity:0}75%{opacity:1}90%{opacity:1}100%{opacity:0}}.gap-patch{position:absolute;top:0;left:45%;width:10%;height:100%;overflow:hidden;border-color:inherit}.gap-patch .circle{width:1000%;left:-450%}.circle-clipper{display:inline-block;position:relative;width:50%;height:100%;overflow:hidden;border-color:inherit}.circle-clipper .circle{width:200%;height:100%;border-width:3px;border-style:solid;border-color:inherit;border-bottom-color:transparent!important;border-radius:50%;-webkit-animation:none;animation:none;position:absolute;top:0;right:0;bottom:0}.circle-clipper.left .circle{left:0;border-right-color:transparent!important;-webkit-transform:rotate(129deg);transform:rotate(129deg)}.circle-clipper.right .circle{left:-100%;border-left-color:transparent!important;-webkit-transform:rotate(-129deg);transform:rotate(-129deg)}.active .circle-clipper.left .circle{-webkit-animation:left-spin 1333ms cubic-bezier(0.4,0,0.2,1) infinite both;animation:left-spin 1333ms cubic-bezier(0.4,0,0.2,1) infinite both}.active .circle-clipper.right .circle{-webkit-animation:right-spin 1333ms cubic-bezier(0.4,0,0.2,1) infinite both;animation:right-spin 1333ms cubic-bezier(0.4,0,0.2,1) infinite both}@-webkit-keyframes left-spin{from{-webkit-transform:rotate(130deg)}50%{-webkit-transform:rotate(-5deg)}to{-webkit-transform:rotate(130deg)}}@keyframes left-spin{from{transform:rotate(130deg)}50%{transform:rotate(-5deg)}to{transform:rotate(130deg)}}@-webkit-keyframes right-spin{from{-webkit-transform:rotate(-130deg)}50%{-webkit-transform:rotate(5deg)}to{-webkit-transform:rotate(-130deg)}}@keyframes right-spin{from{transform:rotate(-130deg)}50%{transform:rotate(5deg)}to{transform:rotate(-130deg)}}#spinnerContainer.cooldown{-webkit-animation:container-rotate 1568ms linear infinite,fade-out 400ms cubic-bezier(0.4,0,0.2,1);animation:container-rotate 1568ms linear infinite,fade-out 400ms cubic-bezier(0.4,0,0.2,1)}@-webkit-keyframes fade-out{from{opacity:1}to{opacity:0}}@keyframes fade-out{from{opacity:1}to{opacity:0}}.slider{position:relative;height:400px;width:100%}.slider.fullscreen{height:100%;width:100%;position:absolute;top:0;left:0;right:0;bottom:0}.slider.fullscreen ul.slides{height:100%}.slider.fullscreen ul.indicators{z-index:2;bottom:30px}.slider .slides{background-color:#9e9e9e;margin:0;height:400px}.slider .slides li{opacity:0;position:absolute;top:0;left:0;z-index:1;width:100%;height:inherit;overflow:hidden}.slider .slides li img{height:100%;width:100%;background-size:cover;background-position:center}.slider .slides li .caption{color:#fff;position:absolute;top:15%;left:15%;width:70%;opacity:0}.slider .slides li .caption p{color:#e0e0e0}.slider .slides li.active{z-index:2}.slider .indicators{position:absolute;text-align:center;left:0;right:0;bottom:0;margin:0}.slider .indicators .indicator-item{display:inline-block;position:relative;cursor:pointer;height:16px;width:16px;margin:0 12px;background-color:#e0e0e0;transition:background-color .3s;border-radius:50%}.slider .indicators .indicator-item.active{background-color:#4caf50}.carousel{overflow:hidden;position:relative;width:100%;height:400px;perspective:500px;transform-style:preserve-3d;transform-origin:0 50%}.carousel.carousel-slider{top:0;left:0}.carousel.carousel-slider .carousel-fixed-item{position:absolute;left:0;right:0;bottom:20px;z-index:1}.carousel.carousel-slider .carousel-fixed-item.with-indicators{bottom:68px}.carousel.carousel-slider .carousel-item{width:100%;height:100%;min-height:400px;position:absolute;top:0;left:0}.carousel.carousel-slider .carousel-item h2{font-size:24px;font-weight:500;line-height:32px}.carousel.carousel-slider .carousel-item p{font-size:15px}.carousel .carousel-item{visibility:hidden;width:200px;height:200px;position:absolute;top:0;left:0}.carousel .carousel-item>img{width:100%}.carousel .indicators{position:absolute;text-align:center;left:0;right:0;bottom:0;margin:0}.carousel .indicators .indicator-item{display:inline-block;position:relative;cursor:pointer;height:8px;width:8px;margin:24px 4px;background-color:rgba(255,255,255,0.5);transition:background-color .3s;border-radius:50%}.carousel .indicators .indicator-item.active{background-color:#fff}.carousel.scrolling .carousel-item .materialboxed,.carousel .carousel-item:not(.active) .materialboxed{pointer-events:none}.tap-target-wrapper{width:800px;height:800px;position:fixed;z-index:1000;visibility:hidden;transition:visibility 0s .3s}.tap-target-wrapper.open{visibility:visible;transition:visibility 0s}.tap-target-wrapper.open .tap-target{transform:scale(1);opacity:.95;transition:transform .3s cubic-bezier(0.42,0,0.58,1),opacity .3s cubic-bezier(0.42,0,0.58,1)}.tap-target-wrapper.open .tap-target-wave::before{transform:scale(1)}.tap-target-wrapper.open .tap-target-wave::after{visibility:visible;animation:pulse-animation 1s cubic-bezier(0.24,0,0.38,1) infinite;transition:opacity .3s,transform .3s,visibility 0s 1s}.tap-target{position:absolute;font-size:1rem;border-radius:50%;background-color:#b84000;box-shadow:0 20px 20px 0 rgba(0,0,0,0.14),0 10px 50px 0 rgba(0,0,0,0.12),0 30px 10px -20px rgba(0,0,0,0.2);width:100%;height:100%;opacity:0;transform:scale(0);transition:transform .3s cubic-bezier(0.42,0,0.58,1),opacity .3s cubic-bezier(0.42,0,0.58,1)}.tap-target-content{position:relative;display:table-cell}.tap-target-wave{position:absolute;border-radius:50%;z-index:10001}.tap-target-wave::before,.tap-target-wave::after{content:'';display:block;position:absolute;width:100%;height:100%;border-radius:50%;background-color:#fff}.tap-target-wave::before{transform:scale(0);transition:transform .3s}.tap-target-wave::after{visibility:hidden;transition:opacity .3s,transform .3s,visibility 0s;z-index:-1}.tap-target-origin{top:50%;left:50%;transform:translate(-50%,-50%);z-index:10002;position:absolute!important}.tap-target-origin:not(.btn):not(.btn-large):not(.btn-small),.tap-target-origin:not(.btn):not(.btn-large):not(.btn-small):hover{background:0}@media only screen and (max-width:600px){.tap-target,.tap-target-wrapper{width:600px;height:600px}}.pulse{overflow:visible;position:relative}.pulse::before{content:'';display:block;position:absolute;width:100%;height:100%;top:0;left:0;background-color:inherit;border-radius:inherit;transition:opacity .3s,transform .3s;animation:pulse-animation 1s cubic-bezier(0.24,0,0.38,1) infinite;z-index:-1}@keyframes pulse-animation{0%{opacity:1;transform:scale(1)}50%{opacity:0;transform:scale(1.5)}100%{opacity:0;transform:scale(1.5)}}.datepicker-modal{max-width:325px;min-width:300px;max-height:none}.datepicker-container.modal-content{display:flex;flex-direction:column;padding:0}.datepicker-controls{display:flex;justify-content:space-between;width:280px;margin:0 auto}.datepicker-controls .selects-container{display:flex}.datepicker-controls .select-wrapper input{border-bottom:0;text-align:center;margin:0}.datepicker-controls .select-wrapper input:focus{border-bottom:0}.datepicker-controls .select-wrapper .caret{display:none}.datepicker-controls .select-year input{width:50px}.datepicker-controls .select-month input{width:70px}.month-prev,.month-next{margin-top:4px;cursor:pointer;background-color:transparent;border:0}.datepicker-date-display{flex:1 auto;background-color:#4d9999;color:#fff;padding:20px 22px;font-weight:500}.datepicker-date-display .year-text{display:block;font-size:1.5rem;line-height:25px;color:rgba(255,255,255,0.7)}.datepicker-date-display .date-text{display:block;font-size:2.8rem;line-height:47px;font-weight:500}.datepicker-calendar-container{flex:2.5 auto}.datepicker-table{width:280px;font-size:1rem;margin:0 auto}.datepicker-table thead{border-bottom:0}.datepicker-table th{padding:10px 5px;text-align:center}.datepicker-table tr{border:0}.datepicker-table abbr{text-decoration:none;color:#999}.datepicker-table td{border-radius:50%;padding:0}.datepicker-table td.is-today{color:#4d9999}.datepicker-table td.is-selected{background-color:#4d9999;color:#fff}.datepicker-table td.is-outside-current-month,.datepicker-table td.is-disabled{color:rgba(0,0,0,0.3);pointer-events:none}.datepicker-day-button{background-color:transparent;border:0;line-height:38px;display:block;width:100%;border-radius:50%;padding:0 5px;cursor:pointer;color:inherit}.datepicker-day-button:focus{background-color:rgba(83,147,147,0.25)}.datepicker-footer{width:280px;margin:0 auto;padding-bottom:5px;display:flex;justify-content:space-between}.datepicker-cancel,.datepicker-clear,.datepicker-today,.datepicker-done{color:#4d9999;padding:0 1rem}.datepicker-clear{color:#f44336}@media only screen and (min-width:601px){.datepicker-modal{max-width:625px}.datepicker-container.modal-content{flex-direction:row}.datepicker-date-display{flex:0 1 270px}.datepicker-controls,.datepicker-table,.datepicker-footer{width:320px}.datepicker-day-button{line-height:44px}}.timepicker-modal{max-width:325px;max-height:none}.timepicker-container.modal-content{display:flex;flex-direction:column;padding:0}.text-primary{color:white}.timepicker-digital-display{flex:1 auto;background-color:#4d9999;padding:10px;font-weight:300}.timepicker-text-container{font-size:4rem;font-weight:bold;text-align:center;color:rgba(255,255,255,0.6);font-weight:400;position:relative;user-select:none}.timepicker-span-hours,.timepicker-span-minutes,.timepicker-span-am-pm div{cursor:pointer}.timepicker-span-hours{margin-right:3px}.timepicker-span-minutes{margin-left:3px}.timepicker-display-am-pm{font-size:1.3rem;position:absolute;right:1rem;bottom:1rem;font-weight:400}.timepicker-analog-display{flex:2.5 auto}.timepicker-plate{background-color:#eee;border-radius:50%;width:270px;height:270px;overflow:visible;position:relative;margin:auto;margin-top:25px;margin-bottom:5px;user-select:none}.timepicker-canvas,.timepicker-dial{position:absolute;left:0;right:0;top:0;bottom:0}.timepicker-minutes{visibility:hidden}.timepicker-tick{border-radius:50%;color:rgba(0,0,0,0.87);line-height:40px;text-align:center;width:40px;height:40px;position:absolute;cursor:pointer;font-size:15px}.timepicker-tick.active,.timepicker-tick:hover{background-color:rgba(77,153,153,0.25)}.timepicker-dial{transition:transform 350ms,opacity 350ms}.timepicker-dial-out{opacity:0}.timepicker-dial-out.timepicker-hours{transform:scale(1.1,1.1)}.timepicker-dial-out.timepicker-minutes{transform:scale(0.8,0.8)}.timepicker-canvas{transition:opacity 175ms}.timepicker-canvas line{stroke:#4d9999;stroke-width:4;stroke-linecap:round}.timepicker-canvas-out{opacity:.25}.timepicker-canvas-bearing{stroke:none;fill:#4d9999}.timepicker-canvas-bg{stroke:none;fill:#4d9999}.timepicker-footer{margin:0 auto;padding:5px 1rem;display:flex;justify-content:space-between}.timepicker-clear{color:#f44336}.timepicker-close{color:#4d9999}.timepicker-clear,.timepicker-close{padding:0 20px}@media only screen and (min-width:601px){.timepicker-modal{max-width:600px}.timepicker-container.modal-content{flex-direction:row}.timepicker-text-container{top:32%}.timepicker-display-am-pm{position:relative;right:auto;bottom:auto;text-align:center;margin-top:1.2rem}}.material-icons{font-family:'Material Icons';font-weight:normal;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:'liga';-webkit-font-smoothing:antialiased}.btn.disabled,.disabled.btn-large,.disabled.btn-small{pointer-events:auto}.grid{grid-auto-rows:min-content;display:inline-grid;width:100%}.grid .ghead,.grid .gbody,.grid .gfoot,.grid .gr{display:contents}.grid .gd,.grid .gh{display:grid;grid-auto-columns:1fr;justify-content:center;align-content:center;text-align:center;padding:15px}.grid .gh{align-content:baseline}.grid .gh .card{position:sticky;top:15px;bottom:15px}.grid .ghead{color:#b2b2b2}.grid .ghead .gh{z-index:8;border-bottom:1px solid #b2b2b2;max-height:40px;line-height:1em}.grid .gbody .gr.spacer{grid-column:1 / -1}.grid .gbody .separator{grid-column:1 / -1;border-top:1px solid #b2b2b2}.grid .pagination{grid-column:1 / -1}.grid .gbody>.gr>.gd{min-height:70px}.grid.striped .gbody>.gr:nth-child(odd) .gd{background-color:#ffeee6}.grid.striped .gbody>.gr:nth-child(odd):hover .gd{background-color:#f7f2ee}.grid.striped .gbody>.gr:nth-child(even):hover .gd{background-color:#eef6f6}.grid .gbody>.gr .gd.action{grid-auto-flow:column;grid-gap:5px}.grid .gbody>.gr .gd.action.side .btn,.grid .gbody>.gr .gd.action.side .btn-large,.grid .gbody>.gr .gd.action.side .btn-small{width:min-content}.grid .gbody>.gr>.gr.extendable>.gd.action{padding-top:0;padding-bottom:0;transition:padding .3s,max-height .3s}.grid .gbody>.gr>.gr.extendable>.gd.action .btn,.grid .gbody>.gr>.gr.extendable>.gd.action .btn-large,.grid .gbody>.gr>.gr.extendable>.gd.action .btn-small{max-height:0;transition:max-height .3s}.grid .gbody>.gr:focus-within .gd{background-color:#5cd6d6!important}.grid .gbody>.gr:focus-within>.gr.extendable>.gd.action{padding-bottom:15px}.grid .gbody>.gr:focus-within>.gr.extendable>.gd.action .btn,.grid .gbody>.gr:focus-within>.gr.extendable>.gd.action .btn-large,.grid .gbody>.gr:focus-within>.gr.extendable>.gd.action .btn-small{max-height:36px}#tooltip{opacity:.75;transition:opacity .3s,margin-top .3s;position:fixed;pointer-events:none;transform:translate(-50%,-100%);max-width:120px;width:120px;background-color:black;color:#fff;text-align:center;padding:5px;border-radius:6px;margin-top:-7px;font-size:11px;line-height:13px;z-index:1005}#tooltip.v-enter,#tooltip.v-leave-to{margin-top:3px;opacity:0}#tooltip::after{content:" ";position:absolute;left:50%;bottom:-10px;margin-left:-5px;border-width:5px;border-style:solid;border-color:black transparent transparent transparent}#documentation{position:fixed;display:flex;align-items:center;justify-content:center;z-index:2000;pointer-events:none;opacity:1;transition:opacity .3s}#documentation.v-enter,#documentation.v-leave-to{opacity:0}#documentation.v-enter .overlay,#documentation.v-leave-to .overlay{width:0!important;height:0!important}#documentation .overlay{position:fixed;border-radius:10050px;border:10000px solid rgba(0,0,0,0.66);box-sizing:content-box;transform:translate(-50%,-50%);transition:all .3s}#documentation.first .overlay{transition:opacity .3s,height .3s,width .3s}#documentation .content{position:absolute;font-size:1.5em;color:white;max-height:75%;max-width:75%}#documentation .content h1{text-align:center}#documentation .content *{color:white}#documentation .content>*:first-child{margin-top:0}#documentation .content>*:last-child{margin-bottom:0}#documentation svg{position:fixed;top:0;left:0;width:100%;height:100%;stroke-width:5px;fill:none;stroke:white}#documentation .next,#documentation .close{user-select:none;pointer-events:all!important}#documentation .close{top:16px;right:6px;padding-top:0}.dropdown-button{position:relative;display:block;overflow:visible;margin:12px 5px;line-height:1}.dropdown-button:focus .dropdown-content,.dropdown-button:focus-within .dropdown-content{display:block;opacity:1}.dropdown-button .dropdown-content{overflow:visible;top:calc(100% + 12px);left:auto;right:0;min-width:250px;width:min-content}.dropdown-button .dropdown-content::before{content:"";position:absolute;top:-20px;right:10px;border-width:10px;border-style:solid;border-color:transparent transparent white transparent}.dropdown-button .dropdown-content .dropdown-title{margin:0;padding:8px;font-weight:bold;border-bottom:1px solid #dddfe2}.dropdown-button .dropdown-content .dropdown-title .option{position:absolute;right:8px;font-weight:normal;cursor:pointer}.dropdown-button .dropdown-content .dropdown-title .option:hover{text-decoration:underline}.dropdown-button .dropdown-content li:hover{background-color:initial}.tabs{display:grid;background:initial}.tabs .tab:not(.disabled) a{cursor:pointer;position:relative}.tabs .tab:not(.disabled) a::after{position:absolute;content:"";background:#b84000;width:0;height:2px;bottom:0;left:50%;transform:translateX(-50%);transition:width .3s}.tabs .tab:not(.disabled) a:hover::after,.tabs .tab:not(.disabled) a.active::after{width:100%}.tabs .tab.disabled a{pointer:default}.arrow{border:solid black;border-width:0 2px 2px 0;border-top-left-radius:10px;display:inline-block;padding:3px;transition:transform .3s}.arrow.to-right{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}.arrow.to-left{transform:rotate(135deg);-webkit-transform:rotate(135deg)}.arrow.to-up{transform:rotate(-135deg);-webkit-transform:rotate(-135deg)}.arrow.to-down{transform:rotate(45deg);-webkit-transform:rotate(45deg)}.modal-wrapper.v-enter-active,.modal-wrapper.v-leave-active{transition:all .3s}.modal-wrapper.v-enter .modal,.modal-wrapper.v-leave-to .modal{opacity:0;transform:scale(0.5)}.modal-wrapper.v-enter .modal+.modal-overlay,.modal-wrapper.v-leave-to .modal+.modal-overlay{opacity:0}.modal-wrapper .modal{opacity:1;transform:none;display:block;top:10%;z-index:1003;min-width:900px;max-height:80vh;transition:opacity .3s ease-in,transform .3s ease-out}.modal-wrapper .modal .dragger{cursor:move;position:absolute;height:24px;width:24px}.modal-wrapper .modal .dragger:before{content:'.';color:#aaa;position:absolute;left:4.5px;top:1.5px;font-size:20px;line-height:0;text-shadow:0 5px,0 10px,5px 0,5px 5px,5px 10px,10px 0,10px 5px,10px 10px}.modal-wrapper .modal.modal-fixed-footer{height:auto;padding-bottom:56px;overflow:hidden}.modal-wrapper .modal.modal-fixed-footer .modal-content{position:initial;max-height:calc(80vh - 56px)}.modal-wrapper .modal+.modal-overlay{top:0;z-index:1002;display:block;opacity:.5;transition:opacity .3s ease-in}.modal-wrapper#confirmDialog .modal{top:15%;z-index:1005;width:50vw;min-width:500px}.modal-wrapper#confirmDialog .modal+.modal-overlay{z-index:1004}.input-field:focus-within>label{color:#4d9999;transform:translateY(-14px) scale(0.8);transform-origin:0 0}.input-field .helper-text.flash{animation:blinker 1s linear infinite}@keyframes blinker{50%{opacity:0}}.chips{padding-top:7px}.chips:focus-within{border-bottom:1px solid #4d9999;box-shadow:0 1px 0 0 #4d9999}.chips:empty ~ label{font-size:inherit;transform:none}.chips .input{height:32px;vertical-align:middle}.chips .input[disabled="disabled"]{border:0}.chip{cursor:pointer;user-select:none;color:white;background-color:#b2b2b2}.chip.negative{background-color:#b84000}.chip.positive{background-color:#4d9999}.chip.valid{background-color:#26a96c}.chip .close{height:24px;width:24px;margin:4px -7px 4px 4px;line-height:24px!important;border-radius:20px;text-align:center;padding:0;transition:background .3s}.chip .close:hover{background:rgba(0,0,0,0.3)}.toast{transition:margin-top .3s,opacity .3s}.toast.v-enter{margin-top:58px;opacity:0!important}.toast.v-leave-to{margin-top:-48px;opacity:0!important}.materialize-textarea{line-height:normal;padding:.8rem 0 .8rem 0;min-height:3rem;border-bottom:1px solid #b2b2b2;border-radius:0;outline:0;width:100%;font-size:16px;transition:box-shadow .3s,border .3s}.materialize-textarea:focus{outline:0;border-bottom:1px solid #4d9999;box-shadow:0 1px 0 0 #4d9999}::-webkit-scrollbar{width:12px;height:12px;border-radius:3px}::-webkit-scrollbar-track{background-color:#cecece;border-left:1px solid #cdc7c2}::-webkit-scrollbar-thumb{background-color:#7e8182;border:3px solid #cecece;border-radius:6px;min-height:40px}::-webkit-scrollbar-thumb:hover{background-color:#565b5c}::-webkit-scrollbar-thumb:active{background-color:#1b6acb}h1{color:#b84000}h2{color:#b84000}h3{color:#000}h4{color:#b84000}h5{color:#000}td,th{border-radius:0}strong{font-weight:bold}textarea{display:block}.btn,.btn-large,.btn-small{text-overflow:ellipsis;white-space:nowrap}.btn.primary-color:hover,.primary-color.btn-large:hover,.primary-color.btn-small:hover{background-color:#b84000}.container{width:85%!important}img{overflow:hidden;max-width:100%;max-height:100%}.clickable:hover{cursor:pointer;text-decoration:underline}.input-field .materialize-textarea{min-width:50px;font-size:inherit}.input-field .materialize-textarea:not([contenteditable]),.input-field .materialize-textarea[contenteditable="false"]{border-color:transparent}.input-field .materialize-textarea[placeholder]:empty::before{content:attr(placeholder);color:black;opacity:.25}[tabindex]:focus{outline:0;cursor:initial}[v-cloak]{display:none}[unselectable="on"]{-moz-user-select:-moz-none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.search-box>input{margin-bottom:0}html body{min-width:900px;overflow-y:scroll;overflow-x:auto}html body #app{--primary-color-hover:var(--primary-color)10;--secondary-color-hover:var(--secondary-color)10;display:flex;min-height:100vh;flex-direction:column}html body #app #help{margin:0 10px;cursor:pointer}html body #app.help{cursor:help}html body #app.help :not(.documented){pointer-events:none}html body #app.help .documented{pointer-events:all}html body #app>nav{height:64px;position:sticky;min-width:900px;width:100%;top:0;left:0;z-index:10}html body #app #loading{position:fixed;margin:auto;top:64px;border-radius:none;z-index:5}html body #app .current-view-wrapper{display:flex;flex-direction:column;min-height:calc(100vh - 64px);padding-bottom:30px}html body #app .current-view-wrapper .current-view{display:flex;flex-direction:column;flex:1}html body #app .current-view-wrapper .current-view>.container{display:flex;flex-direction:column;flex:1;width:85%}html body #app .current-view-wrapper .current-view>.container>#header{position:sticky;padding:0 17px;top:64px;background:white;display:grid;grid-template-columns:1fr max-content;height:60px;align-items:center;z-index:4}html body #app .current-view-wrapper .current-view>.container>#header>div{display:grid;grid-column-gap:.25em;grid-template-columns:max-content 1fr max-content max-content;align-items:center;margin-right:15px;width:fit-content}html body #app .current-view-wrapper .current-view>.container>#header>div>h1{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}html body #app .current-view-wrapper .current-view>.container>#header>div .author{color:#b84000;font-size:14px}html body #app .current-view-wrapper .current-view>.container>#header>div .details{margin:0;line-height:1em}html body #app .current-view-wrapper .current-view>.container>#header>div .details p{margin:0}html body #app .current-view-wrapper .current-view>.container>#header #backTo{position:absolute;top:18px;left:0}html body #app .current-view-wrapper .current-view>.container>.grid{flex:1}html body #app .current-view-wrapper .current-view>.container>.grid>.ghead .gh{position:sticky;top:124px;background:white;z-index:8}html body #app .current-view-wrapper .current-view>.container>.grid .gh>.card{top:179px}html body #app .page-footer .contributors a{display:flex;height:70px;align-items:center;justify-content:center;float:left;margin-right:50px}html body #app .page-footer .contributors a img{max-width:180px;max-height:100%}@media only print{html body #app>nav{display:none}html body #app .current-view{padding-top:0}html body #app .current-view>.container{width:100%}html body #app .current-view>.container>#header{top:0}}.switch label{position:relative}.card{display:block}@media only screen and (max-width:600px){.card{max-width:120px}}@media only screen and (min-width:601px){.card{max-width:160px}}@media only screen and (min-width:993px){.card{max-width:200px}}@media only screen and (min-width:1201px){.card{max-width:240px}}.card h2{max-height:43px;min-height:43px;overflow-y:auto}.card-image{width:100%;margin:auto}@media only screen and (max-width:600px){.card-image{width:120px;height:calc(120px / 3 * 2)}}@media only screen and (min-width:601px){.card-image{width:160px;height:calc(160px / 3 * 2)}}@media only screen and (min-width:993px){.card-image{width:200px;height:calc(200px / 3 * 2)}}@media only screen and (min-width:1201px){.card-image{width:240px;height:calc(240px / 3 * 2)}}.card-image img{height:auto!important;width:auto!important;margin:auto}.light-color{background:#eef6f6}.primary-color{background:#b84000;color:white}nav #logoContainer{z-index:1;float:left}nav #logoContainer img{vertical-align:middle;margin-bottom:5px}nav .menu a{position:relative}nav .menu a::after{position:absolute;content:"";background:white;width:0;height:2px;bottom:0;left:50%;transform:translateX(-50%);transition:width .3s}nav .menu a:hover::after,nav .menu a.active::after{width:100%}nav #userSettings .dropdown-content a.btn,nav #userSettings .dropdown-content a.btn-large,nav #userSettings .dropdown-content a.btn-small{background:#b2b2b2;color:white;width:calc(100% - 30px);margin:10px 15px}nav #userSettings .dropdown-content #changePasswd{margin:5px}nav #userSettings .dropdown-content #changePasswd .input-field input:not(:focus){border-bottom:1px solid}nav #notifications{position:relative}nav #notifications #notificationCount{position:absolute;cursor:pointer;top:15px;right:17px;border-radius:2px;padding:1px 3px;line-height:1.3;min-height:1.3em;min-width:0;font-size:10px;background-color:#f44336}nav #notifications .dropdown-button{width:40px;height:40px;padding:0;border-radius:100px}nav #notifications .dropdown-button i{cursor:pointer;text-align:center;line-height:40px;height:40px}nav #notifications .dropdown-button:focus,nav #notifications .dropdown-button:focus-within{background-color:rgba(0,0,0,0.1)}nav #notifications .dropdown-content{width:460px}nav #notifications .dropdown-content ul{height:calc(100vh - 112px);max-height:600px;overflow:auto}nav #notifications .dropdown-content ul li{position:relative;margin-right:25px;border-bottom:1px solid #dddfe2}nav #notifications .dropdown-content ul li.unread{background-color:#ffeee6}nav #notifications .dropdown-content ul li.unread .read-toggle{border-width:3px}nav #notifications .dropdown-content ul li.unread:hover{background-color:#f7f2ee}nav #notifications .dropdown-content ul li:hover{background-color:#eef6f6}nav #notifications .dropdown-content ul li:hover .read-toggle{opacity:1}nav #notifications .dropdown-content ul li a{padding:5px 16px;font-size:14px}nav #notifications .dropdown-content ul li a .arg{font-weight:bold}nav #notifications .dropdown-content ul li a:hover{background-color:initial}nav #notifications .dropdown-content ul li .read-toggle{position:absolute;opacity:0;right:10px;top:10px;width:10px;height:10px;padding:0;border:5px solid #b2b2b2;border-radius:10px;transition:opacity .3s}nav #notifications .dropdown-content ul li .read-toggle:hover{border-color:#808080}#login>div{justify-content:center}#login>div #loginForm{width:500px}#aafImport .progress{width:490px}#home #welcomeCallout{margin:0;color:#b84000}#home #welcomeCallout img{max-height:100px}@media only screen and (min-width:993px){#home #welcomeCallout img{margin-left:50px}}@media only screen and (max-width:600px){#home #welcomeCallout img{display:none}}#home #categoriesList .col{display:inline-block;float:none}#debates .opinion{height:16px;width:100%;background-color:#b2b2b2}#debates .opinion .for{height:100%;float:left;background-color:#4d9999}#debates .opinion .against{height:100%;float:right;background-color:#ba4100}#debate .comment-mark,.comment .comment-mark{display:inline}@media only print{#debate{height:auto!important}#debate .selection>div{max-height:none!important}#debate .selection::before,#debate .selection::after{content:none}#debate #documentContainer,#debate #commentsContainer{height:auto!important}}#debate .row{margin:0}#debate #options{position:sticky;padding:0 17px;top:124px;background:white;z-index:2;text-align:right}#debate #options .col{padding:0}#debate #options #sortCommentsBy,#debate #options #leftDisplay{position:absolute;bottom:0}#debate #options #sortCommentsBy input+i,#debate #options #leftDisplay input+i{font-style:normal}#debate #options #sortCommentsBy input:checked+i,#debate #options #leftDisplay input:checked+i{font-weight:bold}#debate #options .search-box{margin:0}#debate #options .search-box>input{margin-bottom:5px;margin-top:-5px}#debate #mainContainer{height:calc(100vh - 170px)}#debate #documentContainer,#debate #commentsContainer{width:50%;height:100%;float:left}#debate #documentContainer .scroll-area,#debate #commentsContainer .scroll-area{height:100%;overflow-y:scroll}#debate #commentsContainer.loading{position:relative;overflow-x:hidden}#debate #commentsContainer.loading::before,#debate #commentsContainer.loading::after{content:"";display:block;top:0;left:0;width:100%;height:100%;position:absolute}#debate #commentsContainer.loading::before{background:#e0e0e0;z-index:1}#debate #commentsContainer.loading::after{background:linear-gradient(90deg,transparent,rgba(255,255,255,0.3),transparent);transform:translateX(-100%);animation:loading 1.5s infinite;z-index:1}@keyframes loading{100%{transform:translateX(100%)}}#debate #documentContainer .scroll-area{direction:rtl}#debate #documentContainer .scroll-area>*{direction:ltr}#debate #documentContainer{z-index:1}#debate #documentContainer .scroll-area{padding-left:5px}#debate #documentContainer .scroll-area .wrap{display:flex;min-height:100%}#debate #documentContainer .scroll-area .wrap #documentDisplay{text-align:justify;font-size:13px;line-height:1.42;width:calc(100% - 60px);float:left}#debate #documentContainer .scroll-area .wrap #documentDisplay::selection,#debate #documentContainer .scroll-area .wrap #documentDisplay ::selection{background-color:#c6e4e3}#debate #documentContainer .scroll-area .wrap .bullets-container{float:left}#debate .selection_popup{position:absolute;cursor:pointer;background:#4d9999;color:white;border-radius:5px;padding:0 5px}#debate .selection_popup::before{content:"";position:absolute;border-width:8px 5px;border-style:solid}#debate .selection_popup.top{margin-top:-7px;margin-left:-15px;transform:translateY(-100%)}#debate .selection_popup.top::before{bottom:-16px;left:10px;border-color:#4d9999 transparent transparent transparent}#debate .selection_popup.bottom{margin-top:7px;margin-left:15px;transform:translateX(-100%)}#debate .selection_popup.bottom::before{top:-16px;right:10px;border-color:transparent transparent #4d9999 transparent}#debate .comment-container.moderated::after{content:"";position:absolute;top:0;left:0;height:100%;width:100%;background-color:#f44336;opacity:50%}#debate .answers-container{overflow:hidden}#debate .answers-container .answers{overflow-y:hidden;padding:0 5px 0 10px;transition:margin-top .3s}#debate .answers-container .answers.v-enter-active{transition:all 0s}#debate .comment-body .selection,#debate .spaghetti-data .selection{cursor:pointer}#debate .comment-body .selection:hover,#debate .comment-body .selection.active,#debate .spaghetti-data .selection:hover,#debate .spaghetti-data .selection.active{background:#ebecee;border-left-color:#808080;border-right-color:#808080}#debate .comment-body .selection:hover::before,#debate .comment-body .selection.active::before,#debate .spaghetti-data .selection:hover::before,#debate .spaghetti-data .selection.active::before{background-image:linear-gradient(#ebecee,transparent)}#debate .comment-body .selection:hover::after,#debate .comment-body .selection.active::after,#debate .spaghetti-data .selection:hover::after,#debate .spaghetti-data .selection.active::after{background-image:linear-gradient(transparent,#ebecee)}#debate .bullets-container{position:relative;width:50px;margin:0 5px}#debate .bullets-container .bullets-box{position:absolute;height:1em;width:100%;display:flex;align-items:center;justify-content:space-evenly}#debate .bullets-container .bullets-box .bullet{height:10px;width:10px}#debate .bullets-container .bullets-box .bullet::before{content:"";display:block;width:100%;height:100%;box-sizing:border-box;border-radius:10px}#debate .bullets-container .bullets-box .bullet.for::before{background:#4d9999}#debate .bullets-container .bullets-box .bullet.neutral::before{background:#b2b2b2}#debate .bullets-container .bullets-box .bullet.against::before{background:#ba4100}#debate .bullets-container .bullets-box .bullet:hover{cursor:pointer;z-index:2;width:8px;height:8px;margin:1px}#debate .bullets-container .bullets-box .bullets-drop-down{min-width:10px;padding:5px;border-radius:10px;box-sizing:content-box;line-height:10px;font-size:10px;text-align:center;z-index:1;font-weight:bold;color:white;transition:box-shadow .3s}#debate .bullets-container .bullets-box .bullets-drop-down.for{background:#4d9999}#debate .bullets-container .bullets-box .bullets-drop-down.against{background:#ba4100}#debate .bullets-container .bullets-box .bullets-drop-down.neutral{background:#b2b2b2}#debate .bullets-container .bullets-box .bullets-drop-down>.label{overflow:hidden;height:10px;transition:height .3s}#debate .bullets-container .bullets-box .bullets-drop-down>.body{transition:height .3s;overflow:hidden}#debate .bullets-container .bullets-box:not(:hover) .bullets-drop-down{box-shadow:4px 0 0 -1px #ddd,4px 0 1px -1px black,8px 0 0 -2px #bbb,8px 0 1px -2px black,12px 0 0 -3px #aaa,12px 0 1px -3px black}#debate .bullets-container .bullets-box:not(:hover) .bullets-drop-down>.body{height:0!important}#debate .bullets-container .bullets-box:hover .bullets-drop-down{z-index:9999;background:white!important;width:10px}#debate .bullets-container .bullets-box:hover .bullets-drop-down>.label{height:0}#debate .spaghetti-data{width:50%;float:left}#debate .spaghetti-data>.theme{display:grid;grid-template-columns:min-content 1fr;align-items:center}#debate .spaghetti-data>.theme .close{cursor:pointer;margin-bottom:10px}#debate svg.spaghettis{position:fixed;pointer-events:none;top:0;left:0;width:100%;height:100%;stroke-width:3px}#debate svg.spaghettis use{fill:none;stroke-width:6px;cursor:pointer;pointer-events:initial}#debate svg.spaghettis path{fill:none;stroke-width:inherit;pointer-events:initial}#debate svg.spaghettis path.trigger{stroke-width:20px}#debate svg.spaghettis>g{transition:opacity .3s}#debate svg.spaghettis.hover>g{opacity:.25}.comment{position:relative;font-size:13px;padding:3px 5px;margin-bottom:5px;box-sizing:border-box;border-left:3px solid;outline-width:3px;outline-offset:-3px}.comment .close{position:absolute;cursor:pointer;top:0;right:.5em}.comment.for{border-color:#4d9999;outline-color:#4d9999}.comment.for .comment-header *{color:#4d9999}.comment.neutral{border-color:#b2b2b2;outline-color:#b2b2b2}.comment.neutral .comment-header *{color:#b2b2b2}.comment.against{border-color:#ba4100;outline-color:#ba4100}.comment.against .comment-header *{color:#ba4100}.comment:focus-within{outline-style:solid;outline-width:3px}.comment .comment-header .username{display:inline-block;margin-right:10px;margin-top:0}.comment .comment-header .comment-count{cursor:pointer}.comment .comment-body .reformulation-wrapper,.comment .comment-body .argumentation-wrapper{display:grid;grid-template-columns:20px 1fr 60px}.comment .comment-body .reformulation-wrapper>i,.comment .comment-body .reformulation-wrapper>.tags>i,.comment .comment-body .argumentation-wrapper>i,.comment .comment-body .argumentation-wrapper>.tags>i{font-size:18px;margin-top:1px}.comment .comment-body .reformulation-wrapper .reformulation{white-space:pre-wrap}.comment .comment-body .reformulation-wrapper .tags{margin:0 20px}.comment .comment-body .reformulation-wrapper .tags i{cursor:pointer;text-shadow:0 0 1px black,0 0 1px black,0 0 1px black,0 0 1px black;color:white}.comment .comment-body .reformulation-wrapper .tags.disabled i{cursor:default;opacity:.5}.comment .comment-body .argumentation-wrapper .argumentation{white-space:pre-wrap}.comment .comment-body .argumentation-wrapper .argumentation::selection{background-color:#c6e4e3}.selection{overflow:hidden;position:relative;background:#dddfe2;border-left:3px solid #b2b2b2;border-right:3px solid #b2b2b2;border-radius:5px;transition:background .3s,border-color .3s;text-align:justify;font-size:13px;line-height:1.42;margin-bottom:10px}.selection>div>*:nth-last-child(1){margin-bottom:0}.selection::after,.selection::before{position:absolute;content:"";width:100%;height:10px;background-image:linear-gradient(transparent,#dddfe2);left:0;bottom:0}.selection::before{background-image:linear-gradient(#dddfe2,transparent);top:0}.selection>div{max-height:100px;overflow:auto;padding:5px}.selection>div *:nth-child(1){margin-top:0}.selection>div *:nth-last-child(1){margin-bottom:0}#commentModal .modal{resize:horizontal;min-width:500px}#commentModal #argumentation .materialize-textarea{min-height:6em}#commentModal .input-field:focus-within>#reformulationCheck svg .line{stroke:#4d9999;stroke-width:2px}#commentModal #reformulationCheck{display:flex;align-items:center;background:#fafafa;position:absolute;right:0;bottom:-19px}@keyframes spin{from{transform:rotate(0deg) translate(-3px) rotate(0deg)}to{transform:rotate(360deg) translate(-3px) rotate(-360deg)}}#commentModal #reformulationCheck.loading svg .pupil{animation:spin 2s linear infinite}#commentModal #reformulationCheck svg{fill:none;stroke:none}#commentModal #reformulationCheck svg .eye{stroke:#e5e5e5}#commentModal #reformulationCheck svg .eyelid{fill:#e5e5e5}#commentModal #reformulationCheck svg .pupil{fill:#666}#commentModal #reformulationCheck svg .line,#commentModal #reformulationCheck svg .mouth{stroke:#9e9e9e;transition:stroke .3s,stroke-width .3s}#commentModal #reformulationCheck svg+span{font-size:10px;border:1px solid #9e9e9e;margin-left:7px;margin-bottom:5px;padding:0 5px}#commentModal #reformulationCheck svg+span::before{content:"";position:absolute;top:10px;left:36px;border:solid #9e9e9e;border-width:0 1px 1px 0;padding:3px;background:#fafafa;transform:rotate(135deg)}#commentModal #opinion{padding-bottom:1rem}#commentModal #opinion input+span{padding-left:16px}#commentModal #opinion input+span::before{display:none}#commentModal #opinion input+span::after{display:none}#commentModal #opinion input:checked+span{box-shadow:0 3px 3px 0 rgba(0,0,0,0.14) inset,0 1px 7px 0 rgba(0,0,0,0.12) inset,0 3px 1px -1px rgba(0,0,0,0.2) inset}#commentModal #opinion input:not(:checked)+span:not(:hover){opacity:.5}#commentModal #opinion label>.against{background-color:#ba4100}#commentModal #opinion label>.neutral{background-color:#b2b2b2}#commentModal #opinion label>.for{background-color:#4d9999}#commentModal #hypostase .list{display:grid;width:100%;grid-template-columns:1fr 1fr 1fr 1fr 1fr;transition:height .3s;height:27px}#commentModal #hypostase .list.expert{height:219px}#commentModal #hypostase .list input[type="checkbox"]{display:none}#commentModal #hypostase .list>div>.btn,#commentModal #hypostase .list>div>.btn-large,#commentModal #hypostase .list>div>.btn-small{display:block;height:auto;line-height:initial;text-align:center;padding:0;cursor:pointer;margin:3px;padding:2px 5px!important;text-transform:none}#commentModal #hypostase .list>div>.btn:first-of-type,#commentModal #hypostase .list>div>.btn-large:first-of-type,#commentModal #hypostase .list>div>.btn-small:first-of-type{font-weight:bold}#commentModal #hypostase .list>div>.btn:not(:hover),#commentModal #hypostase .list>div>.btn-large:not(:hover),#commentModal #hypostase .list>div>.btn-small:not(:hover){opacity:.75}#commentModal #hypostase .list>div input:checked+.btn,#commentModal #hypostase .list>div input:checked+.btn-large,#commentModal #hypostase .list>div input:checked+.btn-small{background:#4d9999 linear-gradient(0deg,#4d9999 0,#4d9999 100%);box-shadow:0 3px 3px 0 rgba(0,0,0,0.14) inset,0 1px 7px 0 rgba(0,0,0,0.12) inset,0 3px 1px -1px rgba(0,0,0,0.2) inset;opacity:1}#documents .grid .gr.header .gh:hover{background-color:#eef6f6}#documents .grid .gr.header .card-action{line-height:0;padding-top:0;padding-bottom:0;border:0;transition:all .3s}#documents .grid .gr.header .card-action .btn,#documents .grid .gr.header .card-action .btn-large,#documents .grid .gr.header .card-action .btn-small{max-height:0}#documents .grid .gr.header:focus-within .gh{background-color:#5cd6d6!important}#documents .grid .gr.header:focus-within .card-action{padding-bottom:15px}#documents .grid .gr.header:focus-within .card-action .btn,#documents .grid .gr.header:focus-within .card-action .btn-large,#documents .grid .gr.header:focus-within .card-action .btn-small{max-height:36px}#document .input-field.inline{margin:0}#document .input-field{margin-bottom:1px}#document .ql-toolbar{position:sticky;top:124px;background:white;z-index:10;height:42px;overflow:hidden;transition:height .3s,padding .3s}#document .ql-container{margin-top:-1px;background:white;border-top:1px solid #ccc;transition:margin-top .3s}#document .ql-container .ql-editor{margin-bottom:10px;text-align:justify;transition:height .3s}#document #documentDisplay:not(.in-edition) .ql-toolbar{height:0;padding-top:0;padding-bottom:0;border-bottom-width:0}#createDebate .steps>.tabs{position:sticky;top:75px;z-index:9;display:block;margin-top:-50px;text-align:center;border:0;height:auto;background:white}#createDebate .steps>.tabs .tab{height:auto}#createDebate .steps>.tabs .tab a{text-transform:capitalize;line-height:1em}#createDebate .steps>.tabs .tab a::after{content:none}#createDebate .steps>.tabs .tab:not(.disabled) a.active img,#createDebate .steps>.tabs .tab:not(.disabled) a:hover img{border:1px solid #5cd6d6;border-radius:200px;margin:0 -1px}#createDebate .steps>.tabs .tab.disabled a img{filter:grayscale(100%)}#createDebate .steps .grid>.ghead .gh{position:sticky;top:202px;background:white;z-index:8}#createDebate .steps .grid .gh .card{top:242px}#createDebate .steps #contributors>div>.tabs{position:sticky;top:202px;background:white;z-index:8}#createDebate .steps #contributors .grid>.ghead .gh{position:sticky;top:250px;background:white;z-index:8}#createDebate .steps .collection-item>span{display:inline-block;max-width:calc(100% - 40px)}#createDebate .steps .collection-item .close{cursor:pointer}#createDebate #advancedOptions>li{cursor:pointer}#createDebate #advancedOptions>li .arrow{right:20px;position:absolute}#createDebate #advancedOptions #advancedOptionsBody{overflow:hidden}#createDebate #advancedOptions #advancedOptionsBody>ul{transition:margin-top .3s}#contributors .search-box{width:20em;margin:0}#sort-options{height:46px}#sort-options select{width:50%;float:left;margin:0}#sort-options .input-field{width:20em;max-width:50%;float:right;margin:0}#teams #header>div>select{text-overflow:ellipsis;color:#b84000}#teams .search-box{margin:0}#restitution .detail{background:white;margin-right:10px;margin-bottom:10px}#restitution .detail .document{padding:1px 10px;text-align:justify;font-size:13px;line-height:1.42}#restitution .D3_tree{width:100%;overflow:auto;height:calc(100vh - 172px);position:relative}#restitution .D3_tree .detail{background:white;position:sticky;height:min-content;width:50%;top:10px;left:calc(50% - 10px)}#restitution .D3_tree svg{position:absolute;pointer-events:all}#restitution .D3_tree svg .nodes text{font:12px sans-serif}#restitution .D3_tree svg .nodes .bullet{cursor:pointer}#restitution .D3_tree svg .nodes .bullet:hover{r:4px}#restitution .D3_tree svg .nodes .with-children text{cursor:pointer}#restitution .D3_tree svg .nodes .with-children .bullet:hover{r:3px}#restitution .D3_tree svg .links{fill:none;stroke:black;stroke-width:.5px;stroke-opacity:.5}#restitution .D3_pie{width:100%;height:calc(100vh - 172px);position:relative;display:grid;grid-template-rows:40px 1fr;grid-template-columns:50% 50%}#restitution .D3_pie svg{pointer-events:all}#restitution .D3_pie svg .detailsCircle{fill-opacity:.35;fill:none}#restitution .D3_pie svg .detailsText{text-anchor:middle}#restitution .D3_sunburst{width:100%;height:calc(100vh - 172px);overflow:auto;display:grid;grid-template-rows:40px 1fr;grid-template-columns:50% 50%}#restitution .D3_sunburst svg{position:sticky;top:40px;pointer-events:all}#restitution .D3_sunburst svg .slices path{stroke:none;cursor:pointer}#restitution .D3_pie .switch,#restitution .D3_sunburst .switch{padding:9px 0;align-self:center;background:white;position:sticky;top:0}#restitution .D3_pie .legend,#restitution .D3_sunburst .legend{height:100%;overflow:auto;display:flex;flex-flow:column wrap;align-content:flex-start}#restitution .D3_pie .legend>div,#restitution .D3_sunburst .legend>div{cursor:default;padding-right:10px;height:1.4em;overflow:hidden;transition:height .3s ease,opacity .3s ease}#restitution .D3_pie .legend>div.v-enter,#restitution .D3_pie .legend>div.v-leave-to,#restitution .D3_sunburst .legend>div.v-enter,#restitution .D3_sunburst .legend>div.v-leave-to{opacity:0;height:0}#restitution .D3_pie .legend>div:hover,#restitution .D3_pie .legend>div.active,#restitution .D3_sunburst .legend>div:hover,#restitution .D3_sunburst .legend>div.active{background:#eef6f6}#restitution .D3_pie .legend>div .square,#restitution .D3_sunburst .legend>div .square{display:inline-block;vertical-align:middle;width:1em;height:1em;border:1px solid black;margin-right:5px}#restitution #tagsRestitution{margin:0;height:calc(100vh - 194px)}#restitution #tagsRestitution>.col{height:100%;margin:0;padding:15px 0;overflow:auto}#restitution #tagsRestitution>.col .chip{opacity:.5;padding-left:5px;transition:opacity .3s}#restitution #tagsRestitution>.col .chip.active{opacity:1}#restitution #tagsRestitution>.col .chip [type="checkbox"]{display:none}#restitution #tagsRestitution>.col .chip [type="checkbox"]+span{font-size:inherit;padding-left:25px}#restitution #tagsRestitution>.col .chip [type="checkbox"]+span::before,#restitution #tagsRestitution>.col .chip [type="checkbox"]+span::after{content:'';position:absolute;left:0;top:0;margin:4px;width:16px;height:16px;z-index:0;-webkit-transition:.28s ease;transition:.28s ease;border-radius:50%}#restitution #tagsRestitution>.col .chip [type="checkbox"]:checked+span::before{border-color:white;transform:none}#restitution #tagsRestitution>.col .chip [type="checkbox"]:checked+span::after{transform:scale(0.5);background-color:white} \ No newline at end of file diff --git a/src/main/webapp/assets/css/quill.snow.css b/src/main/webapp/assets/css/quill.snow.css new file mode 100644 index 0000000..8bdc607 --- /dev/null +++ b/src/main/webapp/assets/css/quill.snow.css @@ -0,0 +1,945 @@ +/*! + * Quill Editor v1.3.6 + * https://quilljs.com/ + * Copyright (c) 2014, Jason Chen + * Copyright (c) 2013, salesforce.com + */ +.ql-container { + box-sizing: border-box; + font-family: Helvetica, Arial, sans-serif; + font-size: 13px; + height: 100%; + margin: 0px; + position: relative; +} +.ql-container.ql-disabled .ql-tooltip { + visibility: hidden; +} +.ql-container.ql-disabled .ql-editor ul[data-checked] > li::before { + pointer-events: none; +} +.ql-clipboard { + left: -100000px; + height: 1px; + overflow-y: hidden; + position: absolute; + top: 50%; +} +.ql-clipboard p { + margin: 0; + padding: 0; +} +.ql-editor { + box-sizing: border-box; + line-height: 1.42; + height: 100%; + outline: none; + overflow-y: auto; + padding: 12px 15px; + tab-size: 4; + -moz-tab-size: 4; + text-align: left; + white-space: pre-wrap; + word-wrap: break-word; +} +.ql-editor > * { + cursor: text; +} +.ql-editor p, +.ql-editor ol, +.ql-editor ul, +.ql-editor pre, +.ql-editor blockquote, +.ql-editor h1, +.ql-editor h2, +.ql-editor h3, +.ql-editor h4, +.ql-editor h5, +.ql-editor h6 { + margin: 0; + padding: 0; + counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol, +.ql-editor ul { + padding-left: 1.5em; +} +.ql-editor ol > li, +.ql-editor ul > li { + list-style-type: none; +} +.ql-editor ul > li::before { + content: '\2022'; +} +.ql-editor ul[data-checked=true], +.ql-editor ul[data-checked=false] { + pointer-events: none; +} +.ql-editor ul[data-checked=true] > li *, +.ql-editor ul[data-checked=false] > li * { + pointer-events: all; +} +.ql-editor ul[data-checked=true] > li::before, +.ql-editor ul[data-checked=false] > li::before { + color: #777; + cursor: pointer; + pointer-events: all; +} +.ql-editor ul[data-checked=true] > li::before { + content: '\2611'; +} +.ql-editor ul[data-checked=false] > li::before { + content: '\2610'; +} +.ql-editor li::before { + display: inline-block; + white-space: nowrap; + width: 1.2em; +} +.ql-editor li:not(.ql-direction-rtl)::before { + margin-left: -1.5em; + margin-right: 0.3em; + text-align: right; +} +.ql-editor li.ql-direction-rtl::before { + margin-left: 0.3em; + margin-right: -1.5em; +} +.ql-editor ol li:not(.ql-direction-rtl), +.ql-editor ul li:not(.ql-direction-rtl) { + padding-left: 1.5em; +} +.ql-editor ol li.ql-direction-rtl, +.ql-editor ul li.ql-direction-rtl { + padding-right: 1.5em; +} +.ql-editor ol li { + counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; + counter-increment: list-0; +} +.ql-editor ol li:before { + content: counter(list-0, decimal) '. '; +} +.ql-editor ol li.ql-indent-1 { + counter-increment: list-1; +} +.ql-editor ol li.ql-indent-1:before { + content: counter(list-1, lower-alpha) '. '; +} +.ql-editor ol li.ql-indent-1 { + counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-2 { + counter-increment: list-2; +} +.ql-editor ol li.ql-indent-2:before { + content: counter(list-2, lower-roman) '. '; +} +.ql-editor ol li.ql-indent-2 { + counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-3 { + counter-increment: list-3; +} +.ql-editor ol li.ql-indent-3:before { + content: counter(list-3, decimal) '. '; +} +.ql-editor ol li.ql-indent-3 { + counter-reset: list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-4 { + counter-increment: list-4; +} +.ql-editor ol li.ql-indent-4:before { + content: counter(list-4, lower-alpha) '. '; +} +.ql-editor ol li.ql-indent-4 { + counter-reset: list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-5 { + counter-increment: list-5; +} +.ql-editor ol li.ql-indent-5:before { + content: counter(list-5, lower-roman) '. '; +} +.ql-editor ol li.ql-indent-5 { + counter-reset: list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-6 { + counter-increment: list-6; +} +.ql-editor ol li.ql-indent-6:before { + content: counter(list-6, decimal) '. '; +} +.ql-editor ol li.ql-indent-6 { + counter-reset: list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-7 { + counter-increment: list-7; +} +.ql-editor ol li.ql-indent-7:before { + content: counter(list-7, lower-alpha) '. '; +} +.ql-editor ol li.ql-indent-7 { + counter-reset: list-8 list-9; +} +.ql-editor ol li.ql-indent-8 { + counter-increment: list-8; +} +.ql-editor ol li.ql-indent-8:before { + content: counter(list-8, lower-roman) '. '; +} +.ql-editor ol li.ql-indent-8 { + counter-reset: list-9; +} +.ql-editor ol li.ql-indent-9 { + counter-increment: list-9; +} +.ql-editor ol li.ql-indent-9:before { + content: counter(list-9, decimal) '. '; +} +.ql-editor .ql-indent-1:not(.ql-direction-rtl) { + padding-left: 3em; +} +.ql-editor li.ql-indent-1:not(.ql-direction-rtl) { + padding-left: 4.5em; +} +.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right { + padding-right: 3em; +} +.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right { + padding-right: 4.5em; +} +.ql-editor .ql-indent-2:not(.ql-direction-rtl) { + padding-left: 6em; +} +.ql-editor li.ql-indent-2:not(.ql-direction-rtl) { + padding-left: 7.5em; +} +.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right { + padding-right: 6em; +} +.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right { + padding-right: 7.5em; +} +.ql-editor .ql-indent-3:not(.ql-direction-rtl) { + padding-left: 9em; +} +.ql-editor li.ql-indent-3:not(.ql-direction-rtl) { + padding-left: 10.5em; +} +.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right { + padding-right: 9em; +} +.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right { + padding-right: 10.5em; +} +.ql-editor .ql-indent-4:not(.ql-direction-rtl) { + padding-left: 12em; +} +.ql-editor li.ql-indent-4:not(.ql-direction-rtl) { + padding-left: 13.5em; +} +.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right { + padding-right: 12em; +} +.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right { + padding-right: 13.5em; +} +.ql-editor .ql-indent-5:not(.ql-direction-rtl) { + padding-left: 15em; +} +.ql-editor li.ql-indent-5:not(.ql-direction-rtl) { + padding-left: 16.5em; +} +.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right { + padding-right: 15em; +} +.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right { + padding-right: 16.5em; +} +.ql-editor .ql-indent-6:not(.ql-direction-rtl) { + padding-left: 18em; +} +.ql-editor li.ql-indent-6:not(.ql-direction-rtl) { + padding-left: 19.5em; +} +.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right { + padding-right: 18em; +} +.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right { + padding-right: 19.5em; +} +.ql-editor .ql-indent-7:not(.ql-direction-rtl) { + padding-left: 21em; +} +.ql-editor li.ql-indent-7:not(.ql-direction-rtl) { + padding-left: 22.5em; +} +.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right { + padding-right: 21em; +} +.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right { + padding-right: 22.5em; +} +.ql-editor .ql-indent-8:not(.ql-direction-rtl) { + padding-left: 24em; +} +.ql-editor li.ql-indent-8:not(.ql-direction-rtl) { + padding-left: 25.5em; +} +.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right { + padding-right: 24em; +} +.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right { + padding-right: 25.5em; +} +.ql-editor .ql-indent-9:not(.ql-direction-rtl) { + padding-left: 27em; +} +.ql-editor li.ql-indent-9:not(.ql-direction-rtl) { + padding-left: 28.5em; +} +.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right { + padding-right: 27em; +} +.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right { + padding-right: 28.5em; +} +.ql-editor .ql-video { + display: block; + max-width: 100%; +} +.ql-editor .ql-video.ql-align-center { + margin: 0 auto; +} +.ql-editor .ql-video.ql-align-right { + margin: 0 0 0 auto; +} +.ql-editor .ql-bg-black { + background-color: #000; +} +.ql-editor .ql-bg-red { + background-color: #e60000; +} +.ql-editor .ql-bg-orange { + background-color: #f90; +} +.ql-editor .ql-bg-yellow { + background-color: #ff0; +} +.ql-editor .ql-bg-green { + background-color: #008a00; +} +.ql-editor .ql-bg-blue { + background-color: #06c; +} +.ql-editor .ql-bg-purple { + background-color: #93f; +} +.ql-editor .ql-color-white { + color: #fff; +} +.ql-editor .ql-color-red { + color: #e60000; +} +.ql-editor .ql-color-orange { + color: #f90; +} +.ql-editor .ql-color-yellow { + color: #ff0; +} +.ql-editor .ql-color-green { + color: #008a00; +} +.ql-editor .ql-color-blue { + color: #06c; +} +.ql-editor .ql-color-purple { + color: #93f; +} +.ql-editor .ql-font-serif { + font-family: Georgia, Times New Roman, serif; +} +.ql-editor .ql-font-monospace { + font-family: Monaco, Courier New, monospace; +} +.ql-editor .ql-size-small { + font-size: 0.75em; +} +.ql-editor .ql-size-large { + font-size: 1.5em; +} +.ql-editor .ql-size-huge { + font-size: 2.5em; +} +.ql-editor .ql-direction-rtl { + direction: rtl; + text-align: inherit; +} +.ql-editor .ql-align-center { + text-align: center; +} +.ql-editor .ql-align-justify { + text-align: justify; +} +.ql-editor .ql-align-right { + text-align: right; +} +.ql-editor.ql-blank::before { + color: rgba(0,0,0,0.6); + content: attr(data-placeholder); + font-style: italic; + left: 15px; + pointer-events: none; + position: absolute; + right: 15px; +} +.ql-snow.ql-toolbar:after, +.ql-snow .ql-toolbar:after { + clear: both; + content: ''; + display: table; +} +.ql-snow.ql-toolbar button, +.ql-snow .ql-toolbar button { + background: none; + border: none; + cursor: pointer; + display: inline-block; + float: left; + height: 24px; + padding: 3px 5px; + width: 28px; +} +.ql-snow.ql-toolbar button svg, +.ql-snow .ql-toolbar button svg { + float: left; + height: 100%; +} +.ql-snow.ql-toolbar button:active:hover, +.ql-snow .ql-toolbar button:active:hover { + outline: none; +} +.ql-snow.ql-toolbar input.ql-image[type=file], +.ql-snow .ql-toolbar input.ql-image[type=file] { + display: none; +} +.ql-snow.ql-toolbar button:hover, +.ql-snow .ql-toolbar button:hover, +.ql-snow.ql-toolbar button:focus, +.ql-snow .ql-toolbar button:focus, +.ql-snow.ql-toolbar button.ql-active, +.ql-snow .ql-toolbar button.ql-active, +.ql-snow.ql-toolbar .ql-picker-label:hover, +.ql-snow .ql-toolbar .ql-picker-label:hover, +.ql-snow.ql-toolbar .ql-picker-label.ql-active, +.ql-snow .ql-toolbar .ql-picker-label.ql-active, +.ql-snow.ql-toolbar .ql-picker-item:hover, +.ql-snow .ql-toolbar .ql-picker-item:hover, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected { + color: #06c; +} +.ql-snow.ql-toolbar button:hover .ql-fill, +.ql-snow .ql-toolbar button:hover .ql-fill, +.ql-snow.ql-toolbar button:focus .ql-fill, +.ql-snow .ql-toolbar button:focus .ql-fill, +.ql-snow.ql-toolbar button.ql-active .ql-fill, +.ql-snow .ql-toolbar button.ql-active .ql-fill, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill, +.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill, +.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill, +.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill, +.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill, +.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill, +.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill { + fill: #06c; +} +.ql-snow.ql-toolbar button:hover .ql-stroke, +.ql-snow .ql-toolbar button:hover .ql-stroke, +.ql-snow.ql-toolbar button:focus .ql-stroke, +.ql-snow .ql-toolbar button:focus .ql-stroke, +.ql-snow.ql-toolbar button.ql-active .ql-stroke, +.ql-snow .ql-toolbar button.ql-active .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke, +.ql-snow.ql-toolbar button:hover .ql-stroke-miter, +.ql-snow .ql-toolbar button:hover .ql-stroke-miter, +.ql-snow.ql-toolbar button:focus .ql-stroke-miter, +.ql-snow .ql-toolbar button:focus .ql-stroke-miter, +.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter, +.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter { + stroke: #06c; +} +@media (pointer: coarse) { + .ql-snow.ql-toolbar button:hover:not(.ql-active), + .ql-snow .ql-toolbar button:hover:not(.ql-active) { + color: #444; + } + .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill, + .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill, + .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill, + .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill { + fill: #444; + } + .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke, + .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke, + .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter, + .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter { + stroke: #444; + } +} +.ql-snow { + box-sizing: border-box; +} +.ql-snow * { + box-sizing: border-box; +} +.ql-snow .ql-hidden { + display: none; +} +.ql-snow .ql-out-bottom, +.ql-snow .ql-out-top { + visibility: hidden; +} +.ql-snow .ql-tooltip { + position: absolute; + transform: translateY(10px); +} +.ql-snow .ql-tooltip a { + cursor: pointer; + text-decoration: none; +} +.ql-snow .ql-tooltip.ql-flip { + transform: translateY(-10px); +} +.ql-snow .ql-formats { + display: inline-block; + vertical-align: middle; +} +.ql-snow .ql-formats:after { + clear: both; + content: ''; + display: table; +} +.ql-snow .ql-stroke { + fill: none; + stroke: #444; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 2; +} +.ql-snow .ql-stroke-miter { + fill: none; + stroke: #444; + stroke-miterlimit: 10; + stroke-width: 2; +} +.ql-snow .ql-fill, +.ql-snow .ql-stroke.ql-fill { + fill: #444; +} +.ql-snow .ql-empty { + fill: none; +} +.ql-snow .ql-even { + fill-rule: evenodd; +} +.ql-snow .ql-thin, +.ql-snow .ql-stroke.ql-thin { + stroke-width: 1; +} +.ql-snow .ql-transparent { + opacity: 0.4; +} +.ql-snow .ql-direction svg:last-child { + display: none; +} +.ql-snow .ql-direction.ql-active svg:last-child { + display: inline; +} +.ql-snow .ql-direction.ql-active svg:first-child { + display: none; +} +.ql-snow .ql-editor h1 { + font-size: 2em; +} +.ql-snow .ql-editor h2 { + font-size: 1.5em; +} +.ql-snow .ql-editor h3 { + font-size: 1.17em; +} +.ql-snow .ql-editor h4 { + font-size: 1em; +} +.ql-snow .ql-editor h5 { + font-size: 0.83em; +} +.ql-snow .ql-editor h6 { + font-size: 0.67em; +} +.ql-snow .ql-editor a { + text-decoration: underline; +} +.ql-snow .ql-editor blockquote { + border-left: 4px solid #ccc; + margin-bottom: 5px; + margin-top: 5px; + padding-left: 16px; +} +.ql-snow .ql-editor code, +.ql-snow .ql-editor pre { + background-color: #f0f0f0; + border-radius: 3px; +} +.ql-snow .ql-editor pre { + white-space: pre-wrap; + margin-bottom: 5px; + margin-top: 5px; + padding: 5px 10px; +} +.ql-snow .ql-editor code { + font-size: 85%; + padding: 2px 4px; +} +.ql-snow .ql-editor pre.ql-syntax { + background-color: #23241f; + color: #f8f8f2; + overflow: visible; +} +.ql-snow .ql-editor img { + max-width: 100%; +} +.ql-snow .ql-picker { + color: #444; + display: inline-block; + float: left; + font-size: 14px; + font-weight: 500; + height: 24px; + position: relative; + vertical-align: middle; +} +.ql-snow .ql-picker-label { + cursor: pointer; + display: inline-block; + height: 100%; + padding-left: 8px; + padding-right: 2px; + position: relative; + width: 100%; +} +.ql-snow .ql-picker-label::before { + display: inline-block; + line-height: 22px; +} +.ql-snow .ql-picker-options { + background-color: #fff; + display: none; + min-width: 100%; + padding: 4px 8px; + position: absolute; + white-space: nowrap; +} +.ql-snow .ql-picker-options .ql-picker-item { + cursor: pointer; + display: block; + padding-bottom: 5px; + padding-top: 5px; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-label { + color: #ccc; + z-index: 2; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill { + fill: #ccc; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke { + stroke: #ccc; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-options { + display: block; + margin-top: -1px; + top: 100%; + z-index: 1; +} +.ql-snow .ql-color-picker, +.ql-snow .ql-icon-picker { + width: 28px; +} +.ql-snow .ql-color-picker .ql-picker-label, +.ql-snow .ql-icon-picker .ql-picker-label { + padding: 2px 4px; +} +.ql-snow .ql-color-picker .ql-picker-label svg, +.ql-snow .ql-icon-picker .ql-picker-label svg { + right: 4px; +} +.ql-snow .ql-icon-picker .ql-picker-options { + padding: 4px 0px; +} +.ql-snow .ql-icon-picker .ql-picker-item { + height: 24px; + width: 24px; + padding: 2px 4px; +} +.ql-snow .ql-color-picker .ql-picker-options { + padding: 3px 5px; + width: 152px; +} +.ql-snow .ql-color-picker .ql-picker-item { + border: 1px solid transparent; + float: left; + height: 16px; + margin: 2px; + padding: 0px; + width: 16px; +} +.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg { + position: absolute; + margin-top: -9px; + right: 0; + top: 50%; + width: 18px; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=''])::before { + content: attr(data-label); +} +.ql-snow .ql-picker.ql-header { + width: 98px; +} +.ql-snow .ql-picker.ql-header .ql-picker-label::before, +.ql-snow .ql-picker.ql-header .ql-picker-item::before { + content: 'Normal'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { + content: 'Heading 1'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { + content: 'Heading 2'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { + content: 'Heading 3'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { + content: 'Heading 4'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { + content: 'Heading 5'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { + content: 'Heading 6'; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { + font-size: 2em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { + font-size: 1.5em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { + font-size: 1.17em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { + font-size: 1em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { + font-size: 0.83em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { + font-size: 0.67em; +} +.ql-snow .ql-picker.ql-font { + width: 108px; +} +.ql-snow .ql-picker.ql-font .ql-picker-label::before, +.ql-snow .ql-picker.ql-font .ql-picker-item::before { + content: 'Sans Serif'; +} +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before { + content: 'Serif'; +} +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before { + content: 'Monospace'; +} +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before { + font-family: Georgia, Times New Roman, serif; +} +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before { + font-family: Monaco, Courier New, monospace; +} +.ql-snow .ql-picker.ql-size { + width: 98px; +} +.ql-snow .ql-picker.ql-size .ql-picker-label::before, +.ql-snow .ql-picker.ql-size .ql-picker-item::before { + content: 'Normal'; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before { + content: 'Small'; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before { + content: 'Large'; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before { + content: 'Huge'; +} +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before { + font-size: 10px; +} +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before { + font-size: 18px; +} +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before { + font-size: 32px; +} +.ql-snow .ql-color-picker.ql-background .ql-picker-item { + background-color: #fff; +} +.ql-snow .ql-color-picker.ql-color .ql-picker-item { + background-color: #000; +} +.ql-toolbar.ql-snow { + border: 1px solid #ccc; + box-sizing: border-box; + font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + padding: 8px; +} +.ql-toolbar.ql-snow .ql-formats { + margin-right: 15px; +} +.ql-toolbar.ql-snow .ql-picker-label { + border: 1px solid transparent; +} +.ql-toolbar.ql-snow .ql-picker-options { + border: 1px solid transparent; + box-shadow: rgba(0,0,0,0.2) 0 2px 8px; +} +.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label { + border-color: #ccc; +} +.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options { + border-color: #ccc; +} +.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected, +.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover { + border-color: #000; +} +.ql-toolbar.ql-snow + .ql-container.ql-snow { + border-top: 0px; +} +.ql-snow .ql-tooltip { + background-color: #fff; + border: 1px solid #ccc; + box-shadow: 0px 0px 5px #ddd; + color: #444; + padding: 5px 12px; + white-space: nowrap; +} +.ql-snow .ql-tooltip::before { + content: "Visit URL:"; + line-height: 26px; + margin-right: 8px; +} +.ql-snow .ql-tooltip input[type=text] { + display: none; + border: 1px solid #ccc; + font-size: 13px; + height: 26px; + margin: 0px; + padding: 3px 5px; + width: 170px; +} +.ql-snow .ql-tooltip a.ql-preview { + display: inline-block; + max-width: 200px; + overflow-x: hidden; + text-overflow: ellipsis; + vertical-align: top; +} +.ql-snow .ql-tooltip a.ql-action::after { + border-right: 1px solid #ccc; + content: 'Edit'; + margin-left: 16px; + padding-right: 8px; +} +.ql-snow .ql-tooltip a.ql-remove::before { + content: 'Remove'; + margin-left: 8px; +} +.ql-snow .ql-tooltip a { + line-height: 26px; +} +.ql-snow .ql-tooltip.ql-editing a.ql-preview, +.ql-snow .ql-tooltip.ql-editing a.ql-remove { + display: none; +} +.ql-snow .ql-tooltip.ql-editing input[type=text] { + display: inline-block; +} +.ql-snow .ql-tooltip.ql-editing a.ql-action::after { + border-right: 0px; + content: 'Save'; + padding-right: 0px; +} +.ql-snow .ql-tooltip[data-mode=link]::before { + content: "Enter link:"; +} +.ql-snow .ql-tooltip[data-mode=formula]::before { + content: "Enter formula:"; +} +.ql-snow .ql-tooltip[data-mode=video]::before { + content: "Enter video:"; +} +.ql-snow a { + color: #06c; +} +.ql-container.ql-snow { + border: 1px solid #ccc; +} diff --git a/src/main/webapp/assets/css/quill.snow.min.css b/src/main/webapp/assets/css/quill.snow.min.css new file mode 100644 index 0000000..70c895e --- /dev/null +++ b/src/main/webapp/assets/css/quill.snow.min.css @@ -0,0 +1,6 @@ +/*! + * Quill Editor v1.3.6 + * https://quilljs.com/ + * Copyright (c) 2014, Jason Chen + * Copyright (c) 2013, salesforce.com + */.ql-container{box-sizing:border-box;font-family:Helvetica,Arial,sans-serif;font-size:13px;height:100%;margin:0;position:relative}.ql-container.ql-disabled .ql-tooltip{visibility:hidden}.ql-container.ql-disabled .ql-editor ul[data-checked]>li::before{pointer-events:none}.ql-clipboard{left:-100000px;height:1px;overflow-y:hidden;position:absolute;top:50%}.ql-clipboard p{margin:0;padding:0}.ql-editor{box-sizing:border-box;line-height:1.42;height:100%;outline:0;overflow-y:auto;padding:12px 15px;tab-size:4;-moz-tab-size:4;text-align:left;white-space:pre-wrap;word-wrap:break-word}.ql-editor>*{cursor:text}.ql-editor p,.ql-editor ol,.ql-editor ul,.ql-editor pre,.ql-editor blockquote,.ql-editor h1,.ql-editor h2,.ql-editor h3,.ql-editor h4,.ql-editor h5,.ql-editor h6{margin:0;padding:0;counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol,.ql-editor ul{padding-left:1.5em}.ql-editor ol>li,.ql-editor ul>li{list-style-type:none}.ql-editor ul>li::before{content:'\2022'}.ql-editor ul[data-checked=true],.ql-editor ul[data-checked=false]{pointer-events:none}.ql-editor ul[data-checked=true]>li *,.ql-editor ul[data-checked=false]>li *{pointer-events:all}.ql-editor ul[data-checked=true]>li::before,.ql-editor ul[data-checked=false]>li::before{color:#777;cursor:pointer;pointer-events:all}.ql-editor ul[data-checked=true]>li::before{content:'\2611'}.ql-editor ul[data-checked=false]>li::before{content:'\2610'}.ql-editor li::before{display:inline-block;white-space:nowrap;width:1.2em}.ql-editor li:not(.ql-direction-rtl)::before{margin-left:-1.5em;margin-right:.3em;text-align:right}.ql-editor li.ql-direction-rtl::before{margin-left:.3em;margin-right:-1.5em}.ql-editor ol li:not(.ql-direction-rtl),.ql-editor ul li:not(.ql-direction-rtl){padding-left:1.5em}.ql-editor ol li.ql-direction-rtl,.ql-editor ul li.ql-direction-rtl{padding-right:1.5em}.ql-editor ol li{counter-reset:list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;counter-increment:list-0}.ql-editor ol li:before{content:counter(list-0,decimal) '. '}.ql-editor ol li.ql-indent-1{counter-increment:list-1}.ql-editor ol li.ql-indent-1:before{content:counter(list-1,lower-alpha) '. '}.ql-editor ol li.ql-indent-1{counter-reset:list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-2{counter-increment:list-2}.ql-editor ol li.ql-indent-2:before{content:counter(list-2,lower-roman) '. '}.ql-editor ol li.ql-indent-2{counter-reset:list-3 list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-3{counter-increment:list-3}.ql-editor ol li.ql-indent-3:before{content:counter(list-3,decimal) '. '}.ql-editor ol li.ql-indent-3{counter-reset:list-4 list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-4{counter-increment:list-4}.ql-editor ol li.ql-indent-4:before{content:counter(list-4,lower-alpha) '. '}.ql-editor ol li.ql-indent-4{counter-reset:list-5 list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-5{counter-increment:list-5}.ql-editor ol li.ql-indent-5:before{content:counter(list-5,lower-roman) '. '}.ql-editor ol li.ql-indent-5{counter-reset:list-6 list-7 list-8 list-9}.ql-editor ol li.ql-indent-6{counter-increment:list-6}.ql-editor ol li.ql-indent-6:before{content:counter(list-6,decimal) '. '}.ql-editor ol li.ql-indent-6{counter-reset:list-7 list-8 list-9}.ql-editor ol li.ql-indent-7{counter-increment:list-7}.ql-editor ol li.ql-indent-7:before{content:counter(list-7,lower-alpha) '. '}.ql-editor ol li.ql-indent-7{counter-reset:list-8 list-9}.ql-editor ol li.ql-indent-8{counter-increment:list-8}.ql-editor ol li.ql-indent-8:before{content:counter(list-8,lower-roman) '. '}.ql-editor ol li.ql-indent-8{counter-reset:list-9}.ql-editor ol li.ql-indent-9{counter-increment:list-9}.ql-editor ol li.ql-indent-9:before{content:counter(list-9,decimal) '. '}.ql-editor .ql-indent-1:not(.ql-direction-rtl){padding-left:3em}.ql-editor li.ql-indent-1:not(.ql-direction-rtl){padding-left:4.5em}.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:3em}.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right{padding-right:4.5em}.ql-editor .ql-indent-2:not(.ql-direction-rtl){padding-left:6em}.ql-editor li.ql-indent-2:not(.ql-direction-rtl){padding-left:7.5em}.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:6em}.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right{padding-right:7.5em}.ql-editor .ql-indent-3:not(.ql-direction-rtl){padding-left:9em}.ql-editor li.ql-indent-3:not(.ql-direction-rtl){padding-left:10.5em}.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:9em}.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right{padding-right:10.5em}.ql-editor .ql-indent-4:not(.ql-direction-rtl){padding-left:12em}.ql-editor li.ql-indent-4:not(.ql-direction-rtl){padding-left:13.5em}.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:12em}.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right{padding-right:13.5em}.ql-editor .ql-indent-5:not(.ql-direction-rtl){padding-left:15em}.ql-editor li.ql-indent-5:not(.ql-direction-rtl){padding-left:16.5em}.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:15em}.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right{padding-right:16.5em}.ql-editor .ql-indent-6:not(.ql-direction-rtl){padding-left:18em}.ql-editor li.ql-indent-6:not(.ql-direction-rtl){padding-left:19.5em}.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:18em}.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right{padding-right:19.5em}.ql-editor .ql-indent-7:not(.ql-direction-rtl){padding-left:21em}.ql-editor li.ql-indent-7:not(.ql-direction-rtl){padding-left:22.5em}.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:21em}.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right{padding-right:22.5em}.ql-editor .ql-indent-8:not(.ql-direction-rtl){padding-left:24em}.ql-editor li.ql-indent-8:not(.ql-direction-rtl){padding-left:25.5em}.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:24em}.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right{padding-right:25.5em}.ql-editor .ql-indent-9:not(.ql-direction-rtl){padding-left:27em}.ql-editor li.ql-indent-9:not(.ql-direction-rtl){padding-left:28.5em}.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:27em}.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right{padding-right:28.5em}.ql-editor .ql-video{display:block;max-width:100%}.ql-editor .ql-video.ql-align-center{margin:0 auto}.ql-editor .ql-video.ql-align-right{margin:0 0 0 auto}.ql-editor .ql-bg-black{background-color:#000}.ql-editor .ql-bg-red{background-color:#e60000}.ql-editor .ql-bg-orange{background-color:#f90}.ql-editor .ql-bg-yellow{background-color:#ff0}.ql-editor .ql-bg-green{background-color:#008a00}.ql-editor .ql-bg-blue{background-color:#06c}.ql-editor .ql-bg-purple{background-color:#93f}.ql-editor .ql-color-white{color:#fff}.ql-editor .ql-color-red{color:#e60000}.ql-editor .ql-color-orange{color:#f90}.ql-editor .ql-color-yellow{color:#ff0}.ql-editor .ql-color-green{color:#008a00}.ql-editor .ql-color-blue{color:#06c}.ql-editor .ql-color-purple{color:#93f}.ql-editor .ql-font-serif{font-family:Georgia,Times New Roman,serif}.ql-editor .ql-font-monospace{font-family:Monaco,Courier New,monospace}.ql-editor .ql-size-small{font-size:.75em}.ql-editor .ql-size-large{font-size:1.5em}.ql-editor .ql-size-huge{font-size:2.5em}.ql-editor .ql-direction-rtl{direction:rtl;text-align:inherit}.ql-editor .ql-align-center{text-align:center}.ql-editor .ql-align-justify{text-align:justify}.ql-editor .ql-align-right{text-align:right}.ql-editor.ql-blank::before{color:rgba(0,0,0,0.6);content:attr(data-placeholder);font-style:italic;left:15px;pointer-events:none;position:absolute;right:15px}.ql-snow.ql-toolbar:after,.ql-snow .ql-toolbar:after{clear:both;content:'';display:table}.ql-snow.ql-toolbar button,.ql-snow .ql-toolbar button{background:0;border:0;cursor:pointer;display:inline-block;float:left;height:24px;padding:3px 5px;width:28px}.ql-snow.ql-toolbar button svg,.ql-snow .ql-toolbar button svg{float:left;height:100%}.ql-snow.ql-toolbar button:active:hover,.ql-snow .ql-toolbar button:active:hover{outline:0}.ql-snow.ql-toolbar input.ql-image[type=file],.ql-snow .ql-toolbar input.ql-image[type=file]{display:none}.ql-snow.ql-toolbar button:hover,.ql-snow .ql-toolbar button:hover,.ql-snow.ql-toolbar button:focus,.ql-snow .ql-toolbar button:focus,.ql-snow.ql-toolbar button.ql-active,.ql-snow .ql-toolbar button.ql-active,.ql-snow.ql-toolbar .ql-picker-label:hover,.ql-snow .ql-toolbar .ql-picker-label:hover,.ql-snow.ql-toolbar .ql-picker-label.ql-active,.ql-snow .ql-toolbar .ql-picker-label.ql-active,.ql-snow.ql-toolbar .ql-picker-item:hover,.ql-snow .ql-toolbar .ql-picker-item:hover,.ql-snow.ql-toolbar .ql-picker-item.ql-selected,.ql-snow .ql-toolbar .ql-picker-item.ql-selected{color:#06c}.ql-snow.ql-toolbar button:hover .ql-fill,.ql-snow .ql-toolbar button:hover .ql-fill,.ql-snow.ql-toolbar button:focus .ql-fill,.ql-snow .ql-toolbar button:focus .ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill{fill:#06c}.ql-snow.ql-toolbar button:hover .ql-stroke,.ql-snow .ql-toolbar button:hover .ql-stroke,.ql-snow.ql-toolbar button:focus .ql-stroke,.ql-snow .ql-toolbar button:focus .ql-stroke,.ql-snow.ql-toolbar button.ql-active .ql-stroke,.ql-snow .ql-toolbar button.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,.ql-snow.ql-toolbar button:hover .ql-stroke-miter,.ql-snow .ql-toolbar button:hover .ql-stroke-miter,.ql-snow.ql-toolbar button:focus .ql-stroke-miter,.ql-snow .ql-toolbar button:focus .ql-stroke-miter,.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter{stroke:#06c}@media(pointer:coarse){.ql-snow.ql-toolbar button:hover:not(.ql-active),.ql-snow .ql-toolbar button:hover:not(.ql-active){color:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill{fill:#444}.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke,.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter{stroke:#444}}.ql-snow{box-sizing:border-box}.ql-snow *{box-sizing:border-box}.ql-snow .ql-hidden{display:none}.ql-snow .ql-out-bottom,.ql-snow .ql-out-top{visibility:hidden}.ql-snow .ql-tooltip{position:absolute;transform:translateY(10px)}.ql-snow .ql-tooltip a{cursor:pointer;text-decoration:none}.ql-snow .ql-tooltip.ql-flip{transform:translateY(-10px)}.ql-snow .ql-formats{display:inline-block;vertical-align:middle}.ql-snow .ql-formats:after{clear:both;content:'';display:table}.ql-snow .ql-stroke{fill:none;stroke:#444;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.ql-snow .ql-stroke-miter{fill:none;stroke:#444;stroke-miterlimit:10;stroke-width:2}.ql-snow .ql-fill,.ql-snow .ql-stroke.ql-fill{fill:#444}.ql-snow .ql-empty{fill:none}.ql-snow .ql-even{fill-rule:evenodd}.ql-snow .ql-thin,.ql-snow .ql-stroke.ql-thin{stroke-width:1}.ql-snow .ql-transparent{opacity:.4}.ql-snow .ql-direction svg:last-child{display:none}.ql-snow .ql-direction.ql-active svg:last-child{display:inline}.ql-snow .ql-direction.ql-active svg:first-child{display:none}.ql-snow .ql-editor h1{font-size:2em}.ql-snow .ql-editor h2{font-size:1.5em}.ql-snow .ql-editor h3{font-size:1.17em}.ql-snow .ql-editor h4{font-size:1em}.ql-snow .ql-editor h5{font-size:.83em}.ql-snow .ql-editor h6{font-size:.67em}.ql-snow .ql-editor a{text-decoration:underline}.ql-snow .ql-editor blockquote{border-left:4px solid #ccc;margin-bottom:5px;margin-top:5px;padding-left:16px}.ql-snow .ql-editor code,.ql-snow .ql-editor pre{background-color:#f0f0f0;border-radius:3px}.ql-snow .ql-editor pre{white-space:pre-wrap;margin-bottom:5px;margin-top:5px;padding:5px 10px}.ql-snow .ql-editor code{font-size:85%;padding:2px 4px}.ql-snow .ql-editor pre.ql-syntax{background-color:#23241f;color:#f8f8f2;overflow:visible}.ql-snow .ql-editor img{max-width:100%}.ql-snow .ql-picker{color:#444;display:inline-block;float:left;font-size:14px;font-weight:500;height:24px;position:relative;vertical-align:middle}.ql-snow .ql-picker-label{cursor:pointer;display:inline-block;height:100%;padding-left:8px;padding-right:2px;position:relative;width:100%}.ql-snow .ql-picker-label::before{display:inline-block;line-height:22px}.ql-snow .ql-picker-options{background-color:#fff;display:none;min-width:100%;padding:4px 8px;position:absolute;white-space:nowrap}.ql-snow .ql-picker-options .ql-picker-item{cursor:pointer;display:block;padding-bottom:5px;padding-top:5px}.ql-snow .ql-picker.ql-expanded .ql-picker-label{color:#ccc;z-index:2}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill{fill:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke{stroke:#ccc}.ql-snow .ql-picker.ql-expanded .ql-picker-options{display:block;margin-top:-1px;top:100%;z-index:1}.ql-snow .ql-color-picker,.ql-snow .ql-icon-picker{width:28px}.ql-snow .ql-color-picker .ql-picker-label,.ql-snow .ql-icon-picker .ql-picker-label{padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-label svg,.ql-snow .ql-icon-picker .ql-picker-label svg{right:4px}.ql-snow .ql-icon-picker .ql-picker-options{padding:4px 0}.ql-snow .ql-icon-picker .ql-picker-item{height:24px;width:24px;padding:2px 4px}.ql-snow .ql-color-picker .ql-picker-options{padding:3px 5px;width:152px}.ql-snow .ql-color-picker .ql-picker-item{border:1px solid transparent;float:left;height:16px;margin:2px;padding:0;width:16px}.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg{position:absolute;margin-top:-9px;right:0;top:50%;width:18px}.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=''])::before,.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=''])::before,.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=''])::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=''])::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=''])::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=''])::before{content:attr(data-label)}.ql-snow .ql-picker.ql-header{width:98px}.ql-snow .ql-picker.ql-header .ql-picker-label::before,.ql-snow .ql-picker.ql-header .ql-picker-item::before{content:'Normal'}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before{content:'Heading 1'}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before{content:'Heading 2'}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before{content:'Heading 3'}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before{content:'Heading 4'}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before{content:'Heading 5'}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before{content:'Heading 6'}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before{font-size:2em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before{font-size:1.5em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before{font-size:1.17em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before{font-size:1em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before{font-size:.83em}.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before{font-size:.67em}.ql-snow .ql-picker.ql-font{width:108px}.ql-snow .ql-picker.ql-font .ql-picker-label::before,.ql-snow .ql-picker.ql-font .ql-picker-item::before{content:'Sans Serif'}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before{content:'Serif'}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before{content:'Monospace'}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before{font-family:Georgia,Times New Roman,serif}.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before{font-family:Monaco,Courier New,monospace}.ql-snow .ql-picker.ql-size{width:98px}.ql-snow .ql-picker.ql-size .ql-picker-label::before,.ql-snow .ql-picker.ql-size .ql-picker-item::before{content:'Normal'}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before{content:'Small'}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before{content:'Large'}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before{content:'Huge'}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before{font-size:10px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before{font-size:18px}.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before{font-size:32px}.ql-snow .ql-color-picker.ql-background .ql-picker-item{background-color:#fff}.ql-snow .ql-color-picker.ql-color .ql-picker-item{background-color:#000}.ql-toolbar.ql-snow{border:1px solid #ccc;box-sizing:border-box;font-family:'Helvetica Neue','Helvetica','Arial',sans-serif;padding:8px}.ql-toolbar.ql-snow .ql-formats{margin-right:15px}.ql-toolbar.ql-snow .ql-picker-label{border:1px solid transparent}.ql-toolbar.ql-snow .ql-picker-options{border:1px solid transparent;box-shadow:rgba(0,0,0,0.2) 0 2px 8px}.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label{border-color:#ccc}.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options{border-color:#ccc}.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected,.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover{border-color:#000}.ql-toolbar.ql-snow+.ql-container.ql-snow{border-top:0}.ql-snow .ql-tooltip{background-color:#fff;border:1px solid #ccc;box-shadow:0 0 5px #ddd;color:#444;padding:5px 12px;white-space:nowrap}.ql-snow .ql-tooltip::before{content:"Visit URL:";line-height:26px;margin-right:8px}.ql-snow .ql-tooltip input[type=text]{display:none;border:1px solid #ccc;font-size:13px;height:26px;margin:0;padding:3px 5px;width:170px}.ql-snow .ql-tooltip a.ql-preview{display:inline-block;max-width:200px;overflow-x:hidden;text-overflow:ellipsis;vertical-align:top}.ql-snow .ql-tooltip a.ql-action::after{border-right:1px solid #ccc;content:'Edit';margin-left:16px;padding-right:8px}.ql-snow .ql-tooltip a.ql-remove::before{content:'Remove';margin-left:8px}.ql-snow .ql-tooltip a{line-height:26px}.ql-snow .ql-tooltip.ql-editing a.ql-preview,.ql-snow .ql-tooltip.ql-editing a.ql-remove{display:none}.ql-snow .ql-tooltip.ql-editing input[type=text]{display:inline-block}.ql-snow .ql-tooltip.ql-editing a.ql-action::after{border-right:0;content:'Save';padding-right:0}.ql-snow .ql-tooltip[data-mode=link]::before{content:"Enter link:"}.ql-snow .ql-tooltip[data-mode=formula]::before{content:"Enter formula:"}.ql-snow .ql-tooltip[data-mode=video]::before{content:"Enter video:"}.ql-snow a{color:#06c}.ql-container.ql-snow{border:1px solid #ccc} \ No newline at end of file diff --git a/src/main/webapp/assets/font/material-icons.woff b/src/main/webapp/assets/font/material-icons.woff new file mode 100644 index 0000000..db9f554 Binary files /dev/null and b/src/main/webapp/assets/font/material-icons.woff differ diff --git a/src/main/webapp/assets/font/seravek-bold-webfont.woff b/src/main/webapp/assets/font/seravek-bold-webfont.woff new file mode 100644 index 0000000..bc50d55 Binary files /dev/null and b/src/main/webapp/assets/font/seravek-bold-webfont.woff differ diff --git a/src/main/webapp/assets/font/seravek-light-webfont.woff b/src/main/webapp/assets/font/seravek-light-webfont.woff new file mode 100644 index 0000000..f0b041d Binary files /dev/null and b/src/main/webapp/assets/font/seravek-light-webfont.woff differ diff --git a/src/main/webapp/assets/font/seravek-medium-webfont.woff b/src/main/webapp/assets/font/seravek-medium-webfont.woff new file mode 100644 index 0000000..13c17fa Binary files /dev/null and b/src/main/webapp/assets/font/seravek-medium-webfont.woff differ diff --git a/src/main/webapp/assets/font/seravek-regular-webfont.woff b/src/main/webapp/assets/font/seravek-regular-webfont.woff new file mode 100644 index 0000000..434583a Binary files /dev/null and b/src/main/webapp/assets/font/seravek-regular-webfont.woff differ diff --git a/src/main/webapp/assets/img/Aren-icones-clic-01.svg b/src/main/webapp/assets/img/Aren-icones-clic-01.svg new file mode 100644 index 0000000..8eafef1 --- /dev/null +++ b/src/main/webapp/assets/img/Aren-icones-clic-01.svg @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/assets/img/Aren-icones-clic-02.svg b/src/main/webapp/assets/img/Aren-icones-clic-02.svg new file mode 100644 index 0000000..e274ae2 --- /dev/null +++ b/src/main/webapp/assets/img/Aren-icones-clic-02.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/assets/img/Aren-icones-clic-03.svg b/src/main/webapp/assets/img/Aren-icones-clic-03.svg new file mode 100644 index 0000000..9c7af48 --- /dev/null +++ b/src/main/webapp/assets/img/Aren-icones-clic-03.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/assets/img/Aren-icones-dispo-01.svg b/src/main/webapp/assets/img/Aren-icones-dispo-01.svg new file mode 100644 index 0000000..9213c33 --- /dev/null +++ b/src/main/webapp/assets/img/Aren-icones-dispo-01.svg @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/assets/img/Aren-icones-dispo-02.svg b/src/main/webapp/assets/img/Aren-icones-dispo-02.svg new file mode 100644 index 0000000..e304291 --- /dev/null +++ b/src/main/webapp/assets/img/Aren-icones-dispo-02.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/assets/img/Aren-icones-dispo-03.svg b/src/main/webapp/assets/img/Aren-icones-dispo-03.svg new file mode 100644 index 0000000..ec9d7cf --- /dev/null +++ b/src/main/webapp/assets/img/Aren-icones-dispo-03.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/assets/img/Aren-logo.svg b/src/main/webapp/assets/img/Aren-logo.svg new file mode 100644 index 0000000..72fe52f --- /dev/null +++ b/src/main/webapp/assets/img/Aren-logo.svg @@ -0,0 +1,620 @@ + +image/svg+xml diff --git a/src/main/webapp/assets/img/Aren-logold.svg b/src/main/webapp/assets/img/Aren-logold.svg new file mode 100644 index 0000000..eeb5c5a --- /dev/null +++ b/src/main/webapp/assets/img/Aren-logold.svg @@ -0,0 +1,358 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/assets/img/GitHub-Mark-Light-120px-plus.png b/src/main/webapp/assets/img/GitHub-Mark-Light-120px-plus.png new file mode 100644 index 0000000..192846a Binary files /dev/null and b/src/main/webapp/assets/img/GitHub-Mark-Light-120px-plus.png differ diff --git a/src/main/webapp/assets/img/GitHub-Mark-Light-32px.png b/src/main/webapp/assets/img/GitHub-Mark-Light-32px.png new file mode 100644 index 0000000..628da97 Binary files /dev/null and b/src/main/webapp/assets/img/GitHub-Mark-Light-32px.png differ diff --git a/src/main/webapp/assets/img/GitHub_Logo_White.png b/src/main/webapp/assets/img/GitHub_Logo_White.png new file mode 100644 index 0000000..5b106f1 Binary files /dev/null and b/src/main/webapp/assets/img/GitHub_Logo_White.png differ diff --git a/src/main/webapp/assets/img/LIRMM_logo.png b/src/main/webapp/assets/img/LIRMM_logo.png new file mode 100644 index 0000000..4fa3558 Binary files /dev/null and b/src/main/webapp/assets/img/LIRMM_logo.png differ diff --git a/src/main/webapp/assets/img/against.png b/src/main/webapp/assets/img/against.png new file mode 100644 index 0000000..067ea54 Binary files /dev/null and b/src/main/webapp/assets/img/against.png differ diff --git a/src/main/webapp/assets/img/favicon.ico b/src/main/webapp/assets/img/favicon.ico new file mode 100644 index 0000000..e77b1b2 Binary files /dev/null and b/src/main/webapp/assets/img/favicon.ico differ diff --git a/src/main/webapp/assets/img/for.png b/src/main/webapp/assets/img/for.png new file mode 100644 index 0000000..ee6b9da Binary files /dev/null and b/src/main/webapp/assets/img/for.png differ diff --git a/src/main/webapp/assets/img/imageleves.png b/src/main/webapp/assets/img/imageleves.png new file mode 100644 index 0000000..fccf2d8 Binary files /dev/null and b/src/main/webapp/assets/img/imageleves.png differ diff --git a/src/main/webapp/assets/img/investissement_avenir.png b/src/main/webapp/assets/img/investissement_avenir.png new file mode 100644 index 0000000..35a4c6e Binary files /dev/null and b/src/main/webapp/assets/img/investissement_avenir.png differ diff --git a/src/main/webapp/assets/img/logo-cartodebat.png b/src/main/webapp/assets/img/logo-cartodebat.png new file mode 100644 index 0000000..f28aa68 Binary files /dev/null and b/src/main/webapp/assets/img/logo-cartodebat.png differ diff --git a/src/main/webapp/assets/img/logo-cartodebat.svg b/src/main/webapp/assets/img/logo-cartodebat.svg new file mode 100644 index 0000000..f28aa68 Binary files /dev/null and b/src/main/webapp/assets/img/logo-cartodebat.svg differ diff --git a/src/main/webapp/assets/img/logo-cdc.jpg b/src/main/webapp/assets/img/logo-cdc.jpg new file mode 100644 index 0000000..d5a1ce6 Binary files /dev/null and b/src/main/webapp/assets/img/logo-cdc.jpg differ diff --git a/src/main/webapp/assets/img/logo-controversciences.png b/src/main/webapp/assets/img/logo-controversciences.png new file mode 100644 index 0000000..b31a42b Binary files /dev/null and b/src/main/webapp/assets/img/logo-controversciences.png differ diff --git a/src/main/webapp/assets/img/logo-forum-debate.png b/src/main/webapp/assets/img/logo-forum-debate.png new file mode 100644 index 0000000..7dc3f52 Binary files /dev/null and b/src/main/webapp/assets/img/logo-forum-debate.png differ diff --git a/src/main/webapp/assets/img/logo-intactile.svg b/src/main/webapp/assets/img/logo-intactile.svg new file mode 100644 index 0000000..adb1243 --- /dev/null +++ b/src/main/webapp/assets/img/logo-intactile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/img/logo-lirdef.png b/src/main/webapp/assets/img/logo-lirdef.png new file mode 100644 index 0000000..8c36a46 Binary files /dev/null and b/src/main/webapp/assets/img/logo-lirdef.png differ diff --git a/src/main/webapp/assets/img/logo-lirmm.png b/src/main/webapp/assets/img/logo-lirmm.png new file mode 100644 index 0000000..82c8408 Binary files /dev/null and b/src/main/webapp/assets/img/logo-lirmm.png differ diff --git a/src/main/webapp/assets/img/logo-mezoa.png b/src/main/webapp/assets/img/logo-mezoa.png new file mode 100644 index 0000000..ad3b8dc Binary files /dev/null and b/src/main/webapp/assets/img/logo-mezoa.png differ diff --git a/src/main/webapp/assets/img/logo_acad_montpellier.png b/src/main/webapp/assets/img/logo_acad_montpellier.png new file mode 100644 index 0000000..c59761b Binary files /dev/null and b/src/main/webapp/assets/img/logo_acad_montpellier.png differ diff --git a/src/main/webapp/assets/img/neutral.png b/src/main/webapp/assets/img/neutral.png new file mode 100644 index 0000000..6608a22 Binary files /dev/null and b/src/main/webapp/assets/img/neutral.png differ diff --git a/src/main/webapp/assets/js/components/grids/debatesGrid.vue b/src/main/webapp/assets/js/components/grids/debatesGrid.vue new file mode 100644 index 0000000..7cc27ac --- /dev/null +++ b/src/main/webapp/assets/js/components/grids/debatesGrid.vue @@ -0,0 +1,78 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/grids/documentsGrid.vue b/src/main/webapp/assets/js/components/grids/documentsGrid.vue new file mode 100644 index 0000000..6e4d89c --- /dev/null +++ b/src/main/webapp/assets/js/components/grids/documentsGrid.vue @@ -0,0 +1,51 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/grids/teamsGrid.vue b/src/main/webapp/assets/js/components/grids/teamsGrid.vue new file mode 100644 index 0000000..976b1f8 --- /dev/null +++ b/src/main/webapp/assets/js/components/grids/teamsGrid.vue @@ -0,0 +1,43 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/grids/usersGrid.vue b/src/main/webapp/assets/js/components/grids/usersGrid.vue new file mode 100644 index 0000000..9f45ee9 --- /dev/null +++ b/src/main/webapp/assets/js/components/grids/usersGrid.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/main/webapp/assets/js/components/modals/categoryModal.vue b/src/main/webapp/assets/js/components/modals/categoryModal.vue new file mode 100644 index 0000000..32c17d7 --- /dev/null +++ b/src/main/webapp/assets/js/components/modals/categoryModal.vue @@ -0,0 +1,39 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/modals/commentModal.vue b/src/main/webapp/assets/js/components/modals/commentModal.vue new file mode 100644 index 0000000..cee0516 --- /dev/null +++ b/src/main/webapp/assets/js/components/modals/commentModal.vue @@ -0,0 +1,184 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/modals/contributorModal.vue b/src/main/webapp/assets/js/components/modals/contributorModal.vue new file mode 100644 index 0000000..57c0ab2 --- /dev/null +++ b/src/main/webapp/assets/js/components/modals/contributorModal.vue @@ -0,0 +1,73 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/modals/createUserModal.vue b/src/main/webapp/assets/js/components/modals/createUserModal.vue new file mode 100644 index 0000000..4e9f3f8 --- /dev/null +++ b/src/main/webapp/assets/js/components/modals/createUserModal.vue @@ -0,0 +1,123 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/modals/loginModal.vue b/src/main/webapp/assets/js/components/modals/loginModal.vue new file mode 100644 index 0000000..5f3b4d3 --- /dev/null +++ b/src/main/webapp/assets/js/components/modals/loginModal.vue @@ -0,0 +1,58 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/modals/passwordModal.vue b/src/main/webapp/assets/js/components/modals/passwordModal.vue new file mode 100644 index 0000000..ba0871c --- /dev/null +++ b/src/main/webapp/assets/js/components/modals/passwordModal.vue @@ -0,0 +1,96 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/modals/resetPasswordModal.vue b/src/main/webapp/assets/js/components/modals/resetPasswordModal.vue new file mode 100644 index 0000000..3ffb1cd --- /dev/null +++ b/src/main/webapp/assets/js/components/modals/resetPasswordModal.vue @@ -0,0 +1,43 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/modals/tagsModal.vue b/src/main/webapp/assets/js/components/modals/tagsModal.vue new file mode 100644 index 0000000..ab098fb --- /dev/null +++ b/src/main/webapp/assets/js/components/modals/tagsModal.vue @@ -0,0 +1,110 @@ + + + diff --git a/src/main/webapp/assets/js/components/modals/teamModal.vue b/src/main/webapp/assets/js/components/modals/teamModal.vue new file mode 100644 index 0000000..857fc12 --- /dev/null +++ b/src/main/webapp/assets/js/components/modals/teamModal.vue @@ -0,0 +1,31 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/modals/userInTeamModal.vue b/src/main/webapp/assets/js/components/modals/userInTeamModal.vue new file mode 100644 index 0000000..d7f7c60 --- /dev/null +++ b/src/main/webapp/assets/js/components/modals/userInTeamModal.vue @@ -0,0 +1,57 @@ + + + diff --git a/src/main/webapp/assets/js/components/singletons/confirm.vue b/src/main/webapp/assets/js/components/singletons/confirm.vue new file mode 100644 index 0000000..64e38c6 --- /dev/null +++ b/src/main/webapp/assets/js/components/singletons/confirm.vue @@ -0,0 +1,57 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/singletons/documentation.vue b/src/main/webapp/assets/js/components/singletons/documentation.vue new file mode 100644 index 0000000..dd537d8 --- /dev/null +++ b/src/main/webapp/assets/js/components/singletons/documentation.vue @@ -0,0 +1,154 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/singletons/toaster.vue b/src/main/webapp/assets/js/components/singletons/toaster.vue new file mode 100644 index 0000000..dd6b03d --- /dev/null +++ b/src/main/webapp/assets/js/components/singletons/toaster.vue @@ -0,0 +1,43 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/singletons/tooltip.vue b/src/main/webapp/assets/js/components/singletons/tooltip.vue new file mode 100644 index 0000000..cc9b7f3 --- /dev/null +++ b/src/main/webapp/assets/js/components/singletons/tooltip.vue @@ -0,0 +1,40 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/D3Pie.vue b/src/main/webapp/assets/js/components/widgets/D3Pie.vue new file mode 100644 index 0000000..46aa9a7 --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/D3Pie.vue @@ -0,0 +1,194 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/D3Sunburst.vue b/src/main/webapp/assets/js/components/widgets/D3Sunburst.vue new file mode 100644 index 0000000..c2418fc --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/D3Sunburst.vue @@ -0,0 +1,240 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/D3Tree.vue b/src/main/webapp/assets/js/components/widgets/D3Tree.vue new file mode 100644 index 0000000..a988229 --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/D3Tree.vue @@ -0,0 +1,166 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/actionButton.vue b/src/main/webapp/assets/js/components/widgets/actionButton.vue new file mode 100644 index 0000000..c1bb18e --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/actionButton.vue @@ -0,0 +1,22 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/bulletsContainer.vue b/src/main/webapp/assets/js/components/widgets/bulletsContainer.vue new file mode 100644 index 0000000..e85ddf8 --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/bulletsContainer.vue @@ -0,0 +1,108 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/comment.vue b/src/main/webapp/assets/js/components/widgets/comment.vue new file mode 100644 index 0000000..6fc25ea --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/comment.vue @@ -0,0 +1,264 @@ + + + diff --git a/src/main/webapp/assets/js/components/widgets/contributors.vue b/src/main/webapp/assets/js/components/widgets/contributors.vue new file mode 100644 index 0000000..a63ea68 --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/contributors.vue @@ -0,0 +1,65 @@ + + + diff --git a/src/main/webapp/assets/js/components/widgets/debatePrint.vue b/src/main/webapp/assets/js/components/widgets/debatePrint.vue new file mode 100644 index 0000000..fe75eec --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/debatePrint.vue @@ -0,0 +1,97 @@ + + + diff --git a/src/main/webapp/assets/js/components/widgets/documented.vue b/src/main/webapp/assets/js/components/widgets/documented.vue new file mode 100644 index 0000000..af5bdba --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/documented.vue @@ -0,0 +1,25 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/institutionSelect.vue b/src/main/webapp/assets/js/components/widgets/institutionSelect.vue new file mode 100644 index 0000000..90c8e32 --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/institutionSelect.vue @@ -0,0 +1,44 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/notificationsPanel.vue b/src/main/webapp/assets/js/components/widgets/notificationsPanel.vue new file mode 100644 index 0000000..15d80fb --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/notificationsPanel.vue @@ -0,0 +1,74 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/searchBox.vue b/src/main/webapp/assets/js/components/widgets/searchBox.vue new file mode 100644 index 0000000..3d9b15b --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/searchBox.vue @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/tagsRestitution.vue b/src/main/webapp/assets/js/components/widgets/tagsRestitution.vue new file mode 100644 index 0000000..3e17995 --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/tagsRestitution.vue @@ -0,0 +1,120 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/textInput.vue b/src/main/webapp/assets/js/components/widgets/textInput.vue new file mode 100644 index 0000000..c84ea2c --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/textInput.vue @@ -0,0 +1,78 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/toggleActionButton.vue b/src/main/webapp/assets/js/components/widgets/toggleActionButton.vue new file mode 100644 index 0000000..76068a9 --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/toggleActionButton.vue @@ -0,0 +1,24 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/tooltiped.vue b/src/main/webapp/assets/js/components/widgets/tooltiped.vue new file mode 100644 index 0000000..dd9a05a --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/tooltiped.vue @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/js/components/widgets/wysiwygEditor.vue b/src/main/webapp/assets/js/components/widgets/wysiwygEditor.vue new file mode 100644 index 0000000..f2cacb0 --- /dev/null +++ b/src/main/webapp/assets/js/components/widgets/wysiwygEditor.vue @@ -0,0 +1,48 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/layouts/baseLayout.vue b/src/main/webapp/assets/js/layouts/baseLayout.vue new file mode 100644 index 0000000..5457d3c --- /dev/null +++ b/src/main/webapp/assets/js/layouts/baseLayout.vue @@ -0,0 +1,28 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/layouts/gridLayout.vue b/src/main/webapp/assets/js/layouts/gridLayout.vue new file mode 100644 index 0000000..2b77d2b --- /dev/null +++ b/src/main/webapp/assets/js/layouts/gridLayout.vue @@ -0,0 +1,152 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/layouts/modalLayout.vue b/src/main/webapp/assets/js/layouts/modalLayout.vue new file mode 100644 index 0000000..c1a3f03 --- /dev/null +++ b/src/main/webapp/assets/js/layouts/modalLayout.vue @@ -0,0 +1,67 @@ + + + diff --git a/src/main/webapp/assets/js/layouts/tabsLayout.vue b/src/main/webapp/assets/js/layouts/tabsLayout.vue new file mode 100644 index 0000000..0c46e4a --- /dev/null +++ b/src/main/webapp/assets/js/layouts/tabsLayout.vue @@ -0,0 +1,58 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/router.js b/src/main/webapp/assets/js/router.js new file mode 100644 index 0000000..0419957 --- /dev/null +++ b/src/main/webapp/assets/js/router.js @@ -0,0 +1,24 @@ +const router = new VueRouter({ + base: "", + mode: "history", + routes: [ + {path: '/', component: vueLoader('views/home')}, + {path: '/createDebate', component: vueLoader('views/createDebate')}, + {path: '/teams', component: vueLoader('views/teams')}, + {path: '/teams/:id', component: vueLoader('views/team')}, + {path: '/documents', component: vueLoader('views/documents')}, + {path: '/documents/:id', component: vueLoader('views/document')}, + {path: '/debates', component: vueLoader('views/debates')}, + {path: '/debates/:id', component: vueLoader('views/debate')}, + {path: '/debates/:id/restitution', component: vueLoader('views/restitution')}, + {path: '/debates/:id/print', component: vueLoader('views/debatePrint')}, + {path: '/aaf', component: vueLoader('views/aaf')}, + {path: '/tags', component: vueLoader('views/updateTags')}, + {path: '/agendas', component: vueLoader('views/agendas')}, + {path: '/agenda', component: vueLoader('views/agenda')}, + {path: '/sondages', component: vueLoader('views/sondages')}, + {path: '/sondage', component: vueLoader('views/sondage')}, + {path: '/test', component: vueLoader('views/test')}, + {path: '*', component: vueLoader('views/404')}, + ] +}); \ No newline at end of file diff --git a/src/main/webapp/assets/js/router.min.js b/src/main/webapp/assets/js/router.min.js new file mode 100644 index 0000000..fe8fe4f --- /dev/null +++ b/src/main/webapp/assets/js/router.min.js @@ -0,0 +1,2 @@ +const router=new VueRouter({base:"",mode:"history",routes:[{path:"/",component:vueLoader("views/home")},{path:"/createDebate",component:vueLoader("views/createDebate")},{path:"/teams",component:vueLoader("views/teams")},{path:"/teams/:id",component:vueLoader("views/team")},{path:"/documents",component:vueLoader("views/documents")},{path:"/documents/:id",component:vueLoader("views/document")},{path:"/debates",component:vueLoader("views/debates")},{path:"/debates/:id",component:vueLoader("views/debate")}, +{path:"/debates/:id/restitution",component:vueLoader("views/restitution")},{path:"/debates/:id/print",component:vueLoader("views/debatePrint")},{path:"/aaf",component:vueLoader("views/aaf")},{path:"/tags",component:vueLoader("views/updateTags")},{path:"*",component:vueLoader("views/404")}]}); \ No newline at end of file diff --git a/src/main/webapp/assets/js/service/aren.js b/src/main/webapp/assets/js/service/aren.js new file mode 100644 index 0000000..8d464ad --- /dev/null +++ b/src/main/webapp/assets/js/service/aren.js @@ -0,0 +1,937 @@ +const Authority = { + DELETED: "DELETED", + GUEST: "GUEST", + USER: "USER", + MODO: "MODO", + ADMIN: "ADMIN", + SUPERADMIN: "SUPERADMIN", + _value: { + DELETED: -1, + GUEST: 0, + USER: 1, + MODO: 2, + ADMIN: 3, + SUPERADMIN: 4, + }, +}; + +const Opinion = { + FOR: "FOR", + NEUTRAL: "NEUTRAL", + AGAINST: "AGAINST", +}; + +const Hypostase = [ + [ + "EXPLANATION", + "LAW", + "PRINCIPLE", + "THEORY", + "BELIEF", + "CONJECTURE", + "HYPOTHESIS", + "AXIOM", + "DEFINITION", + ], + [ + "QUALITATIVE", + "VARIABLE", + "OBJECT", + "EVENT", + "PHENOMENON", + "DATA", + "MODE", + "DOMAIN", + ], + [ + "QUANTITATIVE", + "VARIATION", + "VARIANCE", + "APPROXIMATION", + "VALUE", + "CLUE", + "INVARIANT", + "DIMENSION", + ], + [ + "STRUCTURAL", + "STRUCTURE", + "METHOD", + "FORMALISM", + "CLASSIFICATION", + "PARADIGME", + ], + ["DIFFICULTY", "APORIA", "PARADOXE", "PROBLEM"], +]; + +function Tag(obj = {}) { + if (obj.constructor === String) { + obj = obj.replace(/[^A-Za-zÀ-ÖØ-öø-ÿ0-9 \-\']/g, "").trim(); + let split = obj.split("|"); + if (split[1]) { + this.power = split[1] * 1; + } else { + this.power = 0; + } + split[0] = split[0].trim(); + if (split[0][0] === "-") { + this.negative = true; + this.value = split[0].substring(1).trim(); + } else { + this.negative = false; + this.value = split[0]; + } + } else { + this.value = obj.value; + this.negative = obj.negative; + this.power = obj.power; + } +} + +function Message(obj = {}) { + this.title = obj.title; + this.message = obj.message; + this.details = obj.details; +} + +function Entity(obj = {}) { + for (let attr in this.attrs) { + this[attr] = obj[attr] ? obj[attr] : undefined; + } + for (let attr in this.manyToOne) { + this[attr] = undefined; + } + for (let attr in this.oneToMany) { + this[attr] = []; + } + for (let attr in this.manyToMany) { + this[attr] = []; + } +} + +function Category(obj = {}) { + Entity.call(this, obj); +} +Category.prototype.attrs = { + id: Number, + name: String, + picture: String, + debatesCount: Number, + lastCommentDate: Date, +}; +Category.prototype.oneToMany = { + documents: [Document, "category"], +}; +Category.prototype.debates = function () { + return this.documents.map((document) => document.debates).flat(); +}; + +function Document(obj = {}) { + Entity.call(this, obj); +} +Document.prototype.attrs = { + id: Number, + created: Date, + name: String, + author: String, + content: String, + debatesCount: Number, + lastCommentDate: Date, +}; +Document.prototype.oneToMany = { + debates: [Debate, "document"], +}; +Document.prototype.manyToOne = { + category: [Category, "documents"], +}; + +function Debate(obj = {}) { + Entity.call(this, obj); +} +Debate.prototype.attrs = { + id: Number, + created: Date, + name: String, + closed: Date, + active: Boolean, + commentsCount: Number, + commentsCountFor: Number, + commentsCountAgainst: Number, + lastCommentDate: Date, + withHypostases: Boolean, + reformulationCheck: Boolean, + idfixLink: Boolean, + openPublic: Boolean, +}; +Debate.prototype.oneToMany = { + comments: [Comment, "debate"], +}; +Debate.prototype.manyToOne = { + owner: [User, "createdDebates"], + document: [Document, "debates"], +}; +Debate.prototype.manyToMany = { + teams: [Team, "debates"], + guests: [User, "invitedDebates"], +}; +Debate.prototype.deepSortComments = function (sortFunction) { + this.comments.sort(sortFunction); + let len = this.comments.length; + for (let i = 0; i < len; i++) { + this.comments[i].deepSortComments(sortFunction); + } +}; + +function Comment(obj = {}) { + Entity.call(this, obj); +} +Comment.prototype.attrs = { + id: Number, + created: Date, + reformulation: String, + argumentation: String, + selection: String, + startContainer: String, + startOffset: Number, + endContainer: String, + endOffset: Number, + opinion: String, + signaled: Boolean, + moderated: Boolean, + hypostases: Array, + proposedTags: Array, + tags: Array, +}; +Comment.prototype.oneToMany = { + comments: [Comment, "parent"], +}; +Comment.prototype.manyToOne = { + owner: [User, "comments"], + debate: [Debate, "comments"], + parent: [Comment, "comments"], +}; +Comment.prototype.deepSortComments = function (sortFunction) { + this.comments.sort(sortFunction); + let len = this.comments.length; + for (let i = 0; i < len; i++) { + this.comments[i].deepSortComments(sortFunction); + } +}; +Comment.prototype.compareBoundaryPoints = function (type, comment) { + return compareRange(type, this, comment); +}; + +function Institution(obj = {}) { + Entity.call(this, obj); +} +Institution.prototype.attrs = { + id: Number, + type: String, + name: String, + academy: String, +}; +Institution.prototype.oneToMany = { + users: [User, "institution"], + teams: [Team, "institution"], +}; + +function Notification(obj = {}) { + Entity.call(this, obj); +} +Notification.prototype.attrs = { + id: Number, + owner: Number, + created: Date, + content: Message, + unread: Boolean, + comment: Number, + debate: Number, +}; + +function Team(obj = {}) { + Entity.call(this, obj); +} +Team.prototype.attrs = { + id: Number, + entId: String, + name: String, + community: Boolean, + debatesCount: Number, + usersCount: Number, +}; +Team.prototype.manyToOne = { + institution: [Institution, "teams"], +}; +Team.prototype.manyToMany = { + debates: [Debate, "teams"], + users: [User, "teams"], +}; + +function User(obj = {}) { + Entity.call(this, obj); + this.authority = Authority.GUEST; +} +User.prototype.attrs = { + id: Number, + entId: String, + username: String, + password: String, + firstName: String, + lastName: String, + email: String, + lastLogin: Date, + active: Boolean, + authority: String, +}; +User.prototype.oneToMany = { + comments: [Comment, "owner"], + createdDebates: [Debate, "owner"], + notifications: [Notification, "owner"], +}; +User.prototype.manyToOne = { + institution: [Institution, "users"], +}; +User.prototype.manyToMany = { + invitedDebates: [Debate, "guests"], + teams: [Team, "users"], +}; +User.prototype.fullName = function () { + if (this.firstName && this.lastName) { + return this.firstName + " " + this.lastName; + } else { + return this.username; + } +}; +User.prototype.is = function (authority) { + return Authority._value[this.authority] >= Authority._value[authority]; +}; + +const ApiService = function (anUrl, locale) { + let self = this; + + this.Store = { + clear() { + this.Category = []; + this.Document = []; + this.Debate = []; + this.Comment = []; + this.Institution = []; + this.Notification = []; + this.Team = []; + this.User = []; + }, + detach(obj) { + this[obj.constructor.name].remove(obj); + }, + remove(obj) { + let manyToOne = obj.manyToOne; + let oneToMany = obj.oneToMany; + let manyToMany = obj.manyToMany; + + for (let foreignKey in manyToOne) { + if (obj[foreignKey]) { + obj[foreignKey][manyToOne[foreignKey][1]].remove(obj); + } + } + for (let collection in oneToMany) { + if (obj[collection]) { + let len = obj[collection].length; + for (let i = 0; i < len; i++) { + delete obj[collection][i][oneToMany[collection][1]]; + } + } + } + for (let collection in manyToMany) { + if (obj[collection]) { + let len = obj[collection].length; + for (let i = 0; i < len; i++) { + obj[collection][i][manyToMany[collection][1]].remove(obj); + } + } + } + this.detach(obj); + }, + createOrUpdate(obj, constructor) { + if (!isNaN(obj)) { + return this.get(obj * 1, constructor); + } + let that = this.get(obj.id, constructor); + if (that === -1) { + that = new constructor(); + if (this.hasOwnProperty(constructor.name)) { + this[constructor.name].push(that); + } + } + + let attrs = that.attrs; + let manyToOne = that.manyToOne; + let oneToMany = that.oneToMany; + let manyToMany = that.manyToMany; + + for (let attr in attrs) { + if (obj[attr] !== undefined) { + switch (attrs[attr]) { + case Boolean: + that[attr] = !!obj[attr]; + break; + case Number: + that[attr] = obj[attr] * 1; + break; + case String: + that[attr] = "" + obj[attr]; + break; + case Date: + that[attr] = new Date(obj[attr]); + break; + case Array: + that[attr] = obj[attr]; + break; + default: + that[attr] = new attrs[attr](obj[attr]); + } + } + } + if (constructor === Comment && that.tags !== undefined) { + // If same same value in Tags and ProposedTags array + // Then point to the same object + let len = that.tags.length; + for (let i = 0; i < len; i++) { + let pTag = that.proposedTags.find( + (t) => t.value === that.tags[i].value + ); + if (pTag !== undefined) { + that.tags[i] = pTag; + } + } + } + + for (let foreignKey in manyToOne) { + if (obj[foreignKey] !== undefined) { + that[foreignKey] = this.createOrUpdate( + obj[foreignKey], + manyToOne[foreignKey][0] + ); + if (manyToOne[foreignKey][1]) { + let foreignCollection = that[foreignKey][manyToOne[foreignKey][1]]; + if (!foreignCollection.includes(that)) { + foreignCollection.push(that); + } + } + } + } + for (let collection in oneToMany) { + if (obj[collection] !== undefined) { + if (obj[collection] && obj[collection].length > 0) { + that[collection].splice(0, that[collection].length); + let len = obj[collection].length; + for (let i = 0; i < len; i++) { + let foreignObj = this.createOrUpdate( + obj[collection][i], + oneToMany[collection][0] + ); + if (!that[collection].includes(foreignObj)) { + that[collection].push(foreignObj); + } + if (oneToMany[collection][1]) { + foreignObj[oneToMany[collection][1]] = that; + } + } + } + } + } + for (let collection in manyToMany) { + if (obj[collection] !== undefined) { + if (obj[collection] && obj[collection].length > 0) { + that[collection].splice(0, that[collection].length); + let len = obj[collection].length; + for (let i = 0; i < len; i++) { + let foreignObj = this.createOrUpdate( + obj[collection][i], + manyToMany[collection][0] + ); + if (!that[collection].includes(foreignObj)) { + that[collection].push(foreignObj); + } + if (manyToMany[collection][1]) { + let foreignCollection = foreignObj[manyToMany[collection][1]]; + if (!foreignCollection.includes(that)) { + foreignCollection.push(that); + } + } + } + } + } + } + return that; + }, + get(id, constructor) { + if (this.hasOwnProperty(constructor.name)) { + let index = this[constructor.name].findIndex((o) => o.id === id); + if (index !== -1) { + return this[constructor.name][index]; + } + } + return -1; + }, + }; + this.Store.clear(); + + this.onLoad = (loading) => {}; + + this.onError = (json, xhttp) => { + if (typeof json === "string") { + console.log(xhttp); + alert( + "ERREUR INTERNE\n\nToutes nos excuses, une erreur s'est produite sur nos serveurs.\nVeuillez réessayer ou contacter un administrateur si l'erreur persiste." + ); + } else { + console.log(xhttp); + alert("ERREUR : " + json.title + "\n\n" + Message.parse(json)); + } + }; + let url = anUrl; + + let xhttp; + + this.abort = () => { + xhttp.abort(); + }; + let ajaxCall = ({ + method, + path, + headers, + onSuccess, + onError, + onProgress, + data, + json = true, + async = true, + loading = true, + } = {}) => { + let xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = () => { + if ( + xhttp.readyState === 4 && + (xhttp.status === 200 || xhttp.status === 204) + ) { + let arr = xhttp + .getAllResponseHeaders() + .trim() + .split(/[\r\n]+/); + let headersMap = {}; + arr.forEach(function (line) { + let parts = line.split(": "); + let header = parts.shift(); + let value = parts.join(": "); + headersMap[header] = value; + }); + if (onSuccess) { + let returnValue; + try { + returnValue = JSON.parse(xhttp.responseText); + } catch (e) { + returnValue = xhttp.responseText; + } + onSuccess(returnValue, headersMap); + } + if (loading) { + this.onLoad(false); + } + } else if (xhttp.readyState === 3) { + if (onProgress) { + let newResponses = xhttp.responseText.split("\ndata: "); + let response = newResponses[newResponses.length - 1]; + try { + onProgress(JSON.parse(response)); + } catch (ex) { + onProgress(response); + } + } + } else if (xhttp.readyState === 4) { + let response = xhttp.responseText; + let jsonResponse = {}; + if (onProgress) { + let newResponses = response.split("\ndata: "); + response = newResponses[newResponses.length - 1]; + } + try { + jsonResponse = JSON.parse(response); + } catch (e) { + jsonResponse = response; + } + if (onError) { + onError(jsonResponse, xhttp); + } else { + this.onError(jsonResponse, xhttp); + } + if (loading) { + this.onLoad(false); + } + } + }; + + xhttp.open(method, url + "/" + path, async); + for (let header in headers) { + xhttp.setRequestHeader(header.name, header.value); + } + xhttp.setRequestHeader("Accept-Language", locale); + if (json) { + xhttp.setRequestHeader("Content-type", "application/json"); + if (typeof data === "string") { + xhttp.send(data); + } else { + xhttp.send(JSON.stringify(decycle(data))); + } + } else { + xhttp.send(data); + } + if (loading) { + this.onLoad(true); + } + }; + + this.import = ({ data, onSuccess, onError, onProgress, loading } = {}) => { + ajaxCall({ + method: "POST", + path: "aaf/import", + data: data, + onProgress, + onSuccess, + onError: onError, + json: false, + loading: loading, + }); + }; + let parse = function (obj, className) { + if (Array.isArray(obj)) { + return obj.map((obj) => self.Store.createOrUpdate(obj, className)); + } else { + return self.Store.createOrUpdate(obj, className); + } + }; + let decycle = function (obj, root = true) { + if (!obj || typeof obj !== "object") return obj; + + if (!root && typeof obj.id !== "undefined") return { id: obj.id }; + + if (obj.constructor === Date) return obj; + + if (Array.isArray(obj)) return obj.map((el) => decycle(el, false)); + + let replica = {}; + Object.keys(obj).forEach( + (key) => (replica[key] = decycle(obj[key], false)) + ); + return replica; + }; + let EntityProcessor = function (resourcePath, className) { + this.call = ({ + method, + data = null, + path = "", + onSuccess, + onError, + onProgress, + query = {}, + parsingClassName = className, + async = true, + loading = true, + } = {}) => { + let urlParameters = Object.keys(query) + .map((key) => key + "=" + encodeURIComponent(query[key])) + .join("&"); + ajaxCall({ + method, + data, + path: + resourcePath + + path + + (urlParameters.length > 0 ? "?" + urlParameters : ""), + onSuccess: function (response) { + let result = response; + if (response && parsingClassName) { + result = parse(response, parsingClassName); + } + onSuccess ? onSuccess(result) : null; + }, + onError, + onProgress, + async, + loading, + }); + }; + + this.getAll = (params = {}) => { + params.method = "GET"; + this.call(params); + }; + this.get = (params = {}) => { + params.method = "GET"; + params.path = "/" + params.id; + this.call(params); + }; + this.remove = (params = {}) => { + params.method = "DELETE"; + params.path = "/" + params.data.id; + let onSuccess = params.onSuccess; + params.onSuccess = function () { + self.Store.remove(params.data); + onSuccess ? onSuccess() : null; + }; + this.call(params); + }; + this.create = (params = {}) => { + params.method = "POST"; + this.call(params); + }; + this.edit = (params = {}) => { + params.method = "PUT"; + params.path = "/" + params.data.id; + this.call(params); + }; + this.createOrUpdate = (params = {}) => { + if (params.data.id) { + this.edit(params); + } else { + this.create(params); + } + }; + }; + + this.Documentation = function ({ onSuccess, onError } = {}) { + ajaxCall({ + method: "GET", + path: "documentation", + onSuccess, + onError, + }); + }; + + let Listener; + if (!!window.SharedWorker) { + Listener = function (aPath, className) { + this.listen = ({ id, onMessage } = {}) => { + let sseWorker = new SharedWorker("assets/js/service/worker.js"); + let eventPath = url + "/events/" + aPath + (id ? "/" + id : ""); + sseWorker.port.postMessage(eventPath); + sseWorker.port.addEventListener( + "message", + (message) => { + let result = parse(JSON.parse(message.data.data), className); + if (onMessage) { + onMessage(result); + } + }, + false + ); + sseWorker.port.start(); + }; + }; + } else { + Listener = function (aPath, className) { + let eventPath = url + "/events/" + aPath; + let source = null; + this.listen = ({ id, onMessage } = {}) => { + source = new EventSource(eventPath + (id ? "/" + id : "")); + source.onmessage = (message) => { + let result = parse(JSON.parse(message.data), className); + if (onMessage) { + onMessage(result); + } + }; + source.onclose = () => {}; + }; + this.stop = () => { + if (source) { + source.close(); + } + }; + }; + } + + this.Categories = new EntityProcessor("categories", Category); + this.Documents = new EntityProcessor("documents", Document); + this.Debates = new EntityProcessor("debates", Debate); + this.Teams = new EntityProcessor("teams", Team); + this.Comments = new EntityProcessor("comments", Comment); + this.Institutions = new EntityProcessor("institutions", Institution); + this.Users = new EntityProcessor("users", User); + this.Notifications = new EntityProcessor("notifications", Notification); + this.CommentListener = new Listener("comments", Comment); + this.NotificationListener = new Listener("notifications", Notification); + + this.Users.getLoged = function (params = {}) { + params.method = "GET"; + params.path = "/me"; + this.call(params); + }; + this.Users.login = function (params = {}) { + params.method = "POST"; + params.path = "/login"; + params.parsingClassName = false; + let onSuccess = params.onSuccess; + params.onSuccess = (token) => { + document.cookie = + "Authorization=" + + token + + "; maxAge=" + + (params.data.rememberMe ? 360 * 24 * 60 * 60 : -1) + + "; path=/"; + document.location.reload(true); + onSuccess ? onSuccess() : null; + }; + this.call(params); + }; + this.Users.logout = function (params = {}) { + params.method = "POST"; + params.path = "/logout"; + params.parsingClassName = false; + let onSuccess = params.onSuccess; + params.onSuccess = () => { + document.cookie = + "Authorization=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; + document.location.replace(""); + onSuccess ? onSuccess() : null; + }; + this.call(params); + }; + this.Users.passwd = function (params = {}) { + params.method = "PUT"; + params.path = "/passwd"; + this.call(params); + }; + this.Users.activate = function (params = {}) { + params.method = "GET"; + params.path = "/activate"; + this.call(params); + }; + this.Users.resetPasswd = function (params = {}) { + params.method = "POST"; + params.path = "/resetPasswd"; + this.call(params); + }; + this.Users.permanentRemove = function (params = {}) { + params.method = "DELETE"; + params.path = "/" + params.data.id + "/permanent/"; + this.call(params); + }; + this.Users.exists = function (params = {}) { + params.method = "GET"; + params.path = "/test"; + params.query = { identifier: params.data }; + params.parsingClassName = false; + this.call(params); + }; + this.Documents.duplicate = function (params = {}) { + params.method = "POST"; + params.path = "/" + params.id + "/duplicate"; + this.call(params); + }; + this.Debates.addComment = function (params = {}) { + params.method = "POST"; + params.path = "/" + params.id + "/comments"; + params.parsingClassName = Comment; + this.call(params); + }; + this.Debates.addTeam = function (params = {}) { + params.method = "PUT"; + params.path = "/" + params.id + "/teams/" + params.data.id; + let onSuccess = params.onSuccess; + params.onSuccess = function () { + self.Store.get(params.id, Debate).teams.push(params.data); + params.data.debates.push(self.Store.get(params.id, Debate)); + onSuccess ? onSuccess() : null; + }; + params.parsingClassName = Team; + this.call(params); + }; + this.Debates.removeTeam = function (params = {}) { + params.method = "DELETE"; + params.path = "/" + params.id + "/teams/" + params.data.id; + let onSuccess = params.onSuccess; + params.onSuccess = function () { + self.Store.get(params.id, Debate).teams.remove(params.data); + onSuccess ? onSuccess() : null; + }; + this.call(params); + }; + this.Debates.addGuest = function (params = {}) { + params.method = "PUT"; + params.path = "/" + params.id + "/users/" + params.data.id; + let onSuccess = params.onSuccess; + params.onSuccess = function () { + self.Store.get(params.id, Debate).guests.push(params.data); + params.data.invitedDebates.push(self.Store.get(params.id, Debate)); + onSuccess ? onSuccess() : null; + }; + params.parsingClassName = User; + this.call(params); + }; + this.Debates.removeGuest = function (params = {}) { + params.method = "DELETE"; + params.path = "/" + params.id + "/users/" + params.data.id; + let onSuccess = params.onSuccess; + params.onSuccess = function () { + self.Store.get(params.id, Debate).guests.remove(params.data); + onSuccess ? onSuccess() : null; + }; + this.call(params); + }; + this.Debates.getScraps = function (params = {}) { + params.method = "GET"; + params.path = "/" + params.id + "/scraps"; + params.parsingClassName = false; + this.call(params); + }; + this.Debates.getTheme = function (params = {}) { + params.method = "GET"; + params.path = "/" + params.id + "/theme"; + params.parsingClassName = false; + this.call(params); + }; + this.Teams.addUser = function (params = {}) { + params.method = "PUT"; + params.path = "/" + params.id + "/users/" + params.data.id; + let onSuccess = params.onSuccess; + params.onSuccess = function () { + self.Store.get(params.id, Team).users.push(params.data); + params.data.teams.push(self.Store.get(params.id, Team)); + onSuccess ? onSuccess() : null; + }; + params.parsingClassName = User; + this.call(params); + }; + this.Teams.removeUser = function (params = {}) { + params.method = "DELETE"; + params.path = "/" + params.id + "/users/" + params.data.id; + let onSuccess = params.onSuccess; + params.onSuccess = function () { + self.Store.get(params.id, Team).users.remove(params.data); + onSuccess ? onSuccess() : null; + }; + this.call(params); + }; + this.Comments.getScalar = function (params = {}) { + params.method = "POST"; + params.path = "/scalar"; + params.parsingClassName = false; + this.call(params); + }; + this.Comments.updateTags = function (params = {}) { + params.method = "PUT"; + params.path = "/" + params.id + "/updateTags"; + params.parsingClassName = false; + this.call(params); + }; + this.Comments.updateAllTags = function (params = {}) { + params.method = "PUT"; + params.path = "/updateTags"; + params.parsingClassName = false; + this.call(params); + }; + + this.Notifications.readAll = function (params = {}) { + params.method = "PUT"; + this.call(params); + }; +}; diff --git a/src/main/webapp/assets/js/service/aren.min.js b/src/main/webapp/assets/js/service/aren.min.js new file mode 100644 index 0000000..f4eaf28 --- /dev/null +++ b/src/main/webapp/assets/js/service/aren.min.js @@ -0,0 +1,28 @@ +const Authority={DELETED:"DELETED",GUEST:"GUEST",USER:"USER",MODO:"MODO",ADMIN:"ADMIN",SUPERADMIN:"SUPERADMIN",_value:{DELETED:-1,GUEST:0,USER:1,MODO:2,ADMIN:3,SUPERADMIN:4}},Opinion={FOR:"FOR",NEUTRAL:"NEUTRAL",AGAINST:"AGAINST"},Hypostase=["EXPLANATION LAW PRINCIPLE THEORY BELIEF CONJECTURE HYPOTHESIS AXIOM DEFINITION".split(" "),"QUALITATIVE VARIABLE OBJECT EVENT PHENOMENON DATA MODE DOMAIN".split(" "),"QUANTITATIVE VARIATION VARIANCE APPROXIMATION VALUE CLUE INVARIANT DIMENSION".split(" "),"STRUCTURAL STRUCTURE METHOD FORMALISM CLASSIFICATION PARADIGME".split(" "), +["DIFFICULTY","APORIA","PARADOXE","PROBLEM"]];function Tag(c={}){c.constructor===String?(c=c.replace(/[^A-Za-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u00ff0-9 \-']/g,"").trim(),c=c.split("|"),this.power=c[1]?1*c[1]:0,c[0]=c[0].trim(),"-"===c[0][0]?(this.negative=!0,this.value=c[0].substring(1).trim()):(this.negative=!1,this.value=c[0])):(this.value=c.value,this.negative=c.negative,this.power=c.power)}function Message(c={}){this.title=c.title;this.message=c.message;this.details=c.details} +function Entity(c={}){for(let n in this.attrs)this[n]=c[n]?c[n]:void 0;for(let c in this.manyToOne)this[c]=void 0;for(let c in this.oneToMany)this[c]=[];for(let c in this.manyToMany)this[c]=[]}function Category(c={}){Entity.call(this,c)}Category.prototype.attrs={id:Number,name:String,picture:String,debatesCount:Number,lastCommentDate:Date};Category.prototype.oneToMany={documents:[Document,"category"]};Category.prototype.debates=function(){return this.documents.map(c=>c.debates).flat()}; +function Document(c={}){Entity.call(this,c)}Document.prototype.attrs={id:Number,created:Date,name:String,author:String,content:String,debatesCount:Number,lastCommentDate:Date};Document.prototype.oneToMany={debates:[Debate,"document"]};Document.prototype.manyToOne={category:[Category,"documents"]};function Debate(c={}){Entity.call(this,c)} +Debate.prototype.attrs={id:Number,created:Date,name:String,closed:Date,active:Boolean,commentsCount:Number,commentsCountFor:Number,commentsCountAgainst:Number,lastCommentDate:Date,withHypostases:Boolean,reformulationCheck:Boolean,idfixLink:Boolean,openPublic:Boolean};Debate.prototype.oneToMany={comments:[Comment,"debate"]};Debate.prototype.manyToOne={owner:[User,"createdDebates"],document:[Document,"debates"]};Debate.prototype.manyToMany={teams:[Team,"debates"],guests:[User,"invitedDebates"]}; +Debate.prototype.deepSortComments=function(c){this.comments.sort(c);let n=this.comments.length;for(let e=0;e=Authority._value[c]}; +ApiService=function(c,n){let e=this;this.Store={clear(){this.Category=[];this.Document=[];this.Debate=[];this.Comment=[];this.Institution=[];this.Notification=[];this.Team=[];this.User=[]},detach(a){this[a.constructor.name].remove(a)},remove(a){var b=a.manyToOne,d=a.oneToMany;let c=a.manyToMany;for(var f in b)a[f]&&a[f][b[f][1]].remove(a);for(var g in d)if(a[g])for(b=a[g].length,f=0;fb.value===d.tags[a].value),void 0!==c&&(d.tags[a]=c)}for(var l in f)void 0!==a[l]&&(d[l]=this.createOrUpdate(a[l],f[l][0]),f[l][1]&&(b=d[l][f[l][1]],b.includes(d)||b.push(d)));for(var k in g)if(void 0!==a[k]&&a[k]&&0b.id===a);if(-1!==d)return this[b.name][d]}return-1}};this.Store.clear();this.onLoad=a=>{};this.onError=(a,b)=>{"string"===typeof a?(console.log(b),alert("ERREUR INTERNE\n\nToutes nos excuses, une erreur s'est produite sur nos serveurs.\nVeuillez r\u00e9essayer ou contacter un administrateur si l'erreur persiste.")): +(console.log(b),alert("ERREUR : "+a.title+"\n\n"+Message.parse(a)))};this.abort=()=>{(void 0).abort()};let r=({method:a,path:b,headers:d,onSuccess:e,onError:f,onProgress:g,data:p,json:l=!0,async:k=!0,loading:m=!0}={})=>{let h=new XMLHttpRequest;h.onreadystatechange=()=>{if(4===h.readyState&&(200===h.status||204===h.status)){let b={};h.getAllResponseHeaders().trim().split(/[\r\n]+/).forEach(function(a){var d=a.split(": ");a=d.shift();d=d.join(": ");b[a]=d});if(e){try{var a=JSON.parse(h.responseText)}catch(w){a= +h.responseText}e(a,b)}if(m)this.onLoad(!1)}else if(3===h.readyState){if(g){a=h.responseText.split("\ndata: ");a=a[a.length-1];try{g(JSON.parse(a))}catch(v){g(a)}}}else if(4===h.readyState){var b=h.responseText;a={};g&&(b=b.split("\ndata: "),b=b[b.length-1]);try{a=JSON.parse(b)}catch(v){a=b}if(f)f(a,h);else this.onError(a,h);if(m)this.onLoad(!1)}};h.open(a,c+"/"+b,k);for(let a in d)h.setRequestHeader(a.name,a.value);h.setRequestHeader("Accept-Language",n);l?(h.setRequestHeader("Content-type","application/json"), +"string"===typeof p?h.send(p):h.send(JSON.stringify(q(p)))):h.send(p);if(m)this.onLoad(!0)};this.import=({data:a,onSuccess:b,onError:d,onProgress:c,loading:f}={})=>{r({method:"POST",path:"aaf/import",data:a,onProgress:c,onSuccess:b,onError:d,json:!1,loading:f})};let t=function(a,b){return Array.isArray(a)?a.map(a=>e.Store.createOrUpdate(a,b)):e.Store.createOrUpdate(a,b)},q=function(a,b=!0){if(!a||"object"!==typeof a)return a;if(!b&&"undefined"!==typeof a.id)return{id:a.id};if(a.constructor===Date)return a; +if(Array.isArray(a))return a.map(a=>q(a,!1));let d={};Object.keys(a).forEach(b=>d[b]=q(a[b],!1));return d},m=function(a,b){this.call=({method:d,data:c=null,path:f="",onSuccess:g,onError:e,onProgress:l,query:k={},parsingClassName:m=b,async:h=!0,loading:n=!0}={})=>{let b=Object.keys(k).map(a=>a+"="+encodeURIComponent(k[a])).join("&");r({method:d,data:c,path:a+f+(0{a.method="GET";this.call(a)};this.get=(a={})=>{a.method="GET";a.path="/"+a.id;this.call(a)};this.remove=(a={})=>{a.method="DELETE";a.path="/"+a.data.id;let b=a.onSuccess;a.onSuccess=function(){e.Store.remove(a.data);b?b():null};this.call(a)};this.create=(a={})=>{a.method="POST";this.call(a)};this.edit=(a={})=>{a.method="PUT";a.path="/"+a.data.id;this.call(a)};this.createOrUpdate=(a={})=>{a.data.id?this.edit(a):this.create(a)}};this.Documentation=function({onSuccess:a,onError:b}={}){r({method:"GET", +path:"documentation",onSuccess:a,onError:b})};let u;u=window.SharedWorker?function(a,b){this.listen=({id:d,onMessage:e}={})=>{let f=new SharedWorker("assets/js/service/worker.js");f.port.postMessage(c+"/events/"+a+(d?"/"+d:""));f.port.addEventListener("message",a=>{a=t(JSON.parse(a.data.data),b);e&&e(a)},!1);f.port.start()}}:function(a,b){let d=c+"/events/"+a,e=null;this.listen=({id:a,onMessage:c}={})=>{e=new EventSource(d+(a?"/"+a:""));e.onmessage=a=>{a=t(JSON.parse(a.data),b);c&&c(a)};e.onclose= +()=>{}};this.stop=()=>{e&&e.close()}};this.Categories=new m("categories",Category);this.Documents=new m("documents",Document);this.Debates=new m("debates",Debate);this.Teams=new m("teams",Team);this.Comments=new m("comments",Comment);this.Institutions=new m("institutions",Institution);this.Users=new m("users",User);this.Notifications=new m("notifications",Notification);this.CommentListener=new u("comments",Comment);this.NotificationListener=new u("notifications",Notification);this.Users.getLoged= +function(a={}){a.method="GET";a.path="/me";this.call(a)};this.Users.login=function(a={}){a.method="POST";a.path="/login";a.parsingClassName=!1;let b=a.onSuccess;a.onSuccess=c=>{document.cookie="Authorization="+c+"; maxAge="+(a.data.rememberMe?31104E3:-1)+"; path=/";document.location.reload(!0);b?b():null};this.call(a)};this.Users.logout=function(a={}){a.method="POST";a.path="/logout";a.parsingClassName=!1;let b=a.onSuccess;a.onSuccess=()=>{document.cookie="Authorization=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; +document.location.replace("");b?b():null};this.call(a)};this.Users.passwd=function(a={}){a.method="PUT";a.path="/passwd";this.call(a)};this.Users.activate=function(a={}){a.method="GET";a.path="/activate";this.call(a)};this.Users.resetPasswd=function(a={}){a.method="POST";a.path="/resetPasswd";this.call(a)};this.Users.permanentRemove=function(a={}){a.method="DELETE";a.path="/"+a.data.id+"/permanent/";this.call(a)};this.Users.exists=function(a={}){a.method="GET";a.path="/test";a.query={identifier:a.data}; +a.parsingClassName=!1;this.call(a)};this.Documents.duplicate=function(a={}){a.method="POST";a.path="/"+a.id+"/duplicate";this.call(a)};this.Debates.addComment=function(a={}){a.method="POST";a.path="/"+a.id+"/comments";a.parsingClassName=Comment;this.call(a)};this.Debates.addTeam=function(a={}){a.method="PUT";a.path="/"+a.id+"/teams/"+a.data.id;let b=a.onSuccess;a.onSuccess=function(){e.Store.get(a.id,Debate).teams.push(a.data);a.data.debates.push(e.Store.get(a.id,Debate));b?b():null};a.parsingClassName= +Team;this.call(a)};this.Debates.removeTeam=function(a={}){a.method="DELETE";a.path="/"+a.id+"/teams/"+a.data.id;let b=a.onSuccess;a.onSuccess=function(){e.Store.get(a.id,Debate).teams.remove(a.data);b?b():null};this.call(a)};this.Debates.addGuest=function(a={}){a.method="PUT";a.path="/"+a.id+"/users/"+a.data.id;let b=a.onSuccess;a.onSuccess=function(){e.Store.get(a.id,Debate).guests.push(a.data);a.data.invitedDebates.push(e.Store.get(a.id,Debate));b?b():null};a.parsingClassName=User;this.call(a)}; +this.Debates.removeGuest=function(a={}){a.method="DELETE";a.path="/"+a.id+"/users/"+a.data.id;let b=a.onSuccess;a.onSuccess=function(){e.Store.get(a.id,Debate).guests.remove(a.data);b?b():null};this.call(a)};this.Debates.getScraps=function(a={}){a.method="GET";a.path="/"+a.id+"/scraps";a.parsingClassName=!1;this.call(a)};this.Debates.getTheme=function(a={}){a.method="GET";a.path="/"+a.id+"/theme";a.parsingClassName=!1;this.call(a)};this.Teams.addUser=function(a={}){a.method="PUT";a.path="/"+a.id+ +"/users/"+a.data.id;let b=a.onSuccess;a.onSuccess=function(){e.Store.get(a.id,Team).users.push(a.data);a.data.teams.push(e.Store.get(a.id,Team));b?b():null};a.parsingClassName=User;this.call(a)};this.Teams.removeUser=function(a={}){a.method="DELETE";a.path="/"+a.id+"/users/"+a.data.id;let b=a.onSuccess;a.onSuccess=function(){e.Store.get(a.id,Team).users.remove(a.data);b?b():null};this.call(a)};this.Comments.getScalar=function(a={}){a.method="POST";a.path="/scalar";a.parsingClassName=!1;this.call(a)}; +this.Comments.updateTags=function(a={}){a.method="PUT";a.path="/"+a.id+"/updateTags";a.parsingClassName=!1;this.call(a)};this.Comments.updateAllTags=function(a={}){a.method="PUT";a.path="/updateTags";a.parsingClassName=!1;this.call(a)};this.Notifications.readAll=function(a={}){a.method="PUT";this.call(a)}}; \ No newline at end of file diff --git a/src/main/webapp/assets/js/service/i18n.js b/src/main/webapp/assets/js/service/i18n.js new file mode 100644 index 0000000..21ac9de --- /dev/null +++ b/src/main/webapp/assets/js/service/i18n.js @@ -0,0 +1,330 @@ +const dateTimeFormats = { + 'fr-FR': { + short: { + year: 'numeric', month: 'short', day: 'numeric' + }, + long: { + year: 'numeric', month: 'short', day: 'numeric', + weekday: 'short', hour: 'numeric', minute: 'numeric' + } + }, +} + +const messages = { + 'fr-FR': { + password_forgotten: "Mot de passe oublié", + with_dots: "Avec...", + on_the_doc: "Sur le document...", + recapitulative: "Récapitulatif", + by: "Par", + proposed_by: "Proposé par", + 'with': "Avec", + print: "Imprimer", + connection: "Se connecter à AREN", + connect: "Se connecter", + cas_connection: "Connexion CAS", + cancel: "Annuler", + validate: "Valider", + close: "Fermer", + yes: "Oui", + no: "Non", + i_am: "Je suis", + debate: "Débat", + debate_tree: "Arbre du débat", + comment_repartition: "Répartition des arguments", + debate_sunburst: "Topologie", + odt_export: "Export du débat", + nb_comment: "{count} argument|{count} arguments", + nb_letter: "{count} lettre|{count} lettres", + by_comment_count: "Par nombre d'arguments", + by_letter_count: "Par nombre de lettres", + by_user: "Par utilisateur⋅rice", + by_opinion: "Par opinion", + display_labels: "Afficher les légendes", + display_arguments: "Afficher les arguments", + tags_edition: "Édition des mots-clefs", + tags: "Mots-clefs", + proposed_tags: "Mots-clefs proposés", + no_tags_yet: "En recherche de proposition", + category_edition: "Édition de catégorie", + category_creation: "Création de catégorie", + team_edition: "Édition de groupe", + team_creation: "Création de groupe", + image: "Image", + user_creation: "Création d'un⋅e untilisateur⋅rice", + username: "Pseudonyme", + email: "E-mail", + first_name: "Prénom", + last_name: "Nom de famille", + password: "Mot de passe", + remember_me: "Se souvenir de moi", + old_password: "Mot de passe actuel", + new_password: "Nouveau mot de passe", + password_check: "Vérification du mot de passe", + change_password: "Changer de mot de passe", + theme: "Thème", + scraps: "Selections", + display: "Afficher", + sort_by: "Trier par", + date: "Date", + position: "Position", + creation_success: "Création réussie", + import_success: "Importation réussie", + update_success: "Mise à jour réussie", + display_team: "Afficher le groupe", + new_team: "Nouveau groupe", + new_user: "Nouvel⋅le utilisateur⋅rice", + add_user: "Ajouter un⋅e utilisateur⋅rice", + team_managment: "Gestion des groupes", + user_managment: "Gestion des utilisateur⋅rices", + user_created: "Utilisateur⋅rice enregistré⋅e", + user_activated: "Utilisateur⋅rice activé⋅e", + anonymous_user: "Anonyme", + save: "Sauvegarder", + modify: "Modifier", + nb_users: "Aucun utilisateur⋅rice|{count} utilisateur⋅rice|{count} utilisateur⋅rice⋅s", + nb_teams: "Aucun groupe|{count} groupe|{count} groupes", + nb_debates: "Aucun débat|{count} débat|{count} débats", + nb_comments: "Aucun argument|{count} argument|{count} arguments", + last_post_the: "Dernier post le", + no_post: "Aucun post", + category: "Catégorie", + title: "Titre", + author: "Auteur⋅e", + restitution: "Restitution", + posts: "Posts", + last_post: "Dernier post", + document: "Document", + teams: "Groupes", + moderators: "Modérateur⋅rice.s", + authority: "Status", + users: "Utilisateur⋅rice⋅s", + guests: "Invité⋅e⋅s", + debates: "Débats", + new_debate: "Nouveau débat", + invite_in_debate: "Inviter au débat", + SUPERADMIN: "Super administrateur⋅rice", + SUPERADMIN: "Root", + ADMIN: "Administrateur⋅rice", + MODO: "Modérateur⋅rice", + USER: "Utilisateur⋅rice", + GUEST: "Invité⋅e", + DELETED: "Supprimé", + report: "Signalement", + select_all: "Selectionner tout", + unselect_all: "Déselectionner tout", + advanced_options: "Options avancées", + public_debate: "Débat public", + reformulation_assist: "Assistant de reformulation", + idefix_link: "Lien IDEFIX", + with_hypostases: "Avec hypostase", + without_institution: "Sans établissement", + running: "En cours...", + import: "Importer", + not_connected: "Vous n'êtes pas connecté⋅e", + tutorials: "Tutoriels", + argue: "Argumenter", + aaf_import: "Import AAF", + update_tags: "Mise à jour des tags", + start: "Lancer", + helper: { + welcome: "Bienvenue sur la plateforme AREN (Argumentation & Numérique)
Il s'agit d’un espace numérique de débat pour pratiquer l’argumentation.
Prendre en compte les arguments des autres et justifier son opinion pour mieux argumenter et exercer son esprit critique !", + creating_user: "Création en cour, veuillez patienter...", + not_connected: "Vous devez être inscrit⋅e et connecté⋅e pour réaliser cette action", + mark_as_read: "Marquer comme lue", + mark_as_unread: "Marquer comme non lue", + cas_login: "Connectez-vous via le system CAS de l'ENT", + add_document: "Ajouter un document", + edit_category: "Modifier la catégorie", + remove_category: "Supprimer la catégorie", + cannot_remove_category: "Vous ne pouvez pas supprimer une catégorie contenant un document", + copy_document: "Dupliquer le document", + remove_debate: "Supprimer le débat", + cannot_remove_debate: "Vous ne pouvez pas supprimer un débat contenant des arguments", + remove_document: "Supprimer le document", + cannot_edit_document: "Vous ne pouvez pas modifier un document contenant un débat", + cannot_remove_document: "Vous ne pouvez pas supprimer un document contenant un débat", + edit_team: "Modifier le groupe", + cannot_edit_institution_team: "Vous ne pouvez pas modifier un groupe appartenant à une institution", + remove_team: "Supprimer le groupe", + cannot_remove_institution_team: "Vous ne pouvez pas supprimer un groupe appartenant à une institution", + cannot_remove_team: "Vous ne pouvez pas supprimer un groupe lié à un débat", + add_user_in_team: "Ajouter l'utilisateur⋅rice au groupe", + remove_user_from_team: "Supprimer l'utilisateur⋅rice du groupe", + cannot_add_institution_user: "Vous ne pouvez pas ajouter un utilisateur⋅rice d'un groupe institutionel", + remove_user: "Supprimer l'utilisateur⋅rice", + remove_permanent_user: "Supprimer définitivement l'utilisateur⋅rice", + cannot_remove_institution_user: "Vous ne pouvez pas supprimer un⋅¢ utilisateur⋅rice d'un groupe institutionel", + cannot_create_institution_user: "Vous ne pouvez pas créer un⋅e utilisateur⋅rice dans un établissemnt", + cannot_create_institution_team: "Vous ne pouvez pas ajouter un groupe dans un établissement", + user_already_in_team: "L'utilisateur⋅rice fait déjà partie du groupe", + add_user_to_debate: "Ajouter l'utilisateur⋅rice au débat", + user_already_in_debate: "L'utilisateur⋅rice fait déjà partie du débat", + add_team_to_debate: "Ajouter le groupe au débat", + team_already_in_debate: "Le groupe fait déjà parti du débat", + used_for_connection: "Utilisé pour la connexion", + not_an_email: "Ce n'est pas une adresse e-mail", + different_passwords: "Mots de passes différents", + title_placeholder: "Un titre pertinent", + image_url_placeholder: "L'url d'une image", + restitution_display_details: "Survolez une tranche du graphique pour afficher ses données", + debate_created: "Votre débat a bien été créé sur le document '{documentName}' de la catégorie '{categoryName}'
Voulez-vous y accéder ?", + delete_category: "Vous êtes sur le point de supprimer la catégorie '{categoryName}'", + delete_document: "Vous êtes sur le point de supprimer le document '{documentName}'", + delete_debate: "Vous êtes sur le point de supprimer le débat '{debateName}'", + delete_team: "Vous êtes sur le point de supprimer le groupe '{teamName}'", + delete_user: "Vous êtes sur le point de supprimer l'utilisateur⋅rice '{userName}'", + delete_permanent_user: "Vous êtes sur le point de définitivement supprimer l'utilisateur⋅rice '{userName}'", + delete_permanent_user_warning: "Cette action est irréversible
Si l'utilisateur⋅rice a déja posté des arguments, cette action échouera.
Êtes vous sûr⋅e de vouloir continuer ?", + do_continue: "Êtes vous sûr⋅e de vouloir continuer ?", + password_changed: "Mot de passe mis à jour avec succès", + password_changed_loged_out: "Veuillez vous reconnecter avec votre nouveau mot de passe", + user_created_email: "Un e-mail à été envoyé à l'adresse saisie, cliquez sur le lien fourni pour activer votre compte", + user_activated: "Votre adresse e-mail a bien été vérifiée, vous pouvez fermer cette fenêtre et vous connecter", + username_exists: "Nom d'utilisateur⋅rice déjà existant", + email_exists: "Mail déjà existant", + tag_explanations: "Cliquez sur les mots-clefs cohérents.", + tag_input_explanations: "Presser Entrée pour valider", + report_comment: "Signaler l'argument", + report_details: "Vous vous apprétez à signaler un message à la modération.

Un message doit être signalé pour les raisons suivantes :

  • propos inappropriés ou insultants (par ex. : atteinte à la dignité, discours haineux, menaces)
  • opression systémique (par ex. : racisme, sexisme, homophobie)
  • contenu commercial (par ex. : publicité, promotion, appel d'offre)
  • autres propos sans lien aucun avec le débat en cours

Êtes vous sûr⋅e de vouloir continuer ?", + export: "Votre téléchargement va débuter... Si rien ne se passe cliquez ici", + password_forgotten: "

Vous avez oubié votre mot de passe ? Pas de problème !

Saisissez votre adresse e-mail ou votre pseudonyme.

", + password_forgotten_email: "

Si vous êtes enregistré⋅e, un e-mail expliquant la procédure de réinitialisation sera envoyé à l'adresse associée à votre compte.

Vérifiez votre boite mail.

", + theme_not_found: "Aucun résultat pour ce thème", + theme_already_set: "Thème déjà saisi", + public_debate: "Le débat sera accessible par n'importe quel utilisateur⋅ice, même non coonnecté⋅e", + reformulation_assist: "Affiche un smiley lors de la reformulation", + idefix_link: "Ajoute des tags aux documents et arguments pour les utiliser avec IDFIX", + with_hypostases: "Propose une selection d'hypostase pour les arguments", + aaf_import_success: "Les données AAF ont bien été importées, vous pouvez fermer cette fenêtre.", + update_tags: "Veuillez patienter, ce processus peut-être très long.
Ne fermez pas cette fenêtre", + tag_update_success: "La mise à jour des tags est un succès, vous pouvez fermer cette fenêtre." + }, + notification: { + team_added_to_debate: "Votre groupe {teamName} participe au débat {debateName}.", + invited_to_debate: "Vous êtes invité⋅e sur le débat {debateName}.", + comment_answered: "{firstName} {lastName} à répondu à votre argument.", + comment_moderated: "Votre argument à été modéré sur le débat {debateName}.", + comment_signaled: "Votre argument à été signalé sur le débat {debateName}." + }, + error: { + 'Insertion error': "Erreur d'enregistrement", + 'HTTP 404 Not Found': "HTTP 404 non trouvé", + 'Resource not found': "Resource non trouvée", + 'Authentication error': "Erreur d'authentification", + "Access denied": "Accès refusé", + "Invalid token": "Erreur d'authentification", + permission_missing: "Vous n'avez pas les droits", + invalid_token: "Authentification invalide
Veuillez vous reconnecter et réessayer", + unmutable_object: "Impossible de supprimer l'objet", + bad_credentials: "Identifiants incorrects", + duplicate_key: "La clef {keyName} avec la valeur {keyValue} existe déjà.", + mandatory_property: "La valeur {propertyName} est nécessaire.", + internal: "ERREUR INTERNE", + expired_token: "Jeton d'authentification expiré", + internal_message: "

Toutes nos excuses, une erreur s'est produite sur nos serveurs.

Veuillez réessayer ou contacter un administrateur⋅trice si l'erreur persiste.

", + aaf_import: "

Erreur lors de l'import AAF.

Il est probable que votre fichier soit corompu ou n'entre pas dans les standard de l'application.

", + tag_update_success: "

Erreur lors de la mise à jour des tags.

Contacter un développeur.

" + }, + menu: { + open: "Ouvrir un débat", + users: "Utilisateur⋅rice⋅s", + teams: "Groupes", + documents: "Documents", + my_debates: "Mes débats", + public_debates: "Débats publics", + logout: "Déconnection", + login: "Se connecter", + signin: "S'enregistrer" + }, + comment: { + add_argument: "Ajouter un argument", + reformulation: "Reformulation", + argumentation: "Argumentation", + against: "Plutôt pas d'accord", + for : "Plutôt d'accord", + neutral: "Pas compris", + is_argument: "Il s'agit d'un argument", + is_opinion: "Il s'agit d'une opinion", + opinion: "Opinion", + nb_answer: " |{count} réponse|{count} réponses", + select_hypostases: "Selectionnez une ou plusieurs hypostases dans la liste", + expert: "Expert" + }, + argumentation_check: { + waiting: "Attente de saisie", + loading: "Analyse en cours", + off_topic: "Reformulation hors sujet", + close: "Reformulation un peu éloignée", + nice: "Belle reformulation !", + identical: "Reformulation identique !" + }, + hypostase: { + qualitative: "Qualitatif", + quantitative: "Quantitatif", + structural: "Structurel", + difficulty: "Difficulté", + explanation: "Explicatif", + variance: "Variance", + mode: "Mode", + axiom: "Axiome", + hypothesis: "Hypothèse", + principle: "Principe", + classification: "Classification", + variation: "Variation", + value: "Valeur", + definition: "Définition", + paradigme: "Paradigme", + paradoxe: "Paradoxe", + clue: "Indice", + conjecture: "Conjecture", + problem: "Problème", + domain: "Domaine", + formalism: "Formalisme", + data: "Donnée", + belief: "Croyance", + theory: "Théorie", + law: "Loi", + aporia: "Aporie", + variable: "Variable", + dimension: "Dimension", + structure: "Structure", + object: "Objet", + approximation: "Approximation", + phenomenon: "Phénomène", + event: "Évènement", + invariant: "Invariant", + method: "Méthode" + }, + documentation: { + help: "

Aide

Cliquez sur la flèche pour passer à l'aide suivante, ou survolez les éléments qui vous questionnent.

", + user_panel: "

Panneau d'utilisateur⋅ice

Vous permet de changer de mot de passe et de vous déconnecter

", + notification_panel: "

Restez informé des débats auxquels vous participez.

Vous recevrez une notification lorsqu'une réponse est postée à un de vos arguments et lorsque vous avez été invité⋅e à un nouveau débat.

", + create_debate_with: "

Débatre avec

Sélectionnez les personnes et groupes qui pouront participer au débat. Si rien n'est sélectioné le débat sera public, accessible à tou⋅te⋅s

", + create_debate_document: "

Débatre sur

Sélectionnez le document sur lequel vous désirez porter le débat

", + create_debate_recap: "

Récapitulatif

Vérifiez les informations saisies et selectionez des paramètres avancés

", + debate_display: "

Informations supplémentaires

Sélectionnez Document pour afficher le document à débattre.
Sélectionnez Thème pour retrouver les arguments en lien avec une thématique donnée.
Sélectionnez Sélections pour afficher les parties de texte les plus argumentées.

", + debate_sort: "

Tri des arguments

Triez les arguments par date de rédaction ou par position dans le document.

", + debate_document: "

Document à débattre

Ici s'affiche le texte à débattre, lisez-le attentivement avant de proposer des arguments.

Sélectionnez une partie du texte sur laquelle vous souhaitez intervenir, une icône apparaîtra pour vous permettre d'argumenter.

Vous êtes sur une plateforme dédiée au débat, n'hésitez pas à défendre votre opinion avec des arguments : s’appuyer sur des données, utiliser des connaissances, donner des exemples, préciser vos sources, etc.

", + debate_bulets: "

Puces d'arguments

Les puces indiquent les sélections du texte sur lesquelles des arguments ont été produits. Les couleurs permettent de savoir si les arguments sont pour ou contre la sélection.

Au survol, la partie argumentée est mise en surbrillance.
Au clic, l'argument est sélectionné dans le panneau de droite.

", + debate_themes: "

Thèmes du débat

Saisissez un mot ou un groupe de mot définissant un thème et pressez Entrée

pour valier. Les argument savec le thème saisis seront alors calculé et mis en lien avec celui-ci.

Vous pouvez supprimer un thème an cliquant sur delete_forever

", + debate_scraps: "

Textes les plus selectioné

Voici la liste des portions de texte du document les plus sélectionnées pour argumenter. Chaque seletion est relier aux arguments qui la contienne.

", + debate_spaghettis: "

Spaghettis

" + }, + footer: { + collaborators: "Partenaires", + useful_links: "Liens utiles", + contact: "Contact", + about: "À propos", + contribute: "Contribuer sur GitHub", + } + } +} + + +const i18n = new VueI18n({ + locale: 'fr-FR', + fallbackLocale: 'fr-FR', + messages, + dateTimeFormats +}) \ No newline at end of file diff --git a/src/main/webapp/assets/js/service/i18n.min.js b/src/main/webapp/assets/js/service/i18n.min.js new file mode 100644 index 0000000..b9725cd --- /dev/null +++ b/src/main/webapp/assets/js/service/i18n.min.js @@ -0,0 +1,31 @@ +const dateTimeFormats={"fr-FR":{short:{year:"numeric",month:"short",day:"numeric"},long:{year:"numeric",month:"short",day:"numeric",weekday:"short",hour:"numeric",minute:"numeric"}}}; +const messages={"fr-FR":{password_forgotten:"Mot de passe oubli\u00e9",with_dots:"Avec...",on_the_doc:"Sur le document...",recapitulative:"R\u00e9capitulatif",by:"Par",proposed_by:"Propos\u00e9 par","with":"Avec",print:"Imprimer",connection:"Se connecter \u00e0 AREN",connect:"Se connecter",cas_connection:"Connexion CAS",cancel:"Annuler",validate:"Valider",close:"Fermer",yes:"Oui",no:"Non",i_am:"Je suis",debate:"D\u00e9bat",debate_tree:"Arbre du d\u00e9bat",comment_repartition:"R\u00e9partition des arguments", +debate_sunburst:"Topologie",odt_export:"Export du d\u00e9bat",nb_comment:"{count} argument|{count} arguments",nb_letter:"{count} lettre|{count} lettres",by_comment_count:"Par nombre d'arguments",by_letter_count:"Par nombre de lettres",by_user:"Par utilisateur\u22c5rice",by_opinion:"Par opinion",display_labels:"Afficher les l\u00e9gendes",display_arguments:"Afficher les arguments",tags_edition:"\u00c9dition des mots-clefs",tags:"Mots-clefs",proposed_tags:"Mots-clefs propos\u00e9s",no_tags_yet:"En recherche de proposition", +category_edition:"\u00c9dition de cat\u00e9gorie",category_creation:"Cr\u00e9ation de cat\u00e9gorie",team_edition:"\u00c9dition de groupe",team_creation:"Cr\u00e9ation de groupe",image:"Image",user_creation:"Cr\u00e9ation d'un\u22c5e untilisateur\u22c5rice",username:"Pseudonyme",email:"E-mail",first_name:"Pr\u00e9nom",last_name:"Nom de famille",password:"Mot de passe",remember_me:"Se souvenir de moi",old_password:"Mot de passe actuel",new_password:"Nouveau mot de passe",password_check:"V\u00e9rification du mot de passe", +change_password:"Changer de mot de passe",theme:"Th\u00e8me",scraps:"Selections",display:"Afficher",sort_by:"Trier par",date:"Date",position:"Position",creation_success:"Cr\u00e9ation r\u00e9ussie",import_success:"Importation r\u00e9ussie",update_success:"Mise \u00e0 jour r\u00e9ussie",display_team:"Afficher le groupe",new_team:"Nouveau groupe",new_user:"Nouvel\u22c5le utilisateur\u22c5rice",add_user:"Ajouter un\u22c5e utilisateur\u22c5rice",team_managment:"Gestion des groupes",user_managment:"Gestion des utilisateur\u22c5rices", +user_created:"Utilisateur\u22c5rice enregistr\u00e9\u22c5e",user_activated:"Utilisateur\u22c5rice activ\u00e9\u22c5e",anonymous_user:"Anonyme",save:"Sauvegarder",modify:"Modifier",nb_users:"Aucun utilisateur\u22c5rice|{count} utilisateur\u22c5rice|{count} utilisateur\u22c5rice\u22c5s",nb_teams:"Aucun groupe|{count} groupe|{count} groupes",nb_debates:"Aucun d\u00e9bat|{count} d\u00e9bat|{count} d\u00e9bats",nb_comments:"Aucun argument|{count} argument|{count} arguments",last_post_the:"Dernier post le", +no_post:"Aucun post",category:"Cat\u00e9gorie",title:"Titre",author:"Auteur\u22c5e",restitution:"Restitution",posts:"Posts",last_post:"Dernier post",document:"Document",teams:"Groupes",moderators:"Mod\u00e9rateur\u22c5rice.s",authority:"Status",users:"Utilisateur\u22c5rice\u22c5s",guests:"Invit\u00e9\u22c5e\u22c5s",debates:"D\u00e9bats",new_debate:"Nouveau d\u00e9bat",invite_in_debate:"Inviter au d\u00e9bat",SUPERADMIN:"Super administrateur\u22c5rice",SUPERADMIN:"Root",ADMIN:"Administrateur\u22c5rice", +MODO:"Mod\u00e9rateur\u22c5rice",USER:"Utilisateur\u22c5rice",GUEST:"Invit\u00e9\u22c5e",DELETED:"Supprim\u00e9",report:"Signalement",select_all:"Selectionner tout",unselect_all:"D\u00e9selectionner tout",advanced_options:"Options avanc\u00e9es",public_debate:"D\u00e9bat public",reformulation_assist:"Assistant de reformulation",idefix_link:"Lien IDEFIX",with_hypostases:"Avec hypostase",without_institution:"Sans \u00e9tablissement",running:"En cours...",import:"Importer",not_connected:"Vous n'\u00eates pas connect\u00e9\u22c5e", +tutorials:"Tutoriels",argue:"Argumenter",aaf_import:"Import AAF",update_tags:"Mise \u00e0 jour des tags",start:"Lancer",helper:{welcome:"Bienvenue sur la plateforme AREN (Argumentation & Num\u00e9rique)
Il s'agit d\u2019un espace num\u00e9rique de d\u00e9bat pour pratiquer l\u2019argumentation.
Prendre en compte les arguments des autres et justifier son opinion pour mieux argumenter et exercer son esprit critique !",creating_user:"Cr\u00e9ation en cour, veuillez patienter...",not_connected:"Vous devez \u00eatre inscrit\u22c5e et connect\u00e9\u22c5e pour r\u00e9aliser cette action", +mark_as_read:"Marquer comme lue",mark_as_unread:"Marquer comme non lue",cas_login:"Connectez-vous via le system CAS de l'ENT",add_document:"Ajouter un document",edit_category:"Modifier la cat\u00e9gorie",remove_category:"Supprimer la cat\u00e9gorie",cannot_remove_category:"Vous ne pouvez pas supprimer une cat\u00e9gorie contenant un document",copy_document:"Dupliquer le document",remove_debate:"Supprimer le d\u00e9bat",cannot_remove_debate:"Vous ne pouvez pas supprimer un d\u00e9bat contenant des arguments", +remove_document:"Supprimer le document",cannot_edit_document:"Vous ne pouvez pas modifier un document contenant un d\u00e9bat",cannot_remove_document:"Vous ne pouvez pas supprimer un document contenant un d\u00e9bat",edit_team:"Modifier le groupe",cannot_edit_institution_team:"Vous ne pouvez pas modifier un groupe appartenant \u00e0 une institution",remove_team:"Supprimer le groupe",cannot_remove_institution_team:"Vous ne pouvez pas supprimer un groupe appartenant \u00e0 une institution",cannot_remove_team:"Vous ne pouvez pas supprimer un groupe li\u00e9 \u00e0 un d\u00e9bat", +add_user_in_team:"Ajouter l'utilisateur\u22c5rice au groupe",remove_user_from_team:"Supprimer l'utilisateur\u22c5rice du groupe",cannot_add_institution_user:"Vous ne pouvez pas ajouter un utilisateur\u22c5rice d'un groupe institutionel",remove_user:"Supprimer l'utilisateur\u22c5rice",remove_permanent_user:"Supprimer d\u00e9finitivement l'utilisateur\u22c5rice",cannot_remove_institution_user:"Vous ne pouvez pas supprimer un\u22c5\u00a2 utilisateur\u22c5rice d'un groupe institutionel",cannot_create_institution_user:"Vous ne pouvez pas cr\u00e9er un\u22c5e utilisateur\u22c5rice dans un \u00e9tablissemnt", +cannot_create_institution_team:"Vous ne pouvez pas ajouter un groupe dans un \u00e9tablissement",user_already_in_team:"L'utilisateur\u22c5rice fait d\u00e9j\u00e0 partie du groupe",add_user_to_debate:"Ajouter l'utilisateur\u22c5rice au d\u00e9bat",user_already_in_debate:"L'utilisateur\u22c5rice fait d\u00e9j\u00e0 partie du d\u00e9bat",add_team_to_debate:"Ajouter le groupe au d\u00e9bat",team_already_in_debate:"Le groupe fait d\u00e9j\u00e0 parti du d\u00e9bat",used_for_connection:"Utilis\u00e9 pour la connexion", +not_an_email:"Ce n'est pas une adresse e-mail",different_passwords:"Mots de passes diff\u00e9rents",title_placeholder:"Un titre pertinent",image_url_placeholder:"L'url d'une image",restitution_display_details:"Survolez une tranche du graphique pour afficher ses donn\u00e9es",debate_created:"Votre d\u00e9bat a bien \u00e9t\u00e9 cr\u00e9\u00e9 sur le document '{documentName}' de la cat\u00e9gorie '{categoryName}'
Voulez-vous y acc\u00e9der ?",delete_category:"Vous \u00eates sur le point de supprimer la cat\u00e9gorie '{categoryName}'", +delete_document:"Vous \u00eates sur le point de supprimer le document '{documentName}'",delete_debate:"Vous \u00eates sur le point de supprimer le d\u00e9bat '{debateName}'",delete_team:"Vous \u00eates sur le point de supprimer le groupe '{teamName}'",delete_user:"Vous \u00eates sur le point de supprimer l'utilisateur\u22c5rice '{userName}'",delete_permanent_user:"Vous \u00eates sur le point de d\u00e9finitivement supprimer l'utilisateur\u22c5rice '{userName}'",delete_permanent_user_warning:"Cette action est irr\u00e9versible
Si l'utilisateur\u22c5rice a d\u00e9ja post\u00e9 des arguments, cette action \u00e9chouera.
\u00cates vous s\u00fbr\u22c5e de vouloir continuer ?", +do_continue:"\u00cates vous s\u00fbr\u22c5e de vouloir continuer ?",password_changed:"Mot de passe mis \u00e0 jour avec succ\u00e8s",password_changed_loged_out:"Veuillez vous reconnecter avec votre nouveau mot de passe",user_created_email:"Un e-mail \u00e0 \u00e9t\u00e9 envoy\u00e9 \u00e0 l'adresse saisie, cliquez sur le lien fourni pour activer votre compte",user_activated:"Votre adresse e-mail a bien \u00e9t\u00e9 v\u00e9rifi\u00e9e, vous pouvez fermer cette fen\u00eatre et vous connecter",username_exists:"Nom d'utilisateur\u22c5rice d\u00e9j\u00e0 existant", +email_exists:"Mail d\u00e9j\u00e0 existant",tag_explanations:"Cliquez sur les mots-clefs coh\u00e9rents.",tag_input_explanations:"Presser Entr\u00e9e pour valider",report_comment:"Signaler l'argument",report_details:"Vous vous appr\u00e9tez \u00e0 signaler un message \u00e0 la mod\u00e9ration.

Un message doit \u00eatre signal\u00e9 pour les raisons suivantes :

  • propos inappropri\u00e9s ou insultants (par ex. : atteinte \u00e0 la dignit\u00e9, discours haineux, menaces)
  • opression syst\u00e9mique (par ex. : racisme, sexisme, homophobie)
  • contenu commercial (par ex. : publicit\u00e9, promotion, appel d'offre)
  • autres propos sans lien aucun avec le d\u00e9bat en cours

\u00cates vous s\u00fbr\u22c5e de vouloir continuer ?", +export:"Votre t\u00e9l\u00e9chargement va d\u00e9buter... Si rien ne se passe cliquez ici",password_forgotten:"

Vous avez oubi\u00e9 votre mot de passe ? Pas de probl\u00e8me !

Saisissez votre adresse e-mail ou votre pseudonyme.

",password_forgotten_email:"

Si vous \u00eates enregistr\u00e9\u22c5e, un e-mail expliquant la proc\u00e9dure de r\u00e9initialisation sera envoy\u00e9 \u00e0 l'adresse associ\u00e9e \u00e0 votre compte.

V\u00e9rifiez votre boite mail.

", +theme_not_found:"Aucun r\u00e9sultat pour ce th\u00e8me",theme_already_set:"Th\u00e8me d\u00e9j\u00e0 saisi",public_debate:"Le d\u00e9bat sera accessible par n'importe quel utilisateur\u22c5ice, m\u00eame non coonnect\u00e9\u22c5e",reformulation_assist:"Affiche un smiley lors de la reformulation",idefix_link:"Ajoute des tags aux documents et arguments pour les utiliser avec IDFIX",with_hypostases:"Propose une selection d'hypostase pour les arguments",aaf_import_success:"Les donn\u00e9es AAF ont bien \u00e9t\u00e9 import\u00e9es, vous pouvez fermer cette fen\u00eatre.", +update_tags:"Veuillez patienter, ce processus peut-\u00eatre tr\u00e8s long.
Ne fermez pas cette fen\u00eatre",tag_update_success:"La mise \u00e0 jour des tags est un succ\u00e8s, vous pouvez fermer cette fen\u00eatre."},notification:{team_added_to_debate:"Votre groupe {teamName} participe au d\u00e9bat {debateName}.",invited_to_debate:"Vous \u00eates invit\u00e9\u22c5e sur le d\u00e9bat {debateName}.",comment_answered:"{firstName} {lastName} \u00e0 r\u00e9pondu \u00e0 votre argument.", +comment_moderated:"Votre argument \u00e0 \u00e9t\u00e9 mod\u00e9r\u00e9 sur le d\u00e9bat {debateName}.",comment_signaled:"Votre argument \u00e0 \u00e9t\u00e9 signal\u00e9 sur le d\u00e9bat {debateName}."},error:{"Insertion error":"Erreur d'enregistrement","HTTP 404 Not Found":"HTTP 404 non trouv\u00e9","Resource not found":"Resource non trouv\u00e9e","Authentication error":"Erreur d'authentification","Access denied":"Acc\u00e8s refus\u00e9","Invalid token":"Erreur d'authentification",permission_missing:"Vous n'avez pas les droits", +invalid_token:"Authentification invalide
Veuillez vous reconnecter et r\u00e9essayer",unmutable_object:"Impossible de supprimer l'objet",bad_credentials:"Identifiants incorrects",duplicate_key:"La clef {keyName} avec la valeur {keyValue} existe d\u00e9j\u00e0.",mandatory_property:"La valeur {propertyName} est n\u00e9cessaire.",internal:"ERREUR INTERNE",expired_token:"Jeton d'authentification expir\u00e9",internal_message:"

Toutes nos excuses, une erreur s'est produite sur nos serveurs.

Veuillez r\u00e9essayer ou contacter un administrateur\u22c5trice si l'erreur persiste.

", +aaf_import:"

Erreur lors de l'import AAF.

Il est probable que votre fichier soit corompu ou n'entre pas dans les standard de l'application.

",tag_update_success:"

Erreur lors de la mise \u00e0 jour des tags.

Contacter un d\u00e9veloppeur.

"},menu:{open:"Ouvrir un d\u00e9bat",users:"Utilisateur\u22c5rice\u22c5s",teams:"Groupes",documents:"Documents",my_debates:"Mes d\u00e9bats",public_debates:"D\u00e9bats publics",logout:"D\u00e9connection",login:"Se connecter",signin:"S'enregistrer"}, +comment:{add_argument:"Ajouter un argument",reformulation:"Reformulation",argumentation:"Argumentation",against:"Plut\u00f4t pas d'accord",for:"Plut\u00f4t d'accord",neutral:"Pas compris",is_argument:"Il s'agit d'un argument",is_opinion:"Il s'agit d'une opinion",opinion:"Opinion",nb_answer:" |{count} r\u00e9ponse|{count} r\u00e9ponses",select_hypostases:"Selectionnez une ou plusieurs hypostases dans la liste",expert:"Expert"},argumentation_check:{waiting:"Attente de saisie",loading:"Analyse en cours", +off_topic:"Reformulation hors sujet",close:"Reformulation un peu \u00e9loign\u00e9e",nice:"Belle reformulation !",identical:"Reformulation identique !"},hypostase:{qualitative:"Qualitatif",quantitative:"Quantitatif",structural:"Structurel",difficulty:"Difficult\u00e9",explanation:"Explicatif",variance:"Variance",mode:"Mode",axiom:"Axiome",hypothesis:"Hypoth\u00e8se",principle:"Principe",classification:"Classification",variation:"Variation",value:"Valeur",definition:"D\u00e9finition",paradigme:"Paradigme", +paradoxe:"Paradoxe",clue:"Indice",conjecture:"Conjecture",problem:"Probl\u00e8me",domain:"Domaine",formalism:"Formalisme",data:"Donn\u00e9e",belief:"Croyance",theory:"Th\u00e9orie",law:"Loi",aporia:"Aporie",variable:"Variable",dimension:"Dimension",structure:"Structure",object:"Objet",approximation:"Approximation",phenomenon:"Ph\u00e9nom\u00e8ne",event:"\u00c9v\u00e8nement",invariant:"Invariant",method:"M\u00e9thode"},documentation:{help:"

Aide

Cliquez sur la fl\u00e8che pour passer \u00e0 l'aide suivante, ou survolez les \u00e9l\u00e9ments qui vous questionnent.

", +user_panel:"

Panneau d'utilisateur\u22c5ice

Vous permet de changer de mot de passe et de vous d\u00e9connecter

",notification_panel:"

Restez inform\u00e9 des d\u00e9bats auxquels vous participez.

Vous recevrez une notification lorsqu'une r\u00e9ponse est post\u00e9e \u00e0 un de vos arguments et lorsque vous avez \u00e9t\u00e9 invit\u00e9\u22c5e \u00e0 un nouveau d\u00e9bat.

",create_debate_with:"

D\u00e9batre avec

S\u00e9lectionnez les personnes et groupes qui pouront participer au d\u00e9bat. Si rien n'est s\u00e9lection\u00e9 le d\u00e9bat sera public, accessible \u00e0 tou\u22c5te\u22c5s

", +create_debate_document:"

D\u00e9batre sur

S\u00e9lectionnez le document sur lequel vous d\u00e9sirez porter le d\u00e9bat

",create_debate_recap:"

R\u00e9capitulatif

V\u00e9rifiez les informations saisies et selectionez des param\u00e8tres avanc\u00e9s

",debate_display:"

Informations suppl\u00e9mentaires

S\u00e9lectionnez Document pour afficher le document \u00e0 d\u00e9battre.
S\u00e9lectionnez Th\u00e8me pour retrouver les arguments en lien avec une th\u00e9matique donn\u00e9e.
S\u00e9lectionnez S\u00e9lections pour afficher les parties de texte les plus argument\u00e9es.

", +debate_sort:"

Tri des arguments

Triez les arguments par date de r\u00e9daction ou par position dans le document.

",debate_document:"

Document \u00e0 d\u00e9battre

Ici s'affiche le texte \u00e0 d\u00e9battre, lisez-le attentivement avant de proposer des arguments.

S\u00e9lectionnez une partie du texte sur laquelle vous souhaitez intervenir, une ic\u00f4ne appara\u00eetra pour vous permettre d'argumenter.

Vous \u00eates sur une plateforme d\u00e9di\u00e9e au d\u00e9bat, n'h\u00e9sitez pas \u00e0 d\u00e9fendre votre opinion avec des arguments : s\u2019appuyer sur des donn\u00e9es, utiliser des connaissances, donner des exemples, pr\u00e9ciser vos sources, etc.

", +debate_bulets:"

Puces d'arguments

Les puces indiquent les s\u00e9lections du texte sur lesquelles des arguments ont \u00e9t\u00e9 produits. Les couleurs permettent de savoir si les arguments sont pour ou contre la s\u00e9lection.

Au survol, la partie argument\u00e9e est mise en surbrillance.
Au clic, l'argument est s\u00e9lectionn\u00e9 dans le panneau de droite.

",debate_themes:"

Th\u00e8mes du d\u00e9bat

Saisissez un mot ou un groupe de mot d\u00e9finissant un th\u00e8me et pressez Entr\u00e9e

pour valier. Les argument savec le th\u00e8me saisis seront alors calcul\u00e9 et mis en lien avec celui-ci.

Vous pouvez supprimer un th\u00e8me an cliquant sur delete_forever

", +debate_scraps:"

Textes les plus selection\u00e9

Voici la liste des portions de texte du document les plus s\u00e9lectionn\u00e9es pour argumenter. Chaque seletion est relier aux arguments qui la contienne.

",debate_spaghettis:"

Spaghettis

"},footer:{collaborators:"Partenaires",useful_links:"Liens utiles",contact:"Contact",about:"\u00c0 propos",contribute:"Contribuer sur GitHub"}}};const i18n=new VueI18n({locale:"fr-FR",fallbackLocale:"fr-FR",messages,dateTimeFormats}); \ No newline at end of file diff --git a/src/main/webapp/assets/js/service/worker.js b/src/main/webapp/assets/js/service/worker.js new file mode 100644 index 0000000..39493b7 --- /dev/null +++ b/src/main/webapp/assets/js/service/worker.js @@ -0,0 +1,31 @@ +var connections = 0; +var sources = {}; + +onconnect = function (e) { + let port = e.ports[0]; + connections++; + + port.addEventListener("message", function (e) { + let url = e.data; + + if (!sources.hasOwnProperty(url)) { + sources[url] = new EventSource(url); + } + + sources[url].addEventListener("message", (message) => { + console.clear(); + console.log(message); + port.postMessage({url: url, data: message.data}); + }, false); + + }, false); + + port.start(); +} + +onbeforeunload = function () { + connections--; + if (connections === 0) { + self.terminate(); + } +} \ No newline at end of file diff --git a/src/main/webapp/assets/js/service/worker.min.js b/src/main/webapp/assets/js/service/worker.min.js new file mode 100644 index 0000000..4d374b8 --- /dev/null +++ b/src/main/webapp/assets/js/service/worker.min.js @@ -0,0 +1 @@ +var connections=0,sources={};onconnect=function(a){let c=a.ports[0];connections++;c.addEventListener("message",function(a){let b=a.data;sources.hasOwnProperty(b)||(sources[b]=new EventSource(b));sources[b].addEventListener("message",a=>{console.clear();console.log(a);c.postMessage({url:b,data:a.data})},!1)},!1);c.start()};onbeforeunload=function(){connections--;0===connections&&self.terminate()}; \ No newline at end of file diff --git a/src/main/webapp/assets/js/utils.js b/src/main/webapp/assets/js/utils.js new file mode 100644 index 0000000..8f5d14b --- /dev/null +++ b/src/main/webapp/assets/js/utils.js @@ -0,0 +1,259 @@ +function decycle(obj, stack = [ ]) { + if (!obj || typeof obj !== 'object') + return obj; + + if (stack.includes(obj)) + return null; + + let s = stack.concat([obj]); + + return Array.isArray(obj) ? obj.map(x => decycle(x, s)) + : Object.assign(new obj.constructor(), Object.fromEntries( + Object.entries(obj) + .map(([k, v]) => [k, decycle(v, s)]))); +} + +function vueLoader(file) { + return httpVueLoader('assets/js/' + file + '.vue'); +} + +/***** Useful function on prototypes *****/ +Array.prototype.remove = function (obj) { + let index = this.indexOf(obj); + if (index !== -1) { + this.splice(index, 1); + return true; + } else { + return false; + } +}; + +Array.prototype.compare = function (obj) { + if (this === obj) { + return 0; + } + let len = Math.max(this.length, obj.length); + for (let i = 0; i < len; i++) { + if (this[i] === undefined || obj[i] !== undefined && this[i] < obj[i]) { + return -1; + } else if (obj[i] === undefined || this[i] !== undefined && this[i] > obj[i]) { + return 1; + } + } + return 0; +} + +if (!Array.prototype.includes) { + Array.prototype.includes = function (obj) { + return this.indexOf(obj) !== -1; + } +} + +if (!String.prototype.includes) { + String.prototype.includes = function (obj) { + return this.indexOf(obj) !== -1; + } +} + +Node.prototype.getChildPathTo = function (el) { + if (el === this) { + return ""; + } + let sibIndex = -1; + let len = el.parentNode.childNodes.length; + let sib; + while (sibIndex < len && sib !== el) { + sibIndex++; + sib = el.parentNode.childNodes[sibIndex]; + } + if (el.parentNode === this) { + return sibIndex; + } else { + return this.getChildPathTo(el.parentNode) + "/" + sibIndex; + } +}; + +Node.prototype.childPathSelector = function (path) { + if (path.constructor !== String) { + path = path + ""; + } + let arrayPath = path.split("/"); + var result = this; + let len = arrayPath.length; + for (let i = 0; i < len; i++) { + if (result.childNodes.length > arrayPath[i]) { + result = result.childNodes[arrayPath[i]]; + } else { + console.warn("Warning : impossible to find child number " + arrayPath[i] + ". The return child may be wrong.", this, result); + } + } + return result; +}; + +Node.prototype.forEachNode = function (callback, origin = this, end = false, index = []) { + if (end && this === origin) { + return null; + } + if (!end && callback) { + callback(this, [...index], origin); + } + if (!end && this.firstChild !== null) { + index.push(0); + this.firstChild.forEachNode(callback, origin, false, index); + } else if (this.nextSibling !== null) { + index[index.length - 1]++; + this.nextSibling.forEachNode(callback, origin, false, index); + } else { + index.pop(); + this.parentNode.forEachNode(callback, origin, true, index); +} +} + +/***** Selection handling *****/ +function compareRange(type, r1, r2) { + let pos1, pos2; + switch (type) { + case Range.START_TO_START: + pos1 = (r1.startContainer + "/" + r1.startOffset).split("/").map(v => v * 1); + pos2 = (r2.startContainer + "/" + r2.startOffset).split("/").map(v => v * 1); + break; + case Range.START_TO_END: + pos1 = (r1.startContainer + "/" + r1.startOffset).split("/").map(v => v * 1); + pos2 = (r2.endContainer + "/" + r2.endOffset).split("/").map(v => v * 1); + break; + case Range.END_TO_START: + pos1 = (r1.endContainer + "/" + r1.endOffset).split("/").map(v => v * 1); + pos2 = (r2.startContainer + "/" + r2.startOffset).split("/").map(v => v * 1); + break; + case Range.END_TO_END: + pos1 = (r1.endContainer + "/" + r1.endOffset).split("/").map(v => v * 1); + pos2 = (r2.endContainer + "/" + r2.endOffset).split("/").map(v => v * 1); + break; + default: + throw "Invalid first parameter. Use Range.START_TO_START, Range.START_TO_END, Range.END_TO_START or Range.END_TO_END."; + } + return pos1.compare(pos2); +} + +Range.prototype.setPathStart = function (container, startContainer, startOffset) { + this.setStart(startContainer ? container.childPathSelector(startContainer) : container.firstChild, startOffset); +} + +Range.prototype.setPathEnd = function (container, endContainer, endOffset) { + this.setEnd(endContainer ? container.childPathSelector(endContainer) : container.firstChild, endOffset); +} + +Range.prototype.getHtml = function () { + let div = document.createElement('div'); + div.appendChild(this.cloneContents()); + return div.innerHTML; +} + +Range.prototype.affineToWord = function () { + let regExp = new RegExp('[A-Za-zÀ-ÖØ-öø-ÿ\'\.\n\t]'); + while (this.startOffset > 0 && regExp.test(this.toString().charAt(0))) { + this.setStart(this.startContainer, this.startOffset - 1); + } + if (this.startOffset !== 0) { + this.setStart(this.startContainer, this.startOffset + 1); + } + while (this.endOffset < this.endContainer.length && regExp.test(this.toString().slice(-1))) { + this.setEnd(this.endContainer, this.endOffset + 1); + } + if (!regExp.test(this.toString().slice(-1)) && this.endOffset !== 0) { + this.setEnd(this.endContainer, this.endOffset - 1); + } +} + +function clearSelection() { + if (window.getSelection) { + window.getSelection().removeAllRanges(); + } else if (document.selection) { + document.selection.empty(); + } +} + + +/***** Smooth Scroll *****/ +var scrollProcess = []; + +Math.easeOutExpo = function (time, origin, delta, duration) { + return delta * (-Math.pow(2, -10 * time / duration) + 1) + origin; +}; + +function clearAllSmoothScroll(container) { + let index = scrollProcess.findIndex((s) => s.container === container); + if (index !== -1) { + let len = scrollProcess[index].intervals.length; + for (var i = 0; i < len; i++) { + clearInterval(scrollProcess[index].intervals[i]); + } + scrollProcess.splice(index, 1); + } +} + +function smoothScroll(container, scrollGoal, callback, duration = 0.5) { + clearAllSmoothScroll(container); + + let scrollDir = container.scrollTop < scrollGoal ? 1 : -1; + let timeInt = 5; + + let time = 0; + let origin = container.scrollTop; + let delta = scrollGoal - container.scrollTop; + duration = duration * (1000 / timeInt); + + let index = scrollProcess.findIndex((s) => s.container === container); + if (index === -1) { + scrollProcess.push({ + container, + intervals: [] + }); + index = scrollProcess.length - 1; + } + + scrollProcess[index].intervals.push(setInterval(() => { + if (time === duration + || scrollDir === 1 && ( + container.scrollTop === container.scrollTopMax + || container.scrollTop >= scrollGoal - 1) + || scrollDir === -1 && ( + container.scrollTop === 0 + || container.scrollTop <= scrollGoal + 1) + ) { + clearAllSmoothScroll(container); + if (callback) { + callback(); + } + } else { + container.scrollTop = Math.easeOutExpo(time, origin, delta, duration); + time++; + } + }, timeInt)); +} + +function scrollCenter(container, element, callback, duration = 0.5) { + let elemRect = element.getBoundingClientRect(); + let containerRect = container.getBoundingClientRect(); + let scrollGoal = elemRect.top + (container.scrollTop - containerRect.top); + smoothScroll(container, scrollGoal - (containerRect.height / 4), callback, duration); +} + +function inScrollView(container, element) { + let elemRect = element.getBoundingClientRect(); + let containerRect = container.getBoundingClientRect(); + let scrollTop = elemRect.top + (container.scrollTop - containerRect.top); + let scrollBottom = elemRect.top + (container.scrollTop - containerRect.top - containerRect.height) + elemRect.height; + return (container.scrollTop < scrollTop && container.scrollTop > scrollBottom); +} + +/***** Color function *****/ +const HSL = { + fromString(color) { + let match = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(color); + return {h: match[1], s: match[2], l: match[3] / 100}; + }, + toString(hsl) { + return "hsl(" + hsl.h + ", " + hsl.s * 100 + "%, " + hsl.l * 100 + "%)"; + } +} \ No newline at end of file diff --git a/src/main/webapp/assets/js/utils.min.js b/src/main/webapp/assets/js/utils.min.js new file mode 100644 index 0000000..94a6810 --- /dev/null +++ b/src/main/webapp/assets/js/utils.min.js @@ -0,0 +1,13 @@ +function decycle(a,b=[]){if(!a||"object"!==typeof a)return a;if(b.includes(a))return null;let c=b.concat([a]);return Array.isArray(a)?a.map(a=>decycle(a,c)):Object.assign(new a.constructor,Object.fromEntries(Object.entries(a).map(([a,b])=>[a,decycle(b,c)])))}function vueLoader(a){return httpVueLoader("assets/js/"+a+".vue")}Array.prototype.remove=function(a){a=this.indexOf(a);return-1!==a?(this.splice(a,1),!0):!1}; +Array.prototype.compare=function(a){if(this===a)return 0;let b=Math.max(this.length,a.length);for(let c=0;ca[c])return 1}return 0};Array.prototype.includes||(Array.prototype.includes=function(a){return-1!==this.indexOf(a)});String.prototype.includes||(String.prototype.includes=function(a){return-1!==this.indexOf(a)}); +Node.prototype.getChildPathTo=function(a){if(a===this)return"";let b=-1,c=a.parentNode.childNodes.length,d;for(;ba[d]?b=b.childNodes[a[d]]:console.warn("Warning : impossible to find child number "+a[d]+". The return child may be wrong.",this,b);return b}; +Node.prototype.forEachNode=function(a,b=this,c=!1,d=[]){if(c&&this===b)return null;!c&&a&&a(this,[...d],b);c||null===this.firstChild?null!==this.nextSibling?(d[d.length-1]++,this.nextSibling.forEachNode(a,b,!1,d)):(d.pop(),this.parentNode.forEachNode(a,b,!0,d)):(d.push(0),this.firstChild.forEachNode(a,b,!1,d))}; +function compareRange(a,b,c){switch(a){case Range.START_TO_START:a=(b.startContainer+"/"+b.startOffset).split("/").map(a=>1*a);c=(c.startContainer+"/"+c.startOffset).split("/").map(a=>1*a);break;case Range.START_TO_END:a=(b.startContainer+"/"+b.startOffset).split("/").map(a=>1*a);c=(c.endContainer+"/"+c.endOffset).split("/").map(a=>1*a);break;case Range.END_TO_START:a=(b.endContainer+"/"+b.endOffset).split("/").map(a=>1*a);c=(c.startContainer+"/"+c.startOffset).split("/").map(a=>1*a);break;case Range.END_TO_END:a= +(b.endContainer+"/"+b.endOffset).split("/").map(a=>1*a);c=(c.endContainer+"/"+c.endOffset).split("/").map(a=>1*a);break;default:throw"Invalid first parameter. Use Range.START_TO_START, Range.START_TO_END, Range.END_TO_START or Range.END_TO_END.";}return a.compare(c)}Range.prototype.setPathStart=function(a,b,c){this.setStart(b?a.childPathSelector(b):a.firstChild,c)};Range.prototype.setPathEnd=function(a,b,c){this.setEnd(b?a.childPathSelector(b):a.firstChild,c)}; +Range.prototype.getHtml=function(){let a=document.createElement("div");a.appendChild(this.cloneContents());return a.innerHTML}; +Range.prototype.affineToWord=function(){let a=/[A-Za-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u00ff'.\n\t]/;for(;0b.container===a);if(-1!==b){let a=scrollProcess[b].intervals.length;for(var c=0;cb.container===a);-1===g&&(scrollProcess.push({container:a,intervals:[]}),g=scrollProcess.length-1);scrollProcess[g].intervals.push(setInterval(()=>{f===d||1===e&&(a.scrollTop===a.scrollTopMax||a.scrollTop>=b-1)||-1===e&&(0===a.scrollTop||a.scrollTop<=b+1)?(clearAllSmoothScroll(a),c&&c()):(a.scrollTop=Math.easeOutExpo(f,h,k,d),f++)},5))} +function scrollCenter(a,b,c,d=.5){b=b.getBoundingClientRect();let e=a.getBoundingClientRect();smoothScroll(a,b.top+(a.scrollTop-e.top)-e.height/4,c,d)}function inScrollView(a,b){b=b.getBoundingClientRect();let c=a.getBoundingClientRect(),d=b.top+(a.scrollTop-c.top-c.height)+b.height;return a.scrollTopd} +const HSL={fromString(a){a=/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(a);return{h:a[1],s:a[2],l:a[3]/100}},toString(a){return"hsl("+a.h+", "+100*a.s+"%, "+100*a.l+"%)"}}; \ No newline at end of file diff --git a/src/main/webapp/assets/js/vendors/axios.js b/src/main/webapp/assets/js/vendors/axios.js new file mode 100644 index 0000000..6dd94bd --- /dev/null +++ b/src/main/webapp/assets/js/vendors/axios.js @@ -0,0 +1,1756 @@ +/* axios v0.21.1 | (c) 2020 by Matt Zabriskie */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["axios"] = factory(); + else + root["axios"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + module.exports = __webpack_require__(1); + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + var bind = __webpack_require__(3); + var Axios = __webpack_require__(4); + var mergeConfig = __webpack_require__(22); + var defaults = __webpack_require__(10); + + /** + * Create an instance of Axios + * + * @param {Object} defaultConfig The default config for the instance + * @return {Axios} A new instance of Axios + */ + function createInstance(defaultConfig) { + var context = new Axios(defaultConfig); + var instance = bind(Axios.prototype.request, context); + + // Copy axios.prototype to instance + utils.extend(instance, Axios.prototype, context); + + // Copy context to instance + utils.extend(instance, context); + + return instance; + } + + // Create the default instance to be exported + var axios = createInstance(defaults); + + // Expose Axios class to allow class inheritance + axios.Axios = Axios; + + // Factory for creating new instances + axios.create = function create(instanceConfig) { + return createInstance(mergeConfig(axios.defaults, instanceConfig)); + }; + + // Expose Cancel & CancelToken + axios.Cancel = __webpack_require__(23); + axios.CancelToken = __webpack_require__(24); + axios.isCancel = __webpack_require__(9); + + // Expose all/spread + axios.all = function all(promises) { + return Promise.all(promises); + }; + axios.spread = __webpack_require__(25); + + // Expose isAxiosError + axios.isAxiosError = __webpack_require__(26); + + module.exports = axios; + + // Allow use of default import syntax in TypeScript + module.exports.default = axios; + + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var bind = __webpack_require__(3); + + /*global toString:true*/ + + // utils is a library of generic helper functions non-specific to axios + + var toString = Object.prototype.toString; + + /** + * Determine if a value is an Array + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an Array, otherwise false + */ + function isArray(val) { + return toString.call(val) === '[object Array]'; + } + + /** + * Determine if a value is undefined + * + * @param {Object} val The value to test + * @returns {boolean} True if the value is undefined, otherwise false + */ + function isUndefined(val) { + return typeof val === 'undefined'; + } + + /** + * Determine if a value is a Buffer + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Buffer, otherwise false + */ + function isBuffer(val) { + return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor) + && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val); + } + + /** + * Determine if a value is an ArrayBuffer + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an ArrayBuffer, otherwise false + */ + function isArrayBuffer(val) { + return toString.call(val) === '[object ArrayBuffer]'; + } + + /** + * Determine if a value is a FormData + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an FormData, otherwise false + */ + function isFormData(val) { + return (typeof FormData !== 'undefined') && (val instanceof FormData); + } + + /** + * Determine if a value is a view on an ArrayBuffer + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false + */ + function isArrayBufferView(val) { + var result; + if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { + result = ArrayBuffer.isView(val); + } else { + result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer); + } + return result; + } + + /** + * Determine if a value is a String + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a String, otherwise false + */ + function isString(val) { + return typeof val === 'string'; + } + + /** + * Determine if a value is a Number + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Number, otherwise false + */ + function isNumber(val) { + return typeof val === 'number'; + } + + /** + * Determine if a value is an Object + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an Object, otherwise false + */ + function isObject(val) { + return val !== null && typeof val === 'object'; + } + + /** + * Determine if a value is a plain Object + * + * @param {Object} val The value to test + * @return {boolean} True if value is a plain Object, otherwise false + */ + function isPlainObject(val) { + if (toString.call(val) !== '[object Object]') { + return false; + } + + var prototype = Object.getPrototypeOf(val); + return prototype === null || prototype === Object.prototype; + } + + /** + * Determine if a value is a Date + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Date, otherwise false + */ + function isDate(val) { + return toString.call(val) === '[object Date]'; + } + + /** + * Determine if a value is a File + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a File, otherwise false + */ + function isFile(val) { + return toString.call(val) === '[object File]'; + } + + /** + * Determine if a value is a Blob + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Blob, otherwise false + */ + function isBlob(val) { + return toString.call(val) === '[object Blob]'; + } + + /** + * Determine if a value is a Function + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Function, otherwise false + */ + function isFunction(val) { + return toString.call(val) === '[object Function]'; + } + + /** + * Determine if a value is a Stream + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Stream, otherwise false + */ + function isStream(val) { + return isObject(val) && isFunction(val.pipe); + } + + /** + * Determine if a value is a URLSearchParams object + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a URLSearchParams object, otherwise false + */ + function isURLSearchParams(val) { + return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; + } + + /** + * Trim excess whitespace off the beginning and end of a string + * + * @param {String} str The String to trim + * @returns {String} The String freed of excess whitespace + */ + function trim(str) { + return str.replace(/^\s*/, '').replace(/\s*$/, ''); + } + + /** + * Determine if we're running in a standard browser environment + * + * This allows axios to run in a web worker, and react-native. + * Both environments support XMLHttpRequest, but not fully standard globals. + * + * web workers: + * typeof window -> undefined + * typeof document -> undefined + * + * react-native: + * navigator.product -> 'ReactNative' + * nativescript + * navigator.product -> 'NativeScript' or 'NS' + */ + function isStandardBrowserEnv() { + if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' || + navigator.product === 'NativeScript' || + navigator.product === 'NS')) { + return false; + } + return ( + typeof window !== 'undefined' && + typeof document !== 'undefined' + ); + } + + /** + * Iterate over an Array or an Object invoking a function for each item. + * + * If `obj` is an Array callback will be called passing + * the value, index, and complete array for each item. + * + * If 'obj' is an Object callback will be called passing + * the value, key, and complete object for each property. + * + * @param {Object|Array} obj The object to iterate + * @param {Function} fn The callback to invoke for each item + */ + function forEach(obj, fn) { + // Don't bother if no value provided + if (obj === null || typeof obj === 'undefined') { + return; + } + + // Force an array if not already something iterable + if (typeof obj !== 'object') { + /*eslint no-param-reassign:0*/ + obj = [obj]; + } + + if (isArray(obj)) { + // Iterate over array values + for (var i = 0, l = obj.length; i < l; i++) { + fn.call(null, obj[i], i, obj); + } + } else { + // Iterate over object keys + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + fn.call(null, obj[key], key, obj); + } + } + } + } + + /** + * Accepts varargs expecting each argument to be an object, then + * immutably merges the properties of each object and returns result. + * + * When multiple objects contain the same key the later object in + * the arguments list will take precedence. + * + * Example: + * + * ```js + * var result = merge({foo: 123}, {foo: 456}); + * console.log(result.foo); // outputs 456 + * ``` + * + * @param {Object} obj1 Object to merge + * @returns {Object} Result of all merge properties + */ + function merge(/* obj1, obj2, obj3, ... */) { + var result = {}; + function assignValue(val, key) { + if (isPlainObject(result[key]) && isPlainObject(val)) { + result[key] = merge(result[key], val); + } else if (isPlainObject(val)) { + result[key] = merge({}, val); + } else if (isArray(val)) { + result[key] = val.slice(); + } else { + result[key] = val; + } + } + + for (var i = 0, l = arguments.length; i < l; i++) { + forEach(arguments[i], assignValue); + } + return result; + } + + /** + * Extends object a by mutably adding to it the properties of object b. + * + * @param {Object} a The object to be extended + * @param {Object} b The object to copy properties from + * @param {Object} thisArg The object to bind function to + * @return {Object} The resulting value of object a + */ + function extend(a, b, thisArg) { + forEach(b, function assignValue(val, key) { + if (thisArg && typeof val === 'function') { + a[key] = bind(val, thisArg); + } else { + a[key] = val; + } + }); + return a; + } + + /** + * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + * + * @param {string} content with BOM + * @return {string} content value without BOM + */ + function stripBOM(content) { + if (content.charCodeAt(0) === 0xFEFF) { + content = content.slice(1); + } + return content; + } + + module.exports = { + isArray: isArray, + isArrayBuffer: isArrayBuffer, + isBuffer: isBuffer, + isFormData: isFormData, + isArrayBufferView: isArrayBufferView, + isString: isString, + isNumber: isNumber, + isObject: isObject, + isPlainObject: isPlainObject, + isUndefined: isUndefined, + isDate: isDate, + isFile: isFile, + isBlob: isBlob, + isFunction: isFunction, + isStream: isStream, + isURLSearchParams: isURLSearchParams, + isStandardBrowserEnv: isStandardBrowserEnv, + forEach: forEach, + merge: merge, + extend: extend, + trim: trim, + stripBOM: stripBOM + }; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + + 'use strict'; + + module.exports = function bind(fn, thisArg) { + return function wrap() { + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + return fn.apply(thisArg, args); + }; + }; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + var buildURL = __webpack_require__(5); + var InterceptorManager = __webpack_require__(6); + var dispatchRequest = __webpack_require__(7); + var mergeConfig = __webpack_require__(22); + + /** + * Create a new instance of Axios + * + * @param {Object} instanceConfig The default config for the instance + */ + function Axios(instanceConfig) { + this.defaults = instanceConfig; + this.interceptors = { + request: new InterceptorManager(), + response: new InterceptorManager() + }; + } + + /** + * Dispatch a request + * + * @param {Object} config The config specific for this request (merged with this.defaults) + */ + Axios.prototype.request = function request(config) { + /*eslint no-param-reassign:0*/ + // Allow for axios('example/url'[, config]) a la fetch API + if (typeof config === 'string') { + config = arguments[1] || {}; + config.url = arguments[0]; + } else { + config = config || {}; + } + + config = mergeConfig(this.defaults, config); + + // Set config.method + if (config.method) { + config.method = config.method.toLowerCase(); + } else if (this.defaults.method) { + config.method = this.defaults.method.toLowerCase(); + } else { + config.method = 'get'; + } + + // Hook up interceptors middleware + var chain = [dispatchRequest, undefined]; + var promise = Promise.resolve(config); + + this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { + chain.unshift(interceptor.fulfilled, interceptor.rejected); + }); + + this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { + chain.push(interceptor.fulfilled, interceptor.rejected); + }); + + while (chain.length) { + promise = promise.then(chain.shift(), chain.shift()); + } + + return promise; + }; + + Axios.prototype.getUri = function getUri(config) { + config = mergeConfig(this.defaults, config); + return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, ''); + }; + + // Provide aliases for supported request methods + utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { + /*eslint func-names:0*/ + Axios.prototype[method] = function(url, config) { + return this.request(mergeConfig(config || {}, { + method: method, + url: url, + data: (config || {}).data + })); + }; + }); + + utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { + /*eslint func-names:0*/ + Axios.prototype[method] = function(url, data, config) { + return this.request(mergeConfig(config || {}, { + method: method, + url: url, + data: data + })); + }; + }); + + module.exports = Axios; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + + function encode(val) { + return encodeURIComponent(val). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%20/g, '+'). + replace(/%5B/gi, '['). + replace(/%5D/gi, ']'); + } + + /** + * Build a URL by appending params to the end + * + * @param {string} url The base of the url (e.g., http://www.google.com) + * @param {object} [params] The params to be appended + * @returns {string} The formatted url + */ + module.exports = function buildURL(url, params, paramsSerializer) { + /*eslint no-param-reassign:0*/ + if (!params) { + return url; + } + + var serializedParams; + if (paramsSerializer) { + serializedParams = paramsSerializer(params); + } else if (utils.isURLSearchParams(params)) { + serializedParams = params.toString(); + } else { + var parts = []; + + utils.forEach(params, function serialize(val, key) { + if (val === null || typeof val === 'undefined') { + return; + } + + if (utils.isArray(val)) { + key = key + '[]'; + } else { + val = [val]; + } + + utils.forEach(val, function parseValue(v) { + if (utils.isDate(v)) { + v = v.toISOString(); + } else if (utils.isObject(v)) { + v = JSON.stringify(v); + } + parts.push(encode(key) + '=' + encode(v)); + }); + }); + + serializedParams = parts.join('&'); + } + + if (serializedParams) { + var hashmarkIndex = url.indexOf('#'); + if (hashmarkIndex !== -1) { + url = url.slice(0, hashmarkIndex); + } + + url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; + } + + return url; + }; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + + function InterceptorManager() { + this.handlers = []; + } + + /** + * Add a new interceptor to the stack + * + * @param {Function} fulfilled The function to handle `then` for a `Promise` + * @param {Function} rejected The function to handle `reject` for a `Promise` + * + * @return {Number} An ID used to remove interceptor later + */ + InterceptorManager.prototype.use = function use(fulfilled, rejected) { + this.handlers.push({ + fulfilled: fulfilled, + rejected: rejected + }); + return this.handlers.length - 1; + }; + + /** + * Remove an interceptor from the stack + * + * @param {Number} id The ID that was returned by `use` + */ + InterceptorManager.prototype.eject = function eject(id) { + if (this.handlers[id]) { + this.handlers[id] = null; + } + }; + + /** + * Iterate over all the registered interceptors + * + * This method is particularly useful for skipping over any + * interceptors that may have become `null` calling `eject`. + * + * @param {Function} fn The function to call for each interceptor + */ + InterceptorManager.prototype.forEach = function forEach(fn) { + utils.forEach(this.handlers, function forEachHandler(h) { + if (h !== null) { + fn(h); + } + }); + }; + + module.exports = InterceptorManager; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + var transformData = __webpack_require__(8); + var isCancel = __webpack_require__(9); + var defaults = __webpack_require__(10); + + /** + * Throws a `Cancel` if cancellation has been requested. + */ + function throwIfCancellationRequested(config) { + if (config.cancelToken) { + config.cancelToken.throwIfRequested(); + } + } + + /** + * Dispatch a request to the server using the configured adapter. + * + * @param {object} config The config that is to be used for the request + * @returns {Promise} The Promise to be fulfilled + */ + module.exports = function dispatchRequest(config) { + throwIfCancellationRequested(config); + + // Ensure headers exist + config.headers = config.headers || {}; + + // Transform request data + config.data = transformData( + config.data, + config.headers, + config.transformRequest + ); + + // Flatten headers + config.headers = utils.merge( + config.headers.common || {}, + config.headers[config.method] || {}, + config.headers + ); + + utils.forEach( + ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], + function cleanHeaderConfig(method) { + delete config.headers[method]; + } + ); + + var adapter = config.adapter || defaults.adapter; + + return adapter(config).then(function onAdapterResolution(response) { + throwIfCancellationRequested(config); + + // Transform response data + response.data = transformData( + response.data, + response.headers, + config.transformResponse + ); + + return response; + }, function onAdapterRejection(reason) { + if (!isCancel(reason)) { + throwIfCancellationRequested(config); + + // Transform response data + if (reason && reason.response) { + reason.response.data = transformData( + reason.response.data, + reason.response.headers, + config.transformResponse + ); + } + } + + return Promise.reject(reason); + }); + }; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + + /** + * Transform the data for a request or a response + * + * @param {Object|String} data The data to be transformed + * @param {Array} headers The headers for the request or response + * @param {Array|Function} fns A single function or Array of functions + * @returns {*} The resulting transformed data + */ + module.exports = function transformData(data, headers, fns) { + /*eslint no-param-reassign:0*/ + utils.forEach(fns, function transform(fn) { + data = fn(data, headers); + }); + + return data; + }; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + + 'use strict'; + + module.exports = function isCancel(value) { + return !!(value && value.__CANCEL__); + }; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + var normalizeHeaderName = __webpack_require__(11); + + var DEFAULT_CONTENT_TYPE = { + 'Content-Type': 'application/x-www-form-urlencoded' + }; + + function setContentTypeIfUnset(headers, value) { + if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) { + headers['Content-Type'] = value; + } + } + + function getDefaultAdapter() { + var adapter; + if (typeof XMLHttpRequest !== 'undefined') { + // For browsers use XHR adapter + adapter = __webpack_require__(12); + } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') { + // For node use HTTP adapter + adapter = __webpack_require__(12); + } + return adapter; + } + + var defaults = { + adapter: getDefaultAdapter(), + + transformRequest: [function transformRequest(data, headers) { + normalizeHeaderName(headers, 'Accept'); + normalizeHeaderName(headers, 'Content-Type'); + if (utils.isFormData(data) || + utils.isArrayBuffer(data) || + utils.isBuffer(data) || + utils.isStream(data) || + utils.isFile(data) || + utils.isBlob(data) + ) { + return data; + } + if (utils.isArrayBufferView(data)) { + return data.buffer; + } + if (utils.isURLSearchParams(data)) { + setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); + return data.toString(); + } + if (utils.isObject(data)) { + setContentTypeIfUnset(headers, 'application/json;charset=utf-8'); + return JSON.stringify(data); + } + return data; + }], + + transformResponse: [function transformResponse(data) { + /*eslint no-param-reassign:0*/ + if (typeof data === 'string') { + try { + data = JSON.parse(data); + } catch (e) { /* Ignore */ } + } + return data; + }], + + /** + * A timeout in milliseconds to abort a request. If set to 0 (default) a + * timeout is not created. + */ + timeout: 0, + + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', + + maxContentLength: -1, + maxBodyLength: -1, + + validateStatus: function validateStatus(status) { + return status >= 200 && status < 300; + } + }; + + defaults.headers = { + common: { + 'Accept': 'application/json, text/plain, */*' + } + }; + + utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) { + defaults.headers[method] = {}; + }); + + utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { + defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE); + }); + + module.exports = defaults; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + + module.exports = function normalizeHeaderName(headers, normalizedName) { + utils.forEach(headers, function processHeader(value, name) { + if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) { + headers[normalizedName] = value; + delete headers[name]; + } + }); + }; + + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + var settle = __webpack_require__(13); + var cookies = __webpack_require__(16); + var buildURL = __webpack_require__(5); + var buildFullPath = __webpack_require__(17); + var parseHeaders = __webpack_require__(20); + var isURLSameOrigin = __webpack_require__(21); + var createError = __webpack_require__(14); + + module.exports = function xhrAdapter(config) { + return new Promise(function dispatchXhrRequest(resolve, reject) { + var requestData = config.data; + var requestHeaders = config.headers; + + if (utils.isFormData(requestData)) { + delete requestHeaders['Content-Type']; // Let the browser set it + } + + var request = new XMLHttpRequest(); + + // HTTP basic authentication + if (config.auth) { + var username = config.auth.username || ''; + var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : ''; + requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password); + } + + var fullPath = buildFullPath(config.baseURL, config.url); + request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true); + + // Set the request timeout in MS + request.timeout = config.timeout; + + // Listen for ready state + request.onreadystatechange = function handleLoad() { + if (!request || request.readyState !== 4) { + return; + } + + // The request errored out and we didn't get a response, this will be + // handled by onerror instead + // With one exception: request that using file: protocol, most browsers + // will return status as 0 even though it's a successful request + if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { + return; + } + + // Prepare the response + var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null; + var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response; + var response = { + data: responseData, + status: request.status, + statusText: request.statusText, + headers: responseHeaders, + config: config, + request: request + }; + + settle(resolve, reject, response); + + // Clean up request + request = null; + }; + + // Handle browser request cancellation (as opposed to a manual cancellation) + request.onabort = function handleAbort() { + if (!request) { + return; + } + + reject(createError('Request aborted', config, 'ECONNABORTED', request)); + + // Clean up request + request = null; + }; + + // Handle low level network errors + request.onerror = function handleError() { + // Real errors are hidden from us by the browser + // onerror should only fire if it's a network error + reject(createError('Network Error', config, null, request)); + + // Clean up request + request = null; + }; + + // Handle timeout + request.ontimeout = function handleTimeout() { + var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded'; + if (config.timeoutErrorMessage) { + timeoutErrorMessage = config.timeoutErrorMessage; + } + reject(createError(timeoutErrorMessage, config, 'ECONNABORTED', + request)); + + // Clean up request + request = null; + }; + + // Add xsrf header + // This is only done if running in a standard browser environment. + // Specifically not if we're in a web worker, or react-native. + if (utils.isStandardBrowserEnv()) { + // Add xsrf header + var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ? + cookies.read(config.xsrfCookieName) : + undefined; + + if (xsrfValue) { + requestHeaders[config.xsrfHeaderName] = xsrfValue; + } + } + + // Add headers to the request + if ('setRequestHeader' in request) { + utils.forEach(requestHeaders, function setRequestHeader(val, key) { + if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') { + // Remove Content-Type if data is undefined + delete requestHeaders[key]; + } else { + // Otherwise add header to the request + request.setRequestHeader(key, val); + } + }); + } + + // Add withCredentials to request if needed + if (!utils.isUndefined(config.withCredentials)) { + request.withCredentials = !!config.withCredentials; + } + + // Add responseType to request if needed + if (config.responseType) { + try { + request.responseType = config.responseType; + } catch (e) { + // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2. + // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function. + if (config.responseType !== 'json') { + throw e; + } + } + } + + // Handle progress if needed + if (typeof config.onDownloadProgress === 'function') { + request.addEventListener('progress', config.onDownloadProgress); + } + + // Not all browsers support upload events + if (typeof config.onUploadProgress === 'function' && request.upload) { + request.upload.addEventListener('progress', config.onUploadProgress); + } + + if (config.cancelToken) { + // Handle cancellation + config.cancelToken.promise.then(function onCanceled(cancel) { + if (!request) { + return; + } + + request.abort(); + reject(cancel); + // Clean up request + request = null; + }); + } + + if (!requestData) { + requestData = null; + } + + // Send the request + request.send(requestData); + }); + }; + + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var createError = __webpack_require__(14); + + /** + * Resolve or reject a Promise based on response status. + * + * @param {Function} resolve A function that resolves the promise. + * @param {Function} reject A function that rejects the promise. + * @param {object} response The response. + */ + module.exports = function settle(resolve, reject, response) { + var validateStatus = response.config.validateStatus; + if (!response.status || !validateStatus || validateStatus(response.status)) { + resolve(response); + } else { + reject(createError( + 'Request failed with status code ' + response.status, + response.config, + null, + response.request, + response + )); + } + }; + + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var enhanceError = __webpack_require__(15); + + /** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {Object} config The config. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * @returns {Error} The created error. + */ + module.exports = function createError(message, config, code, request, response) { + var error = new Error(message); + return enhanceError(error, config, code, request, response); + }; + + +/***/ }), +/* 15 */ +/***/ (function(module, exports) { + + 'use strict'; + + /** + * Update an Error with the specified config, error code, and response. + * + * @param {Error} error The error to update. + * @param {Object} config The config. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * @returns {Error} The error. + */ + module.exports = function enhanceError(error, config, code, request, response) { + error.config = config; + if (code) { + error.code = code; + } + + error.request = request; + error.response = response; + error.isAxiosError = true; + + error.toJSON = function toJSON() { + return { + // Standard + message: this.message, + name: this.name, + // Microsoft + description: this.description, + number: this.number, + // Mozilla + fileName: this.fileName, + lineNumber: this.lineNumber, + columnNumber: this.columnNumber, + stack: this.stack, + // Axios + config: this.config, + code: this.code + }; + }; + return error; + }; + + +/***/ }), +/* 16 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + + module.exports = ( + utils.isStandardBrowserEnv() ? + + // Standard browser envs support document.cookie + (function standardBrowserEnv() { + return { + write: function write(name, value, expires, path, domain, secure) { + var cookie = []; + cookie.push(name + '=' + encodeURIComponent(value)); + + if (utils.isNumber(expires)) { + cookie.push('expires=' + new Date(expires).toGMTString()); + } + + if (utils.isString(path)) { + cookie.push('path=' + path); + } + + if (utils.isString(domain)) { + cookie.push('domain=' + domain); + } + + if (secure === true) { + cookie.push('secure'); + } + + document.cookie = cookie.join('; '); + }, + + read: function read(name) { + var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); + return (match ? decodeURIComponent(match[3]) : null); + }, + + remove: function remove(name) { + this.write(name, '', Date.now() - 86400000); + } + }; + })() : + + // Non standard browser env (web workers, react-native) lack needed support. + (function nonStandardBrowserEnv() { + return { + write: function write() {}, + read: function read() { return null; }, + remove: function remove() {} + }; + })() + ); + + +/***/ }), +/* 17 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var isAbsoluteURL = __webpack_require__(18); + var combineURLs = __webpack_require__(19); + + /** + * Creates a new URL by combining the baseURL with the requestedURL, + * only when the requestedURL is not already an absolute URL. + * If the requestURL is absolute, this function returns the requestedURL untouched. + * + * @param {string} baseURL The base URL + * @param {string} requestedURL Absolute or relative URL to combine + * @returns {string} The combined full path + */ + module.exports = function buildFullPath(baseURL, requestedURL) { + if (baseURL && !isAbsoluteURL(requestedURL)) { + return combineURLs(baseURL, requestedURL); + } + return requestedURL; + }; + + +/***/ }), +/* 18 */ +/***/ (function(module, exports) { + + 'use strict'; + + /** + * Determines whether the specified URL is absolute + * + * @param {string} url The URL to test + * @returns {boolean} True if the specified URL is absolute, otherwise false + */ + module.exports = function isAbsoluteURL(url) { + // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). + // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed + // by any combination of letters, digits, plus, period, or hyphen. + return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); + }; + + +/***/ }), +/* 19 */ +/***/ (function(module, exports) { + + 'use strict'; + + /** + * Creates a new URL by combining the specified URLs + * + * @param {string} baseURL The base URL + * @param {string} relativeURL The relative URL + * @returns {string} The combined URL + */ + module.exports = function combineURLs(baseURL, relativeURL) { + return relativeURL + ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') + : baseURL; + }; + + +/***/ }), +/* 20 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + + // Headers whose duplicates are ignored by node + // c.f. https://nodejs.org/api/http.html#http_message_headers + var ignoreDuplicateOf = [ + 'age', 'authorization', 'content-length', 'content-type', 'etag', + 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', + 'last-modified', 'location', 'max-forwards', 'proxy-authorization', + 'referer', 'retry-after', 'user-agent' + ]; + + /** + * Parse headers into an object + * + * ``` + * Date: Wed, 27 Aug 2014 08:58:49 GMT + * Content-Type: application/json + * Connection: keep-alive + * Transfer-Encoding: chunked + * ``` + * + * @param {String} headers Headers needing to be parsed + * @returns {Object} Headers parsed into an object + */ + module.exports = function parseHeaders(headers) { + var parsed = {}; + var key; + var val; + var i; + + if (!headers) { return parsed; } + + utils.forEach(headers.split('\n'), function parser(line) { + i = line.indexOf(':'); + key = utils.trim(line.substr(0, i)).toLowerCase(); + val = utils.trim(line.substr(i + 1)); + + if (key) { + if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) { + return; + } + if (key === 'set-cookie') { + parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]); + } else { + parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; + } + } + }); + + return parsed; + }; + + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + + module.exports = ( + utils.isStandardBrowserEnv() ? + + // Standard browser envs have full support of the APIs needed to test + // whether the request URL is of the same origin as current location. + (function standardBrowserEnv() { + var msie = /(msie|trident)/i.test(navigator.userAgent); + var urlParsingNode = document.createElement('a'); + var originURL; + + /** + * Parse a URL to discover it's components + * + * @param {String} url The URL to be parsed + * @returns {Object} + */ + function resolveURL(url) { + var href = url; + + if (msie) { + // IE needs attribute set twice to normalize properties + urlParsingNode.setAttribute('href', href); + href = urlParsingNode.href; + } + + urlParsingNode.setAttribute('href', href); + + // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils + return { + href: urlParsingNode.href, + protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', + host: urlParsingNode.host, + search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', + hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', + hostname: urlParsingNode.hostname, + port: urlParsingNode.port, + pathname: (urlParsingNode.pathname.charAt(0) === '/') ? + urlParsingNode.pathname : + '/' + urlParsingNode.pathname + }; + } + + originURL = resolveURL(window.location.href); + + /** + * Determine if a URL shares the same origin as the current location + * + * @param {String} requestURL The URL to test + * @returns {boolean} True if URL shares the same origin, otherwise false + */ + return function isURLSameOrigin(requestURL) { + var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL; + return (parsed.protocol === originURL.protocol && + parsed.host === originURL.host); + }; + })() : + + // Non standard browser envs (web workers, react-native) lack needed support. + (function nonStandardBrowserEnv() { + return function isURLSameOrigin() { + return true; + }; + })() + ); + + +/***/ }), +/* 22 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var utils = __webpack_require__(2); + + /** + * Config-specific merge-function which creates a new config-object + * by merging two configuration objects together. + * + * @param {Object} config1 + * @param {Object} config2 + * @returns {Object} New object resulting from merging config2 to config1 + */ + module.exports = function mergeConfig(config1, config2) { + // eslint-disable-next-line no-param-reassign + config2 = config2 || {}; + var config = {}; + + var valueFromConfig2Keys = ['url', 'method', 'data']; + var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy', 'params']; + var defaultToConfig2Keys = [ + 'baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer', + 'timeout', 'timeoutMessage', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName', + 'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'decompress', + 'maxContentLength', 'maxBodyLength', 'maxRedirects', 'transport', 'httpAgent', + 'httpsAgent', 'cancelToken', 'socketPath', 'responseEncoding' + ]; + var directMergeKeys = ['validateStatus']; + + function getMergedValue(target, source) { + if (utils.isPlainObject(target) && utils.isPlainObject(source)) { + return utils.merge(target, source); + } else if (utils.isPlainObject(source)) { + return utils.merge({}, source); + } else if (utils.isArray(source)) { + return source.slice(); + } + return source; + } + + function mergeDeepProperties(prop) { + if (!utils.isUndefined(config2[prop])) { + config[prop] = getMergedValue(config1[prop], config2[prop]); + } else if (!utils.isUndefined(config1[prop])) { + config[prop] = getMergedValue(undefined, config1[prop]); + } + } + + utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) { + if (!utils.isUndefined(config2[prop])) { + config[prop] = getMergedValue(undefined, config2[prop]); + } + }); + + utils.forEach(mergeDeepPropertiesKeys, mergeDeepProperties); + + utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) { + if (!utils.isUndefined(config2[prop])) { + config[prop] = getMergedValue(undefined, config2[prop]); + } else if (!utils.isUndefined(config1[prop])) { + config[prop] = getMergedValue(undefined, config1[prop]); + } + }); + + utils.forEach(directMergeKeys, function merge(prop) { + if (prop in config2) { + config[prop] = getMergedValue(config1[prop], config2[prop]); + } else if (prop in config1) { + config[prop] = getMergedValue(undefined, config1[prop]); + } + }); + + var axiosKeys = valueFromConfig2Keys + .concat(mergeDeepPropertiesKeys) + .concat(defaultToConfig2Keys) + .concat(directMergeKeys); + + var otherKeys = Object + .keys(config1) + .concat(Object.keys(config2)) + .filter(function filterAxiosKeys(key) { + return axiosKeys.indexOf(key) === -1; + }); + + utils.forEach(otherKeys, mergeDeepProperties); + + return config; + }; + + +/***/ }), +/* 23 */ +/***/ (function(module, exports) { + + 'use strict'; + + /** + * A `Cancel` is an object that is thrown when an operation is canceled. + * + * @class + * @param {string=} message The message. + */ + function Cancel(message) { + this.message = message; + } + + Cancel.prototype.toString = function toString() { + return 'Cancel' + (this.message ? ': ' + this.message : ''); + }; + + Cancel.prototype.__CANCEL__ = true; + + module.exports = Cancel; + + +/***/ }), +/* 24 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + var Cancel = __webpack_require__(23); + + /** + * A `CancelToken` is an object that can be used to request cancellation of an operation. + * + * @class + * @param {Function} executor The executor function. + */ + function CancelToken(executor) { + if (typeof executor !== 'function') { + throw new TypeError('executor must be a function.'); + } + + var resolvePromise; + this.promise = new Promise(function promiseExecutor(resolve) { + resolvePromise = resolve; + }); + + var token = this; + executor(function cancel(message) { + if (token.reason) { + // Cancellation has already been requested + return; + } + + token.reason = new Cancel(message); + resolvePromise(token.reason); + }); + } + + /** + * Throws a `Cancel` if cancellation has been requested. + */ + CancelToken.prototype.throwIfRequested = function throwIfRequested() { + if (this.reason) { + throw this.reason; + } + }; + + /** + * Returns an object that contains a new `CancelToken` and a function that, when called, + * cancels the `CancelToken`. + */ + CancelToken.source = function source() { + var cancel; + var token = new CancelToken(function executor(c) { + cancel = c; + }); + return { + token: token, + cancel: cancel + }; + }; + + module.exports = CancelToken; + + +/***/ }), +/* 25 */ +/***/ (function(module, exports) { + + 'use strict'; + + /** + * Syntactic sugar for invoking a function and expanding an array for arguments. + * + * Common use case would be to use `Function.prototype.apply`. + * + * ```js + * function f(x, y, z) {} + * var args = [1, 2, 3]; + * f.apply(null, args); + * ``` + * + * With `spread` this example can be re-written. + * + * ```js + * spread(function(x, y, z) {})([1, 2, 3]); + * ``` + * + * @param {Function} callback + * @returns {Function} + */ + module.exports = function spread(callback) { + return function wrap(arr) { + return callback.apply(null, arr); + }; + }; + + +/***/ }), +/* 26 */ +/***/ (function(module, exports) { + + 'use strict'; + + /** + * Determines whether the payload is an error thrown by Axios + * + * @param {*} payload The value to test + * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false + */ + module.exports = function isAxiosError(payload) { + return (typeof payload === 'object') && (payload.isAxiosError === true); + }; + + +/***/ }) +/******/ ]) +}); +; +//# sourceMappingURL=axios.map \ No newline at end of file diff --git a/src/main/webapp/assets/js/vendors/d3.js b/src/main/webapp/assets/js/vendors/d3.js new file mode 100644 index 0000000..338e89e --- /dev/null +++ b/src/main/webapp/assets/js/vendors/d3.js @@ -0,0 +1,20013 @@ +// https://d3js.org v5.16.0 Copyright 2020 Mike Bostock +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = global || self, factory(global.d3 = global.d3 || {})); +}(this, function (exports) { + 'use strict'; + + var version = "5.16.0"; + + function ascending(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; + } + + function bisector(compare) { + if (compare.length === 1) + compare = ascendingComparator(compare); + return { + left: function (a, x, lo, hi) { + if (lo == null) + lo = 0; + if (hi == null) + hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) < 0) + lo = mid + 1; + else + hi = mid; + } + return lo; + }, + right: function (a, x, lo, hi) { + if (lo == null) + lo = 0; + if (hi == null) + hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) > 0) + hi = mid; + else + lo = mid + 1; + } + return lo; + } + }; + } + + function ascendingComparator(f) { + return function (d, x) { + return ascending(f(d), x); + }; + } + + var ascendingBisect = bisector(ascending); + var bisectRight = ascendingBisect.right; + var bisectLeft = ascendingBisect.left; + + function pairs(array, f) { + if (f == null) + f = pair; + var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) + pairs[i] = f(p, p = array[++i]); + return pairs; + } + + function pair(a, b) { + return [a, b]; + } + + function cross(values0, values1, reduce) { + var n0 = values0.length, + n1 = values1.length, + values = new Array(n0 * n1), + i0, + i1, + i, + value0; + + if (reduce == null) + reduce = pair; + + for (i0 = i = 0; i0 < n0; ++i0) { + for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) { + values[i] = reduce(value0, values1[i1]); + } + } + + return values; + } + + function descending(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; + } + + function number(x) { + return x === null ? NaN : +x; + } + + function variance(values, valueof) { + var n = values.length, + m = 0, + i = -1, + mean = 0, + value, + delta, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) { + delta = value - mean; + mean += delta / ++m; + sum += delta * (value - mean); + } + } + } else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) { + delta = value - mean; + mean += delta / ++m; + sum += delta * (value - mean); + } + } + } + + if (m > 1) + return sum / (m - 1); + } + + function deviation(array, f) { + var v = variance(array, f); + return v ? Math.sqrt(v) : v; + } + + function extent(values, valueof) { + var n = values.length, + i = -1, + value, + min, + max; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + min = max = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null) { + if (min > value) + min = value; + if (max < value) + max = value; + } + } + } + } + } else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + min = max = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null) { + if (min > value) + min = value; + if (max < value) + max = value; + } + } + } + } + } + + return [min, max]; + } + + var array = Array.prototype; + + var slice = array.slice; + var map = array.map; + + function constant(x) { + return function () { + return x; + }; + } + + function identity(x) { + return x; + } + + function sequence(start, stop, step) { + start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; + + var i = -1, + n = Math.max(0, Math.ceil((stop - start) / step)) | 0, + range = new Array(n); + + while (++i < n) { + range[i] = start + i * step; + } + + return range; + } + + var e10 = Math.sqrt(50), + e5 = Math.sqrt(10), + e2 = Math.sqrt(2); + + function ticks(start, stop, count) { + var reverse, + i = -1, + n, + ticks, + step; + + stop = +stop, start = +start, count = +count; + if (start === stop && count > 0) + return [start]; + if (reverse = stop < start) + n = start, start = stop, stop = n; + if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) + return []; + + if (step > 0) { + start = Math.ceil(start / step); + stop = Math.floor(stop / step); + ticks = new Array(n = Math.ceil(stop - start + 1)); + while (++i < n) + ticks[i] = (start + i) * step; + } else { + start = Math.floor(start * step); + stop = Math.ceil(stop * step); + ticks = new Array(n = Math.ceil(start - stop + 1)); + while (++i < n) + ticks[i] = (start - i) / step; + } + + if (reverse) + ticks.reverse(); + + return ticks; + } + + function tickIncrement(start, stop, count) { + var step = (stop - start) / Math.max(0, count), + power = Math.floor(Math.log(step) / Math.LN10), + error = step / Math.pow(10, power); + return power >= 0 + ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) + : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); + } + + function tickStep(start, stop, count) { + var step0 = Math.abs(stop - start) / Math.max(0, count), + step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), + error = step0 / step1; + if (error >= e10) + step1 *= 10; + else if (error >= e5) + step1 *= 5; + else if (error >= e2) + step1 *= 2; + return stop < start ? -step1 : step1; + } + + function thresholdSturges(values) { + return Math.ceil(Math.log(values.length) / Math.LN2) + 1; + } + + function histogram() { + var value = identity, + domain = extent, + threshold = thresholdSturges; + + function histogram(data) { + var i, + n = data.length, + x, + values = new Array(n); + + for (i = 0; i < n; ++i) { + values[i] = value(data[i], i, data); + } + + var xz = domain(values), + x0 = xz[0], + x1 = xz[1], + tz = threshold(values, x0, x1); + + // Convert number of thresholds into uniform thresholds. + if (!Array.isArray(tz)) { + tz = tickStep(x0, x1, tz); + tz = sequence(Math.ceil(x0 / tz) * tz, x1, tz); // exclusive + } + + // Remove any thresholds outside the domain. + var m = tz.length; + while (tz[0] <= x0) + tz.shift(), --m; + while (tz[m - 1] > x1) + tz.pop(), --m; + + var bins = new Array(m + 1), + bin; + + // Initialize bins. + for (i = 0; i <= m; ++i) { + bin = bins[i] = []; + bin.x0 = i > 0 ? tz[i - 1] : x0; + bin.x1 = i < m ? tz[i] : x1; + } + + // Assign data to bins by value, ignoring any outside the domain. + for (i = 0; i < n; ++i) { + x = values[i]; + if (x0 <= x && x <= x1) { + bins[bisectRight(tz, x, 0, m)].push(data[i]); + } + } + + return bins; + } + + histogram.value = function (_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value; + }; + + histogram.domain = function (_) { + return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; + }; + + histogram.thresholds = function (_) { + return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; + }; + + return histogram; + } + + function threshold(values, p, valueof) { + if (valueof == null) + valueof = number; + if (!(n = values.length)) + return; + if ((p = +p) <= 0 || n < 2) + return +valueof(values[0], 0, values); + if (p >= 1) + return +valueof(values[n - 1], n - 1, values); + var n, + i = (n - 1) * p, + i0 = Math.floor(i), + value0 = +valueof(values[i0], i0, values), + value1 = +valueof(values[i0 + 1], i0 + 1, values); + return value0 + (value1 - value0) * (i - i0); + } + + function freedmanDiaconis(values, min, max) { + values = map.call(values, number).sort(ascending); + return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3))); + } + + function scott(values, min, max) { + return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); + } + + function max(values, valueof) { + var n = values.length, + i = -1, + value, + max; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + max = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null && value > max) { + max = value; + } + } + } + } + } else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + max = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null && value > max) { + max = value; + } + } + } + } + } + + return max; + } + + function mean(values, valueof) { + var n = values.length, + m = n, + i = -1, + value, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) + sum += value; + else + --m; + } + } else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) + sum += value; + else + --m; + } + } + + if (m) + return sum / m; + } + + function median(values, valueof) { + var n = values.length, + i = -1, + value, + numbers = []; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) { + numbers.push(value); + } + } + } else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) { + numbers.push(value); + } + } + } + + return threshold(numbers.sort(ascending), 0.5); + } + + function merge(arrays) { + var n = arrays.length, + m, + i = -1, + j = 0, + merged, + array; + + while (++i < n) + j += arrays[i].length; + merged = new Array(j); + + while (--n >= 0) { + array = arrays[n]; + m = array.length; + while (--m >= 0) { + merged[--j] = array[m]; + } + } + + return merged; + } + + function min(values, valueof) { + var n = values.length, + i = -1, + value, + min; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + min = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null && min > value) { + min = value; + } + } + } + } + } else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + min = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null && min > value) { + min = value; + } + } + } + } + } + + return min; + } + + function permute(array, indexes) { + var i = indexes.length, permutes = new Array(i); + while (i--) + permutes[i] = array[indexes[i]]; + return permutes; + } + + function scan(values, compare) { + if (!(n = values.length)) + return; + var n, + i = 0, + j = 0, + xi, + xj = values[j]; + + if (compare == null) + compare = ascending; + + while (++i < n) { + if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) { + xj = xi, j = i; + } + } + + if (compare(xj, xj) === 0) + return j; + } + + function shuffle(array, i0, i1) { + var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0), + t, + i; + + while (m) { + i = Math.random() * m-- | 0; + t = array[m + i0]; + array[m + i0] = array[i + i0]; + array[i + i0] = t; + } + + return array; + } + + function sum(values, valueof) { + var n = values.length, + i = -1, + value, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (value = +values[i]) + sum += value; // Note: zero and null are equivalent. + } + } else { + while (++i < n) { + if (value = +valueof(values[i], i, values)) + sum += value; + } + } + + return sum; + } + + function transpose(matrix) { + if (!(n = matrix.length)) + return []; + for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m; ) { + for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n; ) { + row[j] = matrix[j][i]; + } + } + return transpose; + } + + function length(d) { + return d.length; + } + + function zip() { + return transpose(arguments); + } + + var slice$1 = Array.prototype.slice; + + function identity$1(x) { + return x; + } + + var top = 1, + right = 2, + bottom = 3, + left = 4, + epsilon = 1e-6; + + function translateX(x) { + return "translate(" + (x + 0.5) + ",0)"; + } + + function translateY(y) { + return "translate(0," + (y + 0.5) + ")"; + } + + function number$1(scale) { + return function (d) { + return +scale(d); + }; + } + + function center(scale) { + var offset = Math.max(0, scale.bandwidth() - 1) / 2; // Adjust for 0.5px offset. + if (scale.round()) + offset = Math.round(offset); + return function (d) { + return +scale(d) + offset; + }; + } + + function entering() { + return !this.__axis; + } + + function axis(orient, scale) { + var tickArguments = [], + tickValues = null, + tickFormat = null, + tickSizeInner = 6, + tickSizeOuter = 6, + tickPadding = 3, + k = orient === top || orient === left ? -1 : 1, + x = orient === left || orient === right ? "x" : "y", + transform = orient === top || orient === bottom ? translateX : translateY; + + function axis(context) { + var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues, + format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$1) : tickFormat, + spacing = Math.max(tickSizeInner, 0) + tickPadding, + range = scale.range(), + range0 = +range[0] + 0.5, + range1 = +range[range.length - 1] + 0.5, + position = (scale.bandwidth ? center : number$1)(scale.copy()), + selection = context.selection ? context.selection() : context, + path = selection.selectAll(".domain").data([null]), + tick = selection.selectAll(".tick").data(values, scale).order(), + tickExit = tick.exit(), + tickEnter = tick.enter().append("g").attr("class", "tick"), + line = tick.select("line"), + text = tick.select("text"); + + path = path.merge(path.enter().insert("path", ".tick") + .attr("class", "domain") + .attr("stroke", "currentColor")); + + tick = tick.merge(tickEnter); + + line = line.merge(tickEnter.append("line") + .attr("stroke", "currentColor") + .attr(x + "2", k * tickSizeInner)); + + text = text.merge(tickEnter.append("text") + .attr("fill", "currentColor") + .attr(x, k * spacing) + .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em")); + + if (context !== selection) { + path = path.transition(context); + tick = tick.transition(context); + line = line.transition(context); + text = text.transition(context); + + tickExit = tickExit.transition(context) + .attr("opacity", epsilon) + .attr("transform", function (d) { + return isFinite(d = position(d)) ? transform(d) : this.getAttribute("transform"); + }); + + tickEnter + .attr("opacity", epsilon) + .attr("transform", function (d) { + var p = this.parentNode.__axis; + return transform(p && isFinite(p = p(d)) ? p : position(d)); + }); + } + + tickExit.remove(); + + path + .attr("d", orient === left || orient == right + ? (tickSizeOuter ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter : "M0.5," + range0 + "V" + range1) + : (tickSizeOuter ? "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter : "M" + range0 + ",0.5H" + range1)); + + tick + .attr("opacity", 1) + .attr("transform", function (d) { + return transform(position(d)); + }); + + line + .attr(x + "2", k * tickSizeInner); + + text + .attr(x, k * spacing) + .text(format); + + selection.filter(entering) + .attr("fill", "none") + .attr("font-size", 10) + .attr("font-family", "sans-serif") + .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle"); + + selection + .each(function () { + this.__axis = position; + }); + } + + axis.scale = function (_) { + return arguments.length ? (scale = _, axis) : scale; + }; + + axis.ticks = function () { + return tickArguments = slice$1.call(arguments), axis; + }; + + axis.tickArguments = function (_) { + return arguments.length ? (tickArguments = _ == null ? [] : slice$1.call(_), axis) : tickArguments.slice(); + }; + + axis.tickValues = function (_) { + return arguments.length ? (tickValues = _ == null ? null : slice$1.call(_), axis) : tickValues && tickValues.slice(); + }; + + axis.tickFormat = function (_) { + return arguments.length ? (tickFormat = _, axis) : tickFormat; + }; + + axis.tickSize = function (_) { + return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner; + }; + + axis.tickSizeInner = function (_) { + return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner; + }; + + axis.tickSizeOuter = function (_) { + return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter; + }; + + axis.tickPadding = function (_) { + return arguments.length ? (tickPadding = +_, axis) : tickPadding; + }; + + return axis; + } + + function axisTop(scale) { + return axis(top, scale); + } + + function axisRight(scale) { + return axis(right, scale); + } + + function axisBottom(scale) { + return axis(bottom, scale); + } + + function axisLeft(scale) { + return axis(left, scale); + } + + var noop = {value: function () {}}; + + function dispatch() { + for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { + if (!(t = arguments[i] + "") || (t in _) || /[\s.]/.test(t)) + throw new Error("illegal type: " + t); + _[t] = []; + } + return new Dispatch(_); + } + + function Dispatch(_) { + this._ = _; + } + + function parseTypenames(typenames, types) { + return typenames.trim().split(/^|\s+/).map(function (t) { + var name = "", i = t.indexOf("."); + if (i >= 0) + name = t.slice(i + 1), t = t.slice(0, i); + if (t && !types.hasOwnProperty(t)) + throw new Error("unknown type: " + t); + return {type: t, name: name}; + }); + } + + Dispatch.prototype = dispatch.prototype = { + constructor: Dispatch, + on: function (typename, callback) { + var _ = this._, + T = parseTypenames(typename + "", _), + t, + i = -1, + n = T.length; + + // If no callback was specified, return the callback of the given type and name. + if (arguments.length < 2) { + while (++i < n) + if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) + return t; + return; + } + + // If a type was specified, set the callback for the given type and name. + // Otherwise, if a null callback was specified, remove callbacks of the given name. + if (callback != null && typeof callback !== "function") + throw new Error("invalid callback: " + callback); + while (++i < n) { + if (t = (typename = T[i]).type) + _[t] = set(_[t], typename.name, callback); + else if (callback == null) + for (t in _) + _[t] = set(_[t], typename.name, null); + } + + return this; + }, + copy: function () { + var copy = {}, _ = this._; + for (var t in _) + copy[t] = _[t].slice(); + return new Dispatch(copy); + }, + call: function (type, that) { + if ((n = arguments.length - 2) > 0) + for (var args = new Array(n), i = 0, n, t; i < n; ++i) + args[i] = arguments[i + 2]; + if (!this._.hasOwnProperty(type)) + throw new Error("unknown type: " + type); + for (t = this._[type], i = 0, n = t.length; i < n; ++i) + t[i].value.apply(that, args); + }, + apply: function (type, that, args) { + if (!this._.hasOwnProperty(type)) + throw new Error("unknown type: " + type); + for (var t = this._[type], i = 0, n = t.length; i < n; ++i) + t[i].value.apply(that, args); + } + }; + + function get(type, name) { + for (var i = 0, n = type.length, c; i < n; ++i) { + if ((c = type[i]).name === name) { + return c.value; + } + } + } + + function set(type, name, callback) { + for (var i = 0, n = type.length; i < n; ++i) { + if (type[i].name === name) { + type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); + break; + } + } + if (callback != null) + type.push({name: name, value: callback}); + return type; + } + + var xhtml = "http://www.w3.org/1999/xhtml"; + + var namespaces = { + svg: "http://www.w3.org/2000/svg", + xhtml: xhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + + function namespace(name) { + var prefix = name += "", i = prefix.indexOf(":"); + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") + name = name.slice(i + 1); + return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; + } + + function creatorInherit(name) { + return function () { + var document = this.ownerDocument, + uri = this.namespaceURI; + return uri === xhtml && document.documentElement.namespaceURI === xhtml + ? document.createElement(name) + : document.createElementNS(uri, name); + }; + } + + function creatorFixed(fullname) { + return function () { + return this.ownerDocument.createElementNS(fullname.space, fullname.local); + }; + } + + function creator(name) { + var fullname = namespace(name); + return (fullname.local + ? creatorFixed + : creatorInherit)(fullname); + } + + function none() {} + + function selector(selector) { + return selector == null ? none : function () { + return this.querySelector(selector); + }; + } + + function selection_select(select) { + if (typeof select !== "function") + select = selector(select); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) + subnode.__data__ = node.__data__; + subgroup[i] = subnode; + } + } + } + + return new Selection(subgroups, this._parents); + } + + function empty() { + return []; + } + + function selectorAll(selector) { + return selector == null ? empty : function () { + return this.querySelectorAll(selector); + }; + } + + function selection_selectAll(select) { + if (typeof select !== "function") + select = selectorAll(select); + + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + subgroups.push(select.call(node, node.__data__, i, group)); + parents.push(node); + } + } + } + + return new Selection(subgroups, parents); + } + + function matcher(selector) { + return function () { + return this.matches(selector); + }; + } + + function selection_filter(match) { + if (typeof match !== "function") + match = matcher(match); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + + return new Selection(subgroups, this._parents); + } + + function sparse(update) { + return new Array(update.length); + } + + function selection_enter() { + return new Selection(this._enter || this._groups.map(sparse), this._parents); + } + + function EnterNode(parent, datum) { + this.ownerDocument = parent.ownerDocument; + this.namespaceURI = parent.namespaceURI; + this._next = null; + this._parent = parent; + this.__data__ = datum; + } + + EnterNode.prototype = { + constructor: EnterNode, + appendChild: function (child) { + return this._parent.insertBefore(child, this._next); + }, + insertBefore: function (child, next) { + return this._parent.insertBefore(child, next); + }, + querySelector: function (selector) { + return this._parent.querySelector(selector); + }, + querySelectorAll: function (selector) { + return this._parent.querySelectorAll(selector); + } + }; + + function constant$1(x) { + return function () { + return x; + }; + } + + var keyPrefix = "$"; // Protect against keys like “__proto__”. + + function bindIndex(parent, group, enter, update, exit, data) { + var i = 0, + node, + groupLength = group.length, + dataLength = data.length; + + // Put any non-null nodes that fit into update. + // Put any null nodes into enter. + // Put any remaining data into enter. + for (; i < dataLength; ++i) { + if (node = group[i]) { + node.__data__ = data[i]; + update[i] = node; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Put any non-null nodes that don’t fit into exit. + for (; i < groupLength; ++i) { + if (node = group[i]) { + exit[i] = node; + } + } + } + + function bindKey(parent, group, enter, update, exit, data, key) { + var i, + node, + nodeByKeyValue = {}, + groupLength = group.length, + dataLength = data.length, + keyValues = new Array(groupLength), + keyValue; + + // Compute the key for each node. + // If multiple nodes have the same key, the duplicates are added to exit. + for (i = 0; i < groupLength; ++i) { + if (node = group[i]) { + keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group); + if (keyValue in nodeByKeyValue) { + exit[i] = node; + } else { + nodeByKeyValue[keyValue] = node; + } + } + } + + // Compute the key for each datum. + // If there a node associated with this key, join and add it to update. + // If there is not (or the key is a duplicate), add it to enter. + for (i = 0; i < dataLength; ++i) { + keyValue = keyPrefix + key.call(parent, data[i], i, data); + if (node = nodeByKeyValue[keyValue]) { + update[i] = node; + node.__data__ = data[i]; + nodeByKeyValue[keyValue] = null; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Add any remaining nodes that were not bound to data to exit. + for (i = 0; i < groupLength; ++i) { + if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) { + exit[i] = node; + } + } + } + + function selection_data(value, key) { + if (!value) { + data = new Array(this.size()), j = -1; + this.each(function (d) { + data[++j] = d; + }); + return data; + } + + var bind = key ? bindKey : bindIndex, + parents = this._parents, + groups = this._groups; + + if (typeof value !== "function") + value = constant$1(value); + + for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { + var parent = parents[j], + group = groups[j], + groupLength = group.length, + data = value.call(parent, parent && parent.__data__, j, parents), + dataLength = data.length, + enterGroup = enter[j] = new Array(dataLength), + updateGroup = update[j] = new Array(dataLength), + exitGroup = exit[j] = new Array(groupLength); + + bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); + + // Now connect the enter nodes to their following update node, such that + // appendChild can insert the materialized enter node before this node, + // rather than at the end of the parent node. + for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { + if (previous = enterGroup[i0]) { + if (i0 >= i1) + i1 = i0 + 1; + while (!(next = updateGroup[i1]) && ++i1 < dataLength) + ; + previous._next = next || null; + } + } + } + + update = new Selection(update, parents); + update._enter = enter; + update._exit = exit; + return update; + } + + function selection_exit() { + return new Selection(this._exit || this._groups.map(sparse), this._parents); + } + + function selection_join(onenter, onupdate, onexit) { + var enter = this.enter(), update = this, exit = this.exit(); + enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + ""); + if (onupdate != null) + update = onupdate(update); + if (onexit == null) + exit.remove(); + else + onexit(exit); + return enter && update ? enter.merge(update).order() : update; + } + + function selection_merge(selection) { + + for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Selection(merges, this._parents); + } + + function selection_order() { + + for (var groups = this._groups, j = -1, m = groups.length; ++j < m; ) { + for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { + if (node = group[i]) { + if (next && node.compareDocumentPosition(next) ^ 4) + next.parentNode.insertBefore(node, next); + next = node; + } + } + } + + return this; + } + + function selection_sort(compare) { + if (!compare) + compare = ascending$1; + + function compareNode(a, b) { + return a && b ? compare(a.__data__, b.__data__) : !a - !b; + } + + for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group[i]) { + sortgroup[i] = node; + } + } + sortgroup.sort(compareNode); + } + + return new Selection(sortgroups, this._parents).order(); + } + + function ascending$1(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; + } + + function selection_call() { + var callback = arguments[0]; + arguments[0] = this; + callback.apply(null, arguments); + return this; + } + + function selection_nodes() { + var nodes = new Array(this.size()), i = -1; + this.each(function () { + nodes[++i] = this; + }); + return nodes; + } + + function selection_node() { + + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { + var node = group[i]; + if (node) + return node; + } + } + + return null; + } + + function selection_size() { + var size = 0; + this.each(function () { + ++size; + }); + return size; + } + + function selection_empty() { + return !this.node(); + } + + function selection_each(callback) { + + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { + if (node = group[i]) + callback.call(node, node.__data__, i, group); + } + } + + return this; + } + + function attrRemove(name) { + return function () { + this.removeAttribute(name); + }; + } + + function attrRemoveNS(fullname) { + return function () { + this.removeAttributeNS(fullname.space, fullname.local); + }; + } + + function attrConstant(name, value) { + return function () { + this.setAttribute(name, value); + }; + } + + function attrConstantNS(fullname, value) { + return function () { + this.setAttributeNS(fullname.space, fullname.local, value); + }; + } + + function attrFunction(name, value) { + return function () { + var v = value.apply(this, arguments); + if (v == null) + this.removeAttribute(name); + else + this.setAttribute(name, v); + }; + } + + function attrFunctionNS(fullname, value) { + return function () { + var v = value.apply(this, arguments); + if (v == null) + this.removeAttributeNS(fullname.space, fullname.local); + else + this.setAttributeNS(fullname.space, fullname.local, v); + }; + } + + function selection_attr(name, value) { + var fullname = namespace(name); + + if (arguments.length < 2) { + var node = this.node(); + return fullname.local + ? node.getAttributeNS(fullname.space, fullname.local) + : node.getAttribute(fullname); + } + + return this.each((value == null + ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function" + ? (fullname.local ? attrFunctionNS : attrFunction) + : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value)); + } + + function defaultView(node) { + return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node + || (node.document && node) // node is a Window + || node.defaultView; // node is a Document + } + + function styleRemove(name) { + return function () { + this.style.removeProperty(name); + }; + } + + function styleConstant(name, value, priority) { + return function () { + this.style.setProperty(name, value, priority); + }; + } + + function styleFunction(name, value, priority) { + return function () { + var v = value.apply(this, arguments); + if (v == null) + this.style.removeProperty(name); + else + this.style.setProperty(name, v, priority); + }; + } + + function selection_style(name, value, priority) { + return arguments.length > 1 + ? this.each((value == null + ? styleRemove : typeof value === "function" + ? styleFunction + : styleConstant)(name, value, priority == null ? "" : priority)) + : styleValue(this.node(), name); + } + + function styleValue(node, name) { + return node.style.getPropertyValue(name) + || defaultView(node).getComputedStyle(node, null).getPropertyValue(name); + } + + function propertyRemove(name) { + return function () { + delete this[name]; + }; + } + + function propertyConstant(name, value) { + return function () { + this[name] = value; + }; + } + + function propertyFunction(name, value) { + return function () { + var v = value.apply(this, arguments); + if (v == null) + delete this[name]; + else + this[name] = v; + }; + } + + function selection_property(name, value) { + return arguments.length > 1 + ? this.each((value == null + ? propertyRemove : typeof value === "function" + ? propertyFunction + : propertyConstant)(name, value)) + : this.node()[name]; + } + + function classArray(string) { + return string.trim().split(/^|\s+/); + } + + function classList(node) { + return node.classList || new ClassList(node); + } + + function ClassList(node) { + this._node = node; + this._names = classArray(node.getAttribute("class") || ""); + } + + ClassList.prototype = { + add: function (name) { + var i = this._names.indexOf(name); + if (i < 0) { + this._names.push(name); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + remove: function (name) { + var i = this._names.indexOf(name); + if (i >= 0) { + this._names.splice(i, 1); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + contains: function (name) { + return this._names.indexOf(name) >= 0; + } + }; + + function classedAdd(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) + list.add(names[i]); + } + + function classedRemove(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) + list.remove(names[i]); + } + + function classedTrue(names) { + return function () { + classedAdd(this, names); + }; + } + + function classedFalse(names) { + return function () { + classedRemove(this, names); + }; + } + + function classedFunction(names, value) { + return function () { + (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); + }; + } + + function selection_classed(name, value) { + var names = classArray(name + ""); + + if (arguments.length < 2) { + var list = classList(this.node()), i = -1, n = names.length; + while (++i < n) + if (!list.contains(names[i])) + return false; + return true; + } + + return this.each((typeof value === "function" + ? classedFunction : value + ? classedTrue + : classedFalse)(names, value)); + } + + function textRemove() { + this.textContent = ""; + } + + function textConstant(value) { + return function () { + this.textContent = value; + }; + } + + function textFunction(value) { + return function () { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + }; + } + + function selection_text(value) { + return arguments.length + ? this.each(value == null + ? textRemove : (typeof value === "function" + ? textFunction + : textConstant)(value)) + : this.node().textContent; + } + + function htmlRemove() { + this.innerHTML = ""; + } + + function htmlConstant(value) { + return function () { + this.innerHTML = value; + }; + } + + function htmlFunction(value) { + return function () { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + }; + } + + function selection_html(value) { + return arguments.length + ? this.each(value == null + ? htmlRemove : (typeof value === "function" + ? htmlFunction + : htmlConstant)(value)) + : this.node().innerHTML; + } + + function raise() { + if (this.nextSibling) + this.parentNode.appendChild(this); + } + + function selection_raise() { + return this.each(raise); + } + + function lower() { + if (this.previousSibling) + this.parentNode.insertBefore(this, this.parentNode.firstChild); + } + + function selection_lower() { + return this.each(lower); + } + + function selection_append(name) { + var create = typeof name === "function" ? name : creator(name); + return this.select(function () { + return this.appendChild(create.apply(this, arguments)); + }); + } + + function constantNull() { + return null; + } + + function selection_insert(name, before) { + var create = typeof name === "function" ? name : creator(name), + select = before == null ? constantNull : typeof before === "function" ? before : selector(before); + return this.select(function () { + return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); + }); + } + + function remove() { + var parent = this.parentNode; + if (parent) + parent.removeChild(this); + } + + function selection_remove() { + return this.each(remove); + } + + function selection_cloneShallow() { + var clone = this.cloneNode(false), parent = this.parentNode; + return parent ? parent.insertBefore(clone, this.nextSibling) : clone; + } + + function selection_cloneDeep() { + var clone = this.cloneNode(true), parent = this.parentNode; + return parent ? parent.insertBefore(clone, this.nextSibling) : clone; + } + + function selection_clone(deep) { + return this.select(deep ? selection_cloneDeep : selection_cloneShallow); + } + + function selection_datum(value) { + return arguments.length + ? this.property("__data__", value) + : this.node().__data__; + } + + var filterEvents = {}; + + exports.event = null; + + if (typeof document !== "undefined") { + var element = document.documentElement; + if (!("onmouseenter" in element)) { + filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"}; + } + } + + function filterContextListener(listener, index, group) { + listener = contextListener(listener, index, group); + return function (event) { + var related = event.relatedTarget; + if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) { + listener.call(this, event); + } + }; + } + + function contextListener(listener, index, group) { + return function (event1) { + var event0 = exports.event; // Events can be reentrant (e.g., focus). + exports.event = event1; + try { + listener.call(this, this.__data__, index, group); + } finally { + exports.event = event0; + } + }; + } + + function parseTypenames$1(typenames) { + return typenames.trim().split(/^|\s+/).map(function (t) { + var name = "", i = t.indexOf("."); + if (i >= 0) + name = t.slice(i + 1), t = t.slice(0, i); + return {type: t, name: name}; + }); + } + + function onRemove(typename) { + return function () { + var on = this.__on; + if (!on) + return; + for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { + if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + } else { + on[++i] = o; + } + } + if (++i) + on.length = i; + else + delete this.__on; + }; + } + + function onAdd(typename, value, capture) { + var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; + return function (d, i, group) { + var on = this.__on, o, listener = wrap(value, i, group); + if (on) + for (var j = 0, m = on.length; j < m; ++j) { + if ((o = on[j]).type === typename.type && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + this.addEventListener(o.type, o.listener = listener, o.capture = capture); + o.value = value; + return; + } + } + this.addEventListener(typename.type, listener, capture); + o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture}; + if (!on) + this.__on = [o]; + else + on.push(o); + }; + } + + function selection_on(typename, value, capture) { + var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t; + + if (arguments.length < 2) { + var on = this.node().__on; + if (on) + for (var j = 0, m = on.length, o; j < m; ++j) { + for (i = 0, o = on[j]; i < n; ++i) { + if ((t = typenames[i]).type === o.type && t.name === o.name) { + return o.value; + } + } + } + return; + } + + on = value ? onAdd : onRemove; + if (capture == null) + capture = false; + for (i = 0; i < n; ++i) + this.each(on(typenames[i], value, capture)); + return this; + } + + function customEvent(event1, listener, that, args) { + var event0 = exports.event; + event1.sourceEvent = exports.event; + exports.event = event1; + try { + return listener.apply(that, args); + } finally { + exports.event = event0; + } + } + + function dispatchEvent(node, type, params) { + var window = defaultView(node), + event = window.CustomEvent; + + if (typeof event === "function") { + event = new event(type, params); + } else { + event = window.document.createEvent("Event"); + if (params) + event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; + else + event.initEvent(type, false, false); + } + + node.dispatchEvent(event); + } + + function dispatchConstant(type, params) { + return function () { + return dispatchEvent(this, type, params); + }; + } + + function dispatchFunction(type, params) { + return function () { + return dispatchEvent(this, type, params.apply(this, arguments)); + }; + } + + function selection_dispatch(type, params) { + return this.each((typeof params === "function" + ? dispatchFunction + : dispatchConstant)(type, params)); + } + + var root = [null]; + + function Selection(groups, parents) { + this._groups = groups; + this._parents = parents; + } + + function selection() { + return new Selection([[document.documentElement]], root); + } + + Selection.prototype = selection.prototype = { + constructor: Selection, + select: selection_select, + selectAll: selection_selectAll, + filter: selection_filter, + data: selection_data, + enter: selection_enter, + exit: selection_exit, + join: selection_join, + merge: selection_merge, + order: selection_order, + sort: selection_sort, + call: selection_call, + nodes: selection_nodes, + node: selection_node, + size: selection_size, + empty: selection_empty, + each: selection_each, + attr: selection_attr, + style: selection_style, + property: selection_property, + classed: selection_classed, + text: selection_text, + html: selection_html, + raise: selection_raise, + lower: selection_lower, + append: selection_append, + insert: selection_insert, + remove: selection_remove, + clone: selection_clone, + datum: selection_datum, + on: selection_on, + dispatch: selection_dispatch + }; + + function select(selector) { + return typeof selector === "string" + ? new Selection([[document.querySelector(selector)]], [document.documentElement]) + : new Selection([[selector]], root); + } + + function create(name) { + return select(creator(name).call(document.documentElement)); + } + + var nextId = 0; + + function local() { + return new Local; + } + + function Local() { + this._ = "@" + (++nextId).toString(36); + } + + Local.prototype = local.prototype = { + constructor: Local, + get: function (node) { + var id = this._; + while (!(id in node)) + if (!(node = node.parentNode)) + return; + return node[id]; + }, + set: function (node, value) { + return node[this._] = value; + }, + remove: function (node) { + return this._ in node && delete node[this._]; + }, + toString: function () { + return this._; + } + }; + + function sourceEvent() { + var current = exports.event, source; + while (source = current.sourceEvent) + current = source; + return current; + } + + function point(node, event) { + var svg = node.ownerSVGElement || node; + + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + point.x = event.clientX, point.y = event.clientY; + point = point.matrixTransform(node.getScreenCTM().inverse()); + return [point.x, point.y]; + } + + var rect = node.getBoundingClientRect(); + return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; + } + + function mouse(node) { + var event = sourceEvent(); + if (event.changedTouches) + event = event.changedTouches[0]; + return point(node, event); + } + + function selectAll(selector) { + return typeof selector === "string" + ? new Selection([document.querySelectorAll(selector)], [document.documentElement]) + : new Selection([selector == null ? [] : selector], root); + } + + function touch(node, touches, identifier) { + if (arguments.length < 3) + identifier = touches, touches = sourceEvent().changedTouches; + + for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) { + if ((touch = touches[i]).identifier === identifier) { + return point(node, touch); + } + } + + return null; + } + + function touches(node, touches) { + if (touches == null) + touches = sourceEvent().touches; + + for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) { + points[i] = point(node, touches[i]); + } + + return points; + } + + function nopropagation() { + exports.event.stopImmediatePropagation(); + } + + function noevent() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); + } + + function dragDisable(view) { + var root = view.document.documentElement, + selection = select(view).on("dragstart.drag", noevent, true); + if ("onselectstart" in root) { + selection.on("selectstart.drag", noevent, true); + } else { + root.__noselect = root.style.MozUserSelect; + root.style.MozUserSelect = "none"; + } + } + + function yesdrag(view, noclick) { + var root = view.document.documentElement, + selection = select(view).on("dragstart.drag", null); + if (noclick) { + selection.on("click.drag", noevent, true); + setTimeout(function () { + selection.on("click.drag", null); + }, 0); + } + if ("onselectstart" in root) { + selection.on("selectstart.drag", null); + } else { + root.style.MozUserSelect = root.__noselect; + delete root.__noselect; + } + } + + function constant$2(x) { + return function () { + return x; + }; + } + + function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) { + this.target = target; + this.type = type; + this.subject = subject; + this.identifier = id; + this.active = active; + this.x = x; + this.y = y; + this.dx = dx; + this.dy = dy; + this._ = dispatch; + } + + DragEvent.prototype.on = function () { + var value = this._.on.apply(this._, arguments); + return value === this._ ? this : value; + }; + +// Ignore right-click, since that should open the context menu. + function defaultFilter() { + return !exports.event.ctrlKey && !exports.event.button; + } + + function defaultContainer() { + return this.parentNode; + } + + function defaultSubject(d) { + return d == null ? {x: exports.event.x, y: exports.event.y} : d; + } + + function defaultTouchable() { + return navigator.maxTouchPoints || ("ontouchstart" in this); + } + + function drag() { + var filter = defaultFilter, + container = defaultContainer, + subject = defaultSubject, + touchable = defaultTouchable, + gestures = {}, + listeners = dispatch("start", "drag", "end"), + active = 0, + mousedownx, + mousedowny, + mousemoving, + touchending, + clickDistance2 = 0; + + function drag(selection) { + selection + .on("mousedown.drag", mousedowned) + .filter(touchable) + .on("touchstart.drag", touchstarted) + .on("touchmove.drag", touchmoved) + .on("touchend.drag touchcancel.drag", touchended) + .style("touch-action", "none") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + + function mousedowned() { + if (touchending || !filter.apply(this, arguments)) + return; + var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments); + if (!gesture) + return; + select(exports.event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true); + dragDisable(exports.event.view); + nopropagation(); + mousemoving = false; + mousedownx = exports.event.clientX; + mousedowny = exports.event.clientY; + gesture("start"); + } + + function mousemoved() { + noevent(); + if (!mousemoving) { + var dx = exports.event.clientX - mousedownx, dy = exports.event.clientY - mousedowny; + mousemoving = dx * dx + dy * dy > clickDistance2; + } + gestures.mouse("drag"); + } + + function mouseupped() { + select(exports.event.view).on("mousemove.drag mouseup.drag", null); + yesdrag(exports.event.view, mousemoving); + noevent(); + gestures.mouse("end"); + } + + function touchstarted() { + if (!filter.apply(this, arguments)) + return; + var touches = exports.event.changedTouches, + c = container.apply(this, arguments), + n = touches.length, i, gesture; + + for (i = 0; i < n; ++i) { + if (gesture = beforestart(touches[i].identifier, c, touch, this, arguments)) { + nopropagation(); + gesture("start"); + } + } + } + + function touchmoved() { + var touches = exports.event.changedTouches, + n = touches.length, i, gesture; + + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches[i].identifier]) { + noevent(); + gesture("drag"); + } + } + } + + function touchended() { + var touches = exports.event.changedTouches, + n = touches.length, i, gesture; + + if (touchending) + clearTimeout(touchending); + touchending = setTimeout(function () { + touchending = null; + }, 500); // Ghost clicks are delayed! + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches[i].identifier]) { + nopropagation(); + gesture("end"); + } + } + } + + function beforestart(id, container, point, that, args) { + var p = point(container, id), s, dx, dy, + sublisteners = listeners.copy(); + + if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function () { + if ((exports.event.subject = s = subject.apply(that, args)) == null) + return false; + dx = s.x - p[0] || 0; + dy = s.y - p[1] || 0; + return true; + })) + return; + + return function gesture(type) { + var p0 = p, n; + switch (type) { + case "start": + gestures[id] = gesture, n = active++; + break; + case "end": + delete gestures[id], --active; // nobreak + case "drag": + p = point(container, id), n = active; + break; + } + customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]); + }; + } + + drag.filter = function (_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter; + }; + + drag.container = function (_) { + return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container; + }; + + drag.subject = function (_) { + return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject; + }; + + drag.touchable = function (_) { + return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$2(!!_), drag) : touchable; + }; + + drag.on = function () { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? drag : value; + }; + + drag.clickDistance = function (_) { + return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2); + }; + + return drag; + } + + function define(constructor, factory, prototype) { + constructor.prototype = factory.prototype = prototype; + prototype.constructor = constructor; + } + + function extend(parent, definition) { + var prototype = Object.create(parent.prototype); + for (var key in definition) + prototype[key] = definition[key]; + return prototype; + } + + function Color() {} + + var darker = 0.7; + var brighter = 1 / darker; + + var reI = "\\s*([+-]?\\d+)\\s*", + reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*", + reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*", + reHex = /^#([0-9a-f]{3,8})$/, + reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"), + reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"), + reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"), + reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"), + reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"), + reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); + + var named = { + aliceblue: 0xf0f8ff, + antiquewhite: 0xfaebd7, + aqua: 0x00ffff, + aquamarine: 0x7fffd4, + azure: 0xf0ffff, + beige: 0xf5f5dc, + bisque: 0xffe4c4, + black: 0x000000, + blanchedalmond: 0xffebcd, + blue: 0x0000ff, + blueviolet: 0x8a2be2, + brown: 0xa52a2a, + burlywood: 0xdeb887, + cadetblue: 0x5f9ea0, + chartreuse: 0x7fff00, + chocolate: 0xd2691e, + coral: 0xff7f50, + cornflowerblue: 0x6495ed, + cornsilk: 0xfff8dc, + crimson: 0xdc143c, + cyan: 0x00ffff, + darkblue: 0x00008b, + darkcyan: 0x008b8b, + darkgoldenrod: 0xb8860b, + darkgray: 0xa9a9a9, + darkgreen: 0x006400, + darkgrey: 0xa9a9a9, + darkkhaki: 0xbdb76b, + darkmagenta: 0x8b008b, + darkolivegreen: 0x556b2f, + darkorange: 0xff8c00, + darkorchid: 0x9932cc, + darkred: 0x8b0000, + darksalmon: 0xe9967a, + darkseagreen: 0x8fbc8f, + darkslateblue: 0x483d8b, + darkslategray: 0x2f4f4f, + darkslategrey: 0x2f4f4f, + darkturquoise: 0x00ced1, + darkviolet: 0x9400d3, + deeppink: 0xff1493, + deepskyblue: 0x00bfff, + dimgray: 0x696969, + dimgrey: 0x696969, + dodgerblue: 0x1e90ff, + firebrick: 0xb22222, + floralwhite: 0xfffaf0, + forestgreen: 0x228b22, + fuchsia: 0xff00ff, + gainsboro: 0xdcdcdc, + ghostwhite: 0xf8f8ff, + gold: 0xffd700, + goldenrod: 0xdaa520, + gray: 0x808080, + green: 0x008000, + greenyellow: 0xadff2f, + grey: 0x808080, + honeydew: 0xf0fff0, + hotpink: 0xff69b4, + indianred: 0xcd5c5c, + indigo: 0x4b0082, + ivory: 0xfffff0, + khaki: 0xf0e68c, + lavender: 0xe6e6fa, + lavenderblush: 0xfff0f5, + lawngreen: 0x7cfc00, + lemonchiffon: 0xfffacd, + lightblue: 0xadd8e6, + lightcoral: 0xf08080, + lightcyan: 0xe0ffff, + lightgoldenrodyellow: 0xfafad2, + lightgray: 0xd3d3d3, + lightgreen: 0x90ee90, + lightgrey: 0xd3d3d3, + lightpink: 0xffb6c1, + lightsalmon: 0xffa07a, + lightseagreen: 0x20b2aa, + lightskyblue: 0x87cefa, + lightslategray: 0x778899, + lightslategrey: 0x778899, + lightsteelblue: 0xb0c4de, + lightyellow: 0xffffe0, + lime: 0x00ff00, + limegreen: 0x32cd32, + linen: 0xfaf0e6, + magenta: 0xff00ff, + maroon: 0x800000, + mediumaquamarine: 0x66cdaa, + mediumblue: 0x0000cd, + mediumorchid: 0xba55d3, + mediumpurple: 0x9370db, + mediumseagreen: 0x3cb371, + mediumslateblue: 0x7b68ee, + mediumspringgreen: 0x00fa9a, + mediumturquoise: 0x48d1cc, + mediumvioletred: 0xc71585, + midnightblue: 0x191970, + mintcream: 0xf5fffa, + mistyrose: 0xffe4e1, + moccasin: 0xffe4b5, + navajowhite: 0xffdead, + navy: 0x000080, + oldlace: 0xfdf5e6, + olive: 0x808000, + olivedrab: 0x6b8e23, + orange: 0xffa500, + orangered: 0xff4500, + orchid: 0xda70d6, + palegoldenrod: 0xeee8aa, + palegreen: 0x98fb98, + paleturquoise: 0xafeeee, + palevioletred: 0xdb7093, + papayawhip: 0xffefd5, + peachpuff: 0xffdab9, + peru: 0xcd853f, + pink: 0xffc0cb, + plum: 0xdda0dd, + powderblue: 0xb0e0e6, + purple: 0x800080, + rebeccapurple: 0x663399, + red: 0xff0000, + rosybrown: 0xbc8f8f, + royalblue: 0x4169e1, + saddlebrown: 0x8b4513, + salmon: 0xfa8072, + sandybrown: 0xf4a460, + seagreen: 0x2e8b57, + seashell: 0xfff5ee, + sienna: 0xa0522d, + silver: 0xc0c0c0, + skyblue: 0x87ceeb, + slateblue: 0x6a5acd, + slategray: 0x708090, + slategrey: 0x708090, + snow: 0xfffafa, + springgreen: 0x00ff7f, + steelblue: 0x4682b4, + tan: 0xd2b48c, + teal: 0x008080, + thistle: 0xd8bfd8, + tomato: 0xff6347, + turquoise: 0x40e0d0, + violet: 0xee82ee, + wheat: 0xf5deb3, + white: 0xffffff, + whitesmoke: 0xf5f5f5, + yellow: 0xffff00, + yellowgreen: 0x9acd32 + }; + + define(Color, color, { + copy: function (channels) { + return Object.assign(new this.constructor, this, channels); + }, + displayable: function () { + return this.rgb().displayable(); + }, + hex: color_formatHex, // Deprecated! Use color.formatHex. + formatHex: color_formatHex, + formatHsl: color_formatHsl, + formatRgb: color_formatRgb, + toString: color_formatRgb + }); + + function color_formatHex() { + return this.rgb().formatHex(); + } + + function color_formatHsl() { + return hslConvert(this).formatHsl(); + } + + function color_formatRgb() { + return this.rgb().formatRgb(); + } + + function color(format) { + var m, l; + format = (format + "").trim().toLowerCase(); + return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000 + : l === 3 ? new Rgb((m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1) // #f00 + : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000 + : l === 4 ? rgba((m >> 12 & 0xf) | (m >> 8 & 0xf0), (m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), (((m & 0xf) << 4) | (m & 0xf)) / 0xff) // #f000 + : null) // invalid hex + : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) + : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) + : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) + : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) + : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) + : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) + : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins + : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) + : null; + } + + function rgbn(n) { + return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); + } + + function rgba(r, g, b, a) { + if (a <= 0) + r = g = b = NaN; + return new Rgb(r, g, b, a); + } + + function rgbConvert(o) { + if (!(o instanceof Color)) + o = color(o); + if (!o) + return new Rgb; + o = o.rgb(); + return new Rgb(o.r, o.g, o.b, o.opacity); + } + + function rgb(r, g, b, opacity) { + return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); + } + + function Rgb(r, g, b, opacity) { + this.r = +r; + this.g = +g; + this.b = +b; + this.opacity = +opacity; + } + + define(Rgb, rgb, extend(Color, { + brighter: function (k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + darker: function (k) { + k = k == null ? darker : Math.pow(darker, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + rgb: function () { + return this; + }, + displayable: function () { + return (-0.5 <= this.r && this.r < 255.5) + && (-0.5 <= this.g && this.g < 255.5) + && (-0.5 <= this.b && this.b < 255.5) + && (0 <= this.opacity && this.opacity <= 1); + }, + hex: rgb_formatHex, // Deprecated! Use color.formatHex. + formatHex: rgb_formatHex, + formatRgb: rgb_formatRgb, + toString: rgb_formatRgb + })); + + function rgb_formatHex() { + return "#" + hex(this.r) + hex(this.g) + hex(this.b); + } + + function rgb_formatRgb() { + var a = this.opacity; + a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); + return (a === 1 ? "rgb(" : "rgba(") + + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + + (a === 1 ? ")" : ", " + a + ")"); + } + + function hex(value) { + value = Math.max(0, Math.min(255, Math.round(value) || 0)); + return (value < 16 ? "0" : "") + value.toString(16); + } + + function hsla(h, s, l, a) { + if (a <= 0) + h = s = l = NaN; + else if (l <= 0 || l >= 1) + h = s = NaN; + else if (s <= 0) + h = NaN; + return new Hsl(h, s, l, a); + } + + function hslConvert(o) { + if (o instanceof Hsl) + return new Hsl(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Color)) + o = color(o); + if (!o) + return new Hsl; + if (o instanceof Hsl) + return o; + o = o.rgb(); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + h = NaN, + s = max - min, + l = (max + min) / 2; + if (s) { + if (r === max) + h = (g - b) / s + (g < b) * 6; + else if (g === max) + h = (b - r) / s + 2; + else + h = (r - g) / s + 4; + s /= l < 0.5 ? max + min : 2 - max - min; + h *= 60; + } else { + s = l > 0 && l < 1 ? 0 : h; + } + return new Hsl(h, s, l, o.opacity); + } + + function hsl(h, s, l, opacity) { + return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); + } + + function Hsl(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; + } + + define(Hsl, hsl, extend(Color, { + brighter: function (k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + darker: function (k) { + k = k == null ? darker : Math.pow(darker, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function () { + var h = this.h % 360 + (this.h < 0) * 360, + s = isNaN(h) || isNaN(this.s) ? 0 : this.s, + l = this.l, + m2 = l + (l < 0.5 ? l : 1 - l) * s, + m1 = 2 * l - m2; + return new Rgb( + hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), + hsl2rgb(h, m1, m2), + hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), + this.opacity + ); + }, + displayable: function () { + return (0 <= this.s && this.s <= 1 || isNaN(this.s)) + && (0 <= this.l && this.l <= 1) + && (0 <= this.opacity && this.opacity <= 1); + }, + formatHsl: function () { + var a = this.opacity; + a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); + return (a === 1 ? "hsl(" : "hsla(") + + (this.h || 0) + ", " + + (this.s || 0) * 100 + "%, " + + (this.l || 0) * 100 + "%" + + (a === 1 ? ")" : ", " + a + ")"); + } + })); + + /* From FvD 13.37, CSS Color Module Level 3 */ + function hsl2rgb(h, m1, m2) { + return (h < 60 ? m1 + (m2 - m1) * h / 60 + : h < 180 ? m2 + : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 + : m1) * 255; + } + + var deg2rad = Math.PI / 180; + var rad2deg = 180 / Math.PI; + +// https://observablehq.com/@mbostock/lab-and-rgb + var K = 18, + Xn = 0.96422, + Yn = 1, + Zn = 0.82521, + t0 = 4 / 29, + t1 = 6 / 29, + t2 = 3 * t1 * t1, + t3 = t1 * t1 * t1; + + function labConvert(o) { + if (o instanceof Lab) + return new Lab(o.l, o.a, o.b, o.opacity); + if (o instanceof Hcl) + return hcl2lab(o); + if (!(o instanceof Rgb)) + o = rgbConvert(o); + var r = rgb2lrgb(o.r), + g = rgb2lrgb(o.g), + b = rgb2lrgb(o.b), + y = xyz2lab((0.2225045 * r + 0.7168786 * g + 0.0606169 * b) / Yn), x, z; + if (r === g && g === b) + x = z = y; + else { + x = xyz2lab((0.4360747 * r + 0.3850649 * g + 0.1430804 * b) / Xn); + z = xyz2lab((0.0139322 * r + 0.0971045 * g + 0.7141733 * b) / Zn); + } + return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); + } + + function gray(l, opacity) { + return new Lab(l, 0, 0, opacity == null ? 1 : opacity); + } + + function lab(l, a, b, opacity) { + return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); + } + + function Lab(l, a, b, opacity) { + this.l = +l; + this.a = +a; + this.b = +b; + this.opacity = +opacity; + } + + define(Lab, lab, extend(Color, { + brighter: function (k) { + return new Lab(this.l + K * (k == null ? 1 : k), this.a, this.b, this.opacity); + }, + darker: function (k) { + return new Lab(this.l - K * (k == null ? 1 : k), this.a, this.b, this.opacity); + }, + rgb: function () { + var y = (this.l + 16) / 116, + x = isNaN(this.a) ? y : y + this.a / 500, + z = isNaN(this.b) ? y : y - this.b / 200; + x = Xn * lab2xyz(x); + y = Yn * lab2xyz(y); + z = Zn * lab2xyz(z); + return new Rgb( + lrgb2rgb(3.1338561 * x - 1.6168667 * y - 0.4906146 * z), + lrgb2rgb(-0.9787684 * x + 1.9161415 * y + 0.0334540 * z), + lrgb2rgb(0.0719453 * x - 0.2289914 * y + 1.4052427 * z), + this.opacity + ); + } + })); + + function xyz2lab(t) { + return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; + } + + function lab2xyz(t) { + return t > t1 ? t * t * t : t2 * (t - t0); + } + + function lrgb2rgb(x) { + return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); + } + + function rgb2lrgb(x) { + return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); + } + + function hclConvert(o) { + if (o instanceof Hcl) + return new Hcl(o.h, o.c, o.l, o.opacity); + if (!(o instanceof Lab)) + o = labConvert(o); + if (o.a === 0 && o.b === 0) + return new Hcl(NaN, 0 < o.l && o.l < 100 ? 0 : NaN, o.l, o.opacity); + var h = Math.atan2(o.b, o.a) * rad2deg; + return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); + } + + function lch(l, c, h, opacity) { + return arguments.length === 1 ? hclConvert(l) : new Hcl(h, c, l, opacity == null ? 1 : opacity); + } + + function hcl(h, c, l, opacity) { + return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); + } + + function Hcl(h, c, l, opacity) { + this.h = +h; + this.c = +c; + this.l = +l; + this.opacity = +opacity; + } + + function hcl2lab(o) { + if (isNaN(o.h)) + return new Lab(o.l, 0, 0, o.opacity); + var h = o.h * deg2rad; + return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); + } + + define(Hcl, hcl, extend(Color, { + brighter: function (k) { + return new Hcl(this.h, this.c, this.l + K * (k == null ? 1 : k), this.opacity); + }, + darker: function (k) { + return new Hcl(this.h, this.c, this.l - K * (k == null ? 1 : k), this.opacity); + }, + rgb: function () { + return hcl2lab(this).rgb(); + } + })); + + var A = -0.14861, + B = +1.78277, + C = -0.29227, + D = -0.90649, + E = +1.97294, + ED = E * D, + EB = E * B, + BC_DA = B * C - D * A; + + function cubehelixConvert(o) { + if (o instanceof Cubehelix) + return new Cubehelix(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Rgb)) + o = rgbConvert(o); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), + bl = b - l, + k = (E * (g - l) - C * bl) / D, + s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 + h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; + return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); + } + + function cubehelix(h, s, l, opacity) { + return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); + } + + function Cubehelix(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; + } + + define(Cubehelix, cubehelix, extend(Color, { + brighter: function (k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); + }, + darker: function (k) { + k = k == null ? darker : Math.pow(darker, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function () { + var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, + l = +this.l, + a = isNaN(this.s) ? 0 : this.s * l * (1 - l), + cosh = Math.cos(h), + sinh = Math.sin(h); + return new Rgb( + 255 * (l + a * (A * cosh + B * sinh)), + 255 * (l + a * (C * cosh + D * sinh)), + 255 * (l + a * (E * cosh)), + this.opacity + ); + } + })); + + function basis(t1, v0, v1, v2, v3) { + var t2 = t1 * t1, t3 = t2 * t1; + return ((1 - 3 * t1 + 3 * t2 - t3) * v0 + + (4 - 6 * t2 + 3 * t3) * v1 + + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 + + t3 * v3) / 6; + } + + function basis$1(values) { + var n = values.length - 1; + return function (t) { + var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), + v1 = values[i], + v2 = values[i + 1], + v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, + v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; + } + + function basisClosed(values) { + var n = values.length; + return function (t) { + var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), + v0 = values[(i + n - 1) % n], + v1 = values[i % n], + v2 = values[(i + 1) % n], + v3 = values[(i + 2) % n]; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; + } + + function constant$3(x) { + return function () { + return x; + }; + } + + function linear(a, d) { + return function (t) { + return a + t * d; + }; + } + + function exponential(a, b, y) { + return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function (t) { + return Math.pow(a + t * b, y); + }; + } + + function hue(a, b) { + var d = b - a; + return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a); + } + + function gamma(y) { + return (y = +y) === 1 ? nogamma : function (a, b) { + return b - a ? exponential(a, b, y) : constant$3(isNaN(a) ? b : a); + }; + } + + function nogamma(a, b) { + var d = b - a; + return d ? linear(a, d) : constant$3(isNaN(a) ? b : a); + } + + var interpolateRgb = (function rgbGamma(y) { + var color = gamma(y); + + function rgb$1(start, end) { + var r = color((start = rgb(start)).r, (end = rgb(end)).r), + g = color(start.g, end.g), + b = color(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function (t) { + start.r = r(t); + start.g = g(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; + } + + rgb$1.gamma = rgbGamma; + + return rgb$1; + })(1); + + function rgbSpline(spline) { + return function (colors) { + var n = colors.length, + r = new Array(n), + g = new Array(n), + b = new Array(n), + i, color; + for (i = 0; i < n; ++i) { + color = rgb(colors[i]); + r[i] = color.r || 0; + g[i] = color.g || 0; + b[i] = color.b || 0; + } + r = spline(r); + g = spline(g); + b = spline(b); + color.opacity = 1; + return function (t) { + color.r = r(t); + color.g = g(t); + color.b = b(t); + return color + ""; + }; + }; + } + + var rgbBasis = rgbSpline(basis$1); + var rgbBasisClosed = rgbSpline(basisClosed); + + function numberArray(a, b) { + if (!b) + b = []; + var n = a ? Math.min(b.length, a.length) : 0, + c = b.slice(), + i; + return function (t) { + for (i = 0; i < n; ++i) + c[i] = a[i] * (1 - t) + b[i] * t; + return c; + }; + } + + function isNumberArray(x) { + return ArrayBuffer.isView(x) && !(x instanceof DataView); + } + + function array$1(a, b) { + return (isNumberArray(b) ? numberArray : genericArray)(a, b); + } + + function genericArray(a, b) { + var nb = b ? b.length : 0, + na = a ? Math.min(nb, a.length) : 0, + x = new Array(na), + c = new Array(nb), + i; + + for (i = 0; i < na; ++i) + x[i] = interpolateValue(a[i], b[i]); + for (; i < nb; ++i) + c[i] = b[i]; + + return function (t) { + for (i = 0; i < na; ++i) + c[i] = x[i](t); + return c; + }; + } + + function date(a, b) { + var d = new Date; + return a = +a, b = +b, function (t) { + return d.setTime(a * (1 - t) + b * t), d; + }; + } + + function interpolateNumber(a, b) { + return a = +a, b = +b, function (t) { + return a * (1 - t) + b * t; + }; + } + + function object(a, b) { + var i = {}, + c = {}, + k; + + if (a === null || typeof a !== "object") + a = {}; + if (b === null || typeof b !== "object") + b = {}; + + for (k in b) { + if (k in a) { + i[k] = interpolateValue(a[k], b[k]); + } else { + c[k] = b[k]; + } + } + + return function (t) { + for (k in i) + c[k] = i[k](t); + return c; + }; + } + + var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, + reB = new RegExp(reA.source, "g"); + + function zero(b) { + return function () { + return b; + }; + } + + function one(b) { + return function (t) { + return b(t) + ""; + }; + } + + function interpolateString(a, b) { + var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b + am, // current match in a + bm, // current match in b + bs, // string preceding current number in b, if any + i = -1, // index in s + s = [], // string constants and placeholders + q = []; // number interpolators + + // Coerce inputs to strings. + a = a + "", b = b + ""; + + // Interpolate pairs of numbers in a & b. + while ((am = reA.exec(a)) + && (bm = reB.exec(b))) { + if ((bs = bm.index) > bi) { // a string precedes the next number in b + bs = b.slice(bi, bs); + if (s[i]) + s[i] += bs; // coalesce with previous string + else + s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match + if (s[i]) + s[i] += bm; // coalesce with previous string + else + s[++i] = bm; + } else { // interpolate non-matching numbers + s[++i] = null; + q.push({i: i, x: interpolateNumber(am, bm)}); + } + bi = reB.lastIndex; + } + + // Add remains of b. + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) + s[i] += bs; // coalesce with previous string + else + s[++i] = bs; + } + + // Special optimization for only a single match. + // Otherwise, interpolate each of the numbers and rejoin the string. + return s.length < 2 ? (q[0] + ? one(q[0].x) + : zero(b)) + : (b = q.length, function (t) { + for (var i = 0, o; i < b; ++i) + s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); + } + + function interpolateValue(a, b) { + var t = typeof b, c; + return b == null || t === "boolean" ? constant$3(b) + : (t === "number" ? interpolateNumber + : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString) + : b instanceof color ? interpolateRgb + : b instanceof Date ? date + : isNumberArray(b) ? numberArray + : Array.isArray(b) ? genericArray + : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object + : interpolateNumber)(a, b); + } + + function discrete(range) { + var n = range.length; + return function (t) { + return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; + }; + } + + function hue$1(a, b) { + var i = hue(+a, +b); + return function (t) { + var x = i(t); + return x - 360 * Math.floor(x / 360); + }; + } + + function interpolateRound(a, b) { + return a = +a, b = +b, function (t) { + return Math.round(a * (1 - t) + b * t); + }; + } + + var degrees = 180 / Math.PI; + + var identity$2 = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1 + }; + + function decompose(a, b, c, d, e, f) { + var scaleX, scaleY, skewX; + if (scaleX = Math.sqrt(a * a + b * b)) + a /= scaleX, b /= scaleX; + if (skewX = a * c + b * d) + c -= a * skewX, d -= b * skewX; + if (scaleY = Math.sqrt(c * c + d * d)) + c /= scaleY, d /= scaleY, skewX /= scaleY; + if (a * d < b * c) + a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; + return { + translateX: e, + translateY: f, + rotate: Math.atan2(b, a) * degrees, + skewX: Math.atan(skewX) * degrees, + scaleX: scaleX, + scaleY: scaleY + }; + } + + var cssNode, + cssRoot, + cssView, + svgNode; + + function parseCss(value) { + if (value === "none") + return identity$2; + if (!cssNode) + cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; + cssNode.style.transform = value; + value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); + cssRoot.removeChild(cssNode); + value = value.slice(7, -1).split(","); + return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); + } + + function parseSvg(value) { + if (value == null) + return identity$2; + if (!svgNode) + svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svgNode.setAttribute("transform", value); + if (!(value = svgNode.transform.baseVal.consolidate())) + return identity$2; + value = value.matrix; + return decompose(value.a, value.b, value.c, value.d, value.e, value.f); + } + + function interpolateTransform(parse, pxComma, pxParen, degParen) { + + function pop(s) { + return s.length ? s.pop() + " " : ""; + } + + function translate(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push("translate(", null, pxComma, null, pxParen); + q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); + } else if (xb || yb) { + s.push("translate(" + xb + pxComma + yb + pxParen); + } + } + + function rotate(a, b, s, q) { + if (a !== b) { + if (a - b > 180) + b += 360; + else if (b - a > 180) + a += 360; // shortest path + q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: interpolateNumber(a, b)}); + } else if (b) { + s.push(pop(s) + "rotate(" + b + degParen); + } + } + + function skewX(a, b, s, q) { + if (a !== b) { + q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: interpolateNumber(a, b)}); + } else if (b) { + s.push(pop(s) + "skewX(" + b + degParen); + } + } + + function scale(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push(pop(s) + "scale(", null, ",", null, ")"); + q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)}); + } else if (xb !== 1 || yb !== 1) { + s.push(pop(s) + "scale(" + xb + "," + yb + ")"); + } + } + + return function (a, b) { + var s = [], // string constants and placeholders + q = []; // number interpolators + a = parse(a), b = parse(b); + translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); + rotate(a.rotate, b.rotate, s, q); + skewX(a.skewX, b.skewX, s, q); + scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); + a = b = null; // gc + return function (t) { + var i = -1, n = q.length, o; + while (++i < n) + s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + }; + } + + var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); + var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); + + var rho = Math.SQRT2, + rho2 = 2, + rho4 = 4, + epsilon2 = 1e-12; + + function cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; + } + + function sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; + } + + function tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); + } + +// p0 = [ux0, uy0, w0] +// p1 = [ux1, uy1, w1] + function interpolateZoom(p0, p1) { + var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], + ux1 = p1[0], uy1 = p1[1], w1 = p1[2], + dx = ux1 - ux0, + dy = uy1 - uy0, + d2 = dx * dx + dy * dy, + i, + S; + + // Special case for u0 ≅ u1. + if (d2 < epsilon2) { + S = Math.log(w1 / w0) / rho; + i = function (t) { + return [ + ux0 + t * dx, + uy0 + t * dy, + w0 * Math.exp(rho * t * S) + ]; + }; + } + + // General case. + else { + var d1 = Math.sqrt(d2), + b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), + b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), + r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), + r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / rho; + i = function (t) { + var s = t * S, + coshr0 = cosh(r0), + u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); + return [ + ux0 + u * dx, + uy0 + u * dy, + w0 * coshr0 / cosh(rho * s + r0) + ]; + }; + } + + i.duration = S * 1000; + + return i; + } + + function hsl$1(hue) { + return function (start, end) { + var h = hue((start = hsl(start)).h, (end = hsl(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function (t) { + start.h = h(t); + start.s = s(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } + } + + var hsl$2 = hsl$1(hue); + var hslLong = hsl$1(nogamma); + + function lab$1(start, end) { + var l = nogamma((start = lab(start)).l, (end = lab(end)).l), + a = nogamma(start.a, end.a), + b = nogamma(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function (t) { + start.l = l(t); + start.a = a(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; + } + + function hcl$1(hue) { + return function (start, end) { + var h = hue((start = hcl(start)).h, (end = hcl(end)).h), + c = nogamma(start.c, end.c), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function (t) { + start.h = h(t); + start.c = c(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } + } + + var hcl$2 = hcl$1(hue); + var hclLong = hcl$1(nogamma); + + function cubehelix$1(hue) { + return (function cubehelixGamma(y) { + y = +y; + + function cubehelix$1(start, end) { + var h = hue((start = cubehelix(start)).h, (end = cubehelix(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function (t) { + start.h = h(t); + start.s = s(t); + start.l = l(Math.pow(t, y)); + start.opacity = opacity(t); + return start + ""; + }; + } + + cubehelix$1.gamma = cubehelixGamma; + + return cubehelix$1; + })(1); + } + + var cubehelix$2 = cubehelix$1(hue); + var cubehelixLong = cubehelix$1(nogamma); + + function piecewise(interpolate, values) { + var i = 0, n = values.length - 1, v = values[0], I = new Array(n < 0 ? 0 : n); + while (i < n) + I[i] = interpolate(v, v = values[++i]); + return function (t) { + var i = Math.max(0, Math.min(n - 1, Math.floor(t *= n))); + return I[i](t - i); + }; + } + + function quantize(interpolator, n) { + var samples = new Array(n); + for (var i = 0; i < n; ++i) + samples[i] = interpolator(i / (n - 1)); + return samples; + } + + var frame = 0, // is an animation frame pending? + timeout = 0, // is a timeout pending? + interval = 0, // are any timers active? + pokeDelay = 1000, // how frequently we check for clock skew + taskHead, + taskTail, + clockLast = 0, + clockNow = 0, + clockSkew = 0, + clock = typeof performance === "object" && performance.now ? performance : Date, + setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function (f) { + setTimeout(f, 17); + }; + + function now() { + return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); + } + + function clearNow() { + clockNow = 0; + } + + function Timer() { + this._call = + this._time = + this._next = null; + } + + Timer.prototype = timer.prototype = { + constructor: Timer, + restart: function (callback, delay, time) { + if (typeof callback !== "function") + throw new TypeError("callback is not a function"); + time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); + if (!this._next && taskTail !== this) { + if (taskTail) + taskTail._next = this; + else + taskHead = this; + taskTail = this; + } + this._call = callback; + this._time = time; + sleep(); + }, + stop: function () { + if (this._call) { + this._call = null; + this._time = Infinity; + sleep(); + } + } + }; + + function timer(callback, delay, time) { + var t = new Timer; + t.restart(callback, delay, time); + return t; + } + + function timerFlush() { + now(); // Get the current time, if not already set. + ++frame; // Pretend we’ve set an alarm, if we haven’t already. + var t = taskHead, e; + while (t) { + if ((e = clockNow - t._time) >= 0) + t._call.call(null, e); + t = t._next; + } + --frame; + } + + function wake() { + clockNow = (clockLast = clock.now()) + clockSkew; + frame = timeout = 0; + try { + timerFlush(); + } finally { + frame = 0; + nap(); + clockNow = 0; + } + } + + function poke() { + var now = clock.now(), delay = now - clockLast; + if (delay > pokeDelay) + clockSkew -= delay, clockLast = now; + } + + function nap() { + var t0, t1 = taskHead, t2, time = Infinity; + while (t1) { + if (t1._call) { + if (time > t1._time) + time = t1._time; + t0 = t1, t1 = t1._next; + } else { + t2 = t1._next, t1._next = null; + t1 = t0 ? t0._next = t2 : taskHead = t2; + } + } + taskTail = t0; + sleep(time); + } + + function sleep(time) { + if (frame) + return; // Soonest alarm already set, or will be. + if (timeout) + timeout = clearTimeout(timeout); + var delay = time - clockNow; // Strictly less than if we recomputed clockNow. + if (delay > 24) { + if (time < Infinity) + timeout = setTimeout(wake, time - clock.now() - clockSkew); + if (interval) + interval = clearInterval(interval); + } else { + if (!interval) + clockLast = clock.now(), interval = setInterval(poke, pokeDelay); + frame = 1, setFrame(wake); + } + } + + function timeout$1(callback, delay, time) { + var t = new Timer; + delay = delay == null ? 0 : +delay; + t.restart(function (elapsed) { + t.stop(); + callback(elapsed + delay); + }, delay, time); + return t; + } + + function interval$1(callback, delay, time) { + var t = new Timer, total = delay; + if (delay == null) + return t.restart(callback, delay, time), t; + delay = +delay, time = time == null ? now() : +time; + t.restart(function tick(elapsed) { + elapsed += total; + t.restart(tick, total += delay, time); + callback(elapsed); + }, delay, time); + return t; + } + + var emptyOn = dispatch("start", "end", "cancel", "interrupt"); + var emptyTween = []; + + var CREATED = 0; + var SCHEDULED = 1; + var STARTING = 2; + var STARTED = 3; + var RUNNING = 4; + var ENDING = 5; + var ENDED = 6; + + function schedule(node, name, id, index, group, timing) { + var schedules = node.__transition; + if (!schedules) + node.__transition = {}; + else if (id in schedules) + return; + create$1(node, id, { + name: name, + index: index, // For context during callback. + group: group, // For context during callback. + on: emptyOn, + tween: emptyTween, + time: timing.time, + delay: timing.delay, + duration: timing.duration, + ease: timing.ease, + timer: null, + state: CREATED + }); + } + + function init(node, id) { + var schedule = get$1(node, id); + if (schedule.state > CREATED) + throw new Error("too late; already scheduled"); + return schedule; + } + + function set$1(node, id) { + var schedule = get$1(node, id); + if (schedule.state > STARTED) + throw new Error("too late; already running"); + return schedule; + } + + function get$1(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id])) + throw new Error("transition not found"); + return schedule; + } + + function create$1(node, id, self) { + var schedules = node.__transition, + tween; + + // Initialize the self timer when the transition is created. + // Note the actual delay is not known until the first callback! + schedules[id] = self; + self.timer = timer(schedule, 0, self.time); + + function schedule(elapsed) { + self.state = SCHEDULED; + self.timer.restart(start, self.delay, self.time); + + // If the elapsed delay is less than our first sleep, start immediately. + if (self.delay <= elapsed) + start(elapsed - self.delay); + } + + function start(elapsed) { + var i, j, n, o; + + // If the state is not SCHEDULED, then we previously errored on start. + if (self.state !== SCHEDULED) + return stop(); + + for (i in schedules) { + o = schedules[i]; + if (o.name !== self.name) + continue; + + // While this element already has a starting transition during this frame, + // defer starting an interrupting transition until that transition has a + // chance to tick (and possibly end); see d3/d3-transition#54! + if (o.state === STARTED) + return timeout$1(start); + + // Interrupt the active transition, if any. + if (o.state === RUNNING) { + o.state = ENDED; + o.timer.stop(); + o.on.call("interrupt", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + + // Cancel any pre-empted transitions. + else if (+i < id) { + o.state = ENDED; + o.timer.stop(); + o.on.call("cancel", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + } + + // Defer the first tick to end of the current frame; see d3/d3#1576. + // Note the transition may be canceled after start and before the first tick! + // Note this must be scheduled before the start event; see d3/d3-transition#16! + // Assuming this is successful, subsequent callbacks go straight to tick. + timeout$1(function () { + if (self.state === STARTED) { + self.state = RUNNING; + self.timer.restart(tick, self.delay, self.time); + tick(elapsed); + } + }); + + // Dispatch the start event. + // Note this must be done before the tween are initialized. + self.state = STARTING; + self.on.call("start", node, node.__data__, self.index, self.group); + if (self.state !== STARTING) + return; // interrupted + self.state = STARTED; + + // Initialize the tween, deleting null tween. + tween = new Array(n = self.tween.length); + for (i = 0, j = -1; i < n; ++i) { + if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { + tween[++j] = o; + } + } + tween.length = j + 1; + } + + function tick(elapsed) { + var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), + i = -1, + n = tween.length; + + while (++i < n) { + tween[i].call(node, t); + } + + // Dispatch the end event. + if (self.state === ENDING) { + self.on.call("end", node, node.__data__, self.index, self.group); + stop(); + } + } + + function stop() { + self.state = ENDED; + self.timer.stop(); + delete schedules[id]; + for (var i in schedules) + return; // eslint-disable-line no-unused-vars + delete node.__transition; + } + } + + function interrupt(node, name) { + var schedules = node.__transition, + schedule, + active, + empty = true, + i; + + if (!schedules) + return; + + name = name == null ? null : name + ""; + + for (i in schedules) { + if ((schedule = schedules[i]).name !== name) { + empty = false; + continue; + } + active = schedule.state > STARTING && schedule.state < ENDING; + schedule.state = ENDED; + schedule.timer.stop(); + schedule.on.call(active ? "interrupt" : "cancel", node, node.__data__, schedule.index, schedule.group); + delete schedules[i]; + } + + if (empty) + delete node.__transition; + } + + function selection_interrupt(name) { + return this.each(function () { + interrupt(this, name); + }); + } + + function tweenRemove(id, name) { + var tween0, tween1; + return function () { + var schedule = set$1(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = tween0 = tween; + for (var i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1 = tween1.slice(); + tween1.splice(i, 1); + break; + } + } + } + + schedule.tween = tween1; + }; + } + + function tweenFunction(id, name, value) { + var tween0, tween1; + if (typeof value !== "function") + throw new Error; + return function () { + var schedule = set$1(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = (tween0 = tween).slice(); + for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1[i] = t; + break; + } + } + if (i === n) + tween1.push(t); + } + + schedule.tween = tween1; + }; + } + + function transition_tween(name, value) { + var id = this._id; + + name += ""; + + if (arguments.length < 2) { + var tween = get$1(this.node(), id).tween; + for (var i = 0, n = tween.length, t; i < n; ++i) { + if ((t = tween[i]).name === name) { + return t.value; + } + } + return null; + } + + return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); + } + + function tweenValue(transition, name, value) { + var id = transition._id; + + transition.each(function () { + var schedule = set$1(this, id); + (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); + }); + + return function (node) { + return get$1(node, id).value[name]; + }; + } + + function interpolate(a, b) { + var c; + return (typeof b === "number" ? interpolateNumber + : b instanceof color ? interpolateRgb + : (c = color(b)) ? (b = c, interpolateRgb) + : interpolateString)(a, b); + } + + function attrRemove$1(name) { + return function () { + this.removeAttribute(name); + }; + } + + function attrRemoveNS$1(fullname) { + return function () { + this.removeAttributeNS(fullname.space, fullname.local); + }; + } + + function attrConstant$1(name, interpolate, value1) { + var string00, + string1 = value1 + "", + interpolate0; + return function () { + var string0 = this.getAttribute(name); + return string0 === string1 ? null + : string0 === string00 ? interpolate0 + : interpolate0 = interpolate(string00 = string0, value1); + }; + } + + function attrConstantNS$1(fullname, interpolate, value1) { + var string00, + string1 = value1 + "", + interpolate0; + return function () { + var string0 = this.getAttributeNS(fullname.space, fullname.local); + return string0 === string1 ? null + : string0 === string00 ? interpolate0 + : interpolate0 = interpolate(string00 = string0, value1); + }; + } + + function attrFunction$1(name, interpolate, value) { + var string00, + string10, + interpolate0; + return function () { + var string0, value1 = value(this), string1; + if (value1 == null) + return void this.removeAttribute(name); + string0 = this.getAttribute(name); + string1 = value1 + ""; + return string0 === string1 ? null + : string0 === string00 && string1 === string10 ? interpolate0 + : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + + function attrFunctionNS$1(fullname, interpolate, value) { + var string00, + string10, + interpolate0; + return function () { + var string0, value1 = value(this), string1; + if (value1 == null) + return void this.removeAttributeNS(fullname.space, fullname.local); + string0 = this.getAttributeNS(fullname.space, fullname.local); + string1 = value1 + ""; + return string0 === string1 ? null + : string0 === string00 && string1 === string10 ? interpolate0 + : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + + function transition_attr(name, value) { + var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate; + return this.attrTween(name, typeof value === "function" + ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value)) + : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname) + : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value)); + } + + function attrInterpolate(name, i) { + return function (t) { + this.setAttribute(name, i.call(this, t)); + }; + } + + function attrInterpolateNS(fullname, i) { + return function (t) { + this.setAttributeNS(fullname.space, fullname.local, i.call(this, t)); + }; + } + + function attrTweenNS(fullname, value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t0 = (i0 = i) && attrInterpolateNS(fullname, i); + return t0; + } + tween._value = value; + return tween; + } + + function attrTween(name, value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t0 = (i0 = i) && attrInterpolate(name, i); + return t0; + } + tween._value = value; + return tween; + } + + function transition_attrTween(name, value) { + var key = "attr." + name; + if (arguments.length < 2) + return (key = this.tween(key)) && key._value; + if (value == null) + return this.tween(key, null); + if (typeof value !== "function") + throw new Error; + var fullname = namespace(name); + return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); + } + + function delayFunction(id, value) { + return function () { + init(this, id).delay = +value.apply(this, arguments); + }; + } + + function delayConstant(id, value) { + return value = +value, function () { + init(this, id).delay = value; + }; + } + + function transition_delay(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? delayFunction + : delayConstant)(id, value)) + : get$1(this.node(), id).delay; + } + + function durationFunction(id, value) { + return function () { + set$1(this, id).duration = +value.apply(this, arguments); + }; + } + + function durationConstant(id, value) { + return value = +value, function () { + set$1(this, id).duration = value; + }; + } + + function transition_duration(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? durationFunction + : durationConstant)(id, value)) + : get$1(this.node(), id).duration; + } + + function easeConstant(id, value) { + if (typeof value !== "function") + throw new Error; + return function () { + set$1(this, id).ease = value; + }; + } + + function transition_ease(value) { + var id = this._id; + + return arguments.length + ? this.each(easeConstant(id, value)) + : get$1(this.node(), id).ease; + } + + function transition_filter(match) { + if (typeof match !== "function") + match = matcher(match); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + + return new Transition(subgroups, this._parents, this._name, this._id); + } + + function transition_merge(transition) { + if (transition._id !== this._id) + throw new Error; + + for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Transition(merges, this._parents, this._name, this._id); + } + + function start(name) { + return (name + "").trim().split(/^|\s+/).every(function (t) { + var i = t.indexOf("."); + if (i >= 0) + t = t.slice(0, i); + return !t || t === "start"; + }); + } + + function onFunction(id, name, listener) { + var on0, on1, sit = start(name) ? init : set$1; + return function () { + var schedule = sit(this, id), + on = schedule.on; + + // If this node shared a dispatch with the previous node, + // just assign the updated shared dispatch and we’re done! + // Otherwise, copy-on-write. + if (on !== on0) + (on1 = (on0 = on).copy()).on(name, listener); + + schedule.on = on1; + }; + } + + function transition_on(name, listener) { + var id = this._id; + + return arguments.length < 2 + ? get$1(this.node(), id).on.on(name) + : this.each(onFunction(id, name, listener)); + } + + function removeFunction(id) { + return function () { + var parent = this.parentNode; + for (var i in this.__transition) + if (+i !== id) + return; + if (parent) + parent.removeChild(this); + }; + } + + function transition_remove() { + return this.on("end.remove", removeFunction(this._id)); + } + + function transition_select(select) { + var name = this._name, + id = this._id; + + if (typeof select !== "function") + select = selector(select); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) + subnode.__data__ = node.__data__; + subgroup[i] = subnode; + schedule(subgroup[i], name, id, i, subgroup, get$1(node, id)); + } + } + } + + return new Transition(subgroups, this._parents, name, id); + } + + function transition_selectAll(select) { + var name = this._name, + id = this._id; + + if (typeof select !== "function") + select = selectorAll(select); + + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + for (var children = select.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) { + if (child = children[k]) { + schedule(child, name, id, k, children, inherit); + } + } + subgroups.push(children); + parents.push(node); + } + } + } + + return new Transition(subgroups, parents, name, id); + } + + var Selection$1 = selection.prototype.constructor; + + function transition_selection() { + return new Selection$1(this._groups, this._parents); + } + + function styleNull(name, interpolate) { + var string00, + string10, + interpolate0; + return function () { + var string0 = styleValue(this, name), + string1 = (this.style.removeProperty(name), styleValue(this, name)); + return string0 === string1 ? null + : string0 === string00 && string1 === string10 ? interpolate0 + : interpolate0 = interpolate(string00 = string0, string10 = string1); + }; + } + + function styleRemove$1(name) { + return function () { + this.style.removeProperty(name); + }; + } + + function styleConstant$1(name, interpolate, value1) { + var string00, + string1 = value1 + "", + interpolate0; + return function () { + var string0 = styleValue(this, name); + return string0 === string1 ? null + : string0 === string00 ? interpolate0 + : interpolate0 = interpolate(string00 = string0, value1); + }; + } + + function styleFunction$1(name, interpolate, value) { + var string00, + string10, + interpolate0; + return function () { + var string0 = styleValue(this, name), + value1 = value(this), + string1 = value1 + ""; + if (value1 == null) + string1 = value1 = (this.style.removeProperty(name), styleValue(this, name)); + return string0 === string1 ? null + : string0 === string00 && string1 === string10 ? interpolate0 + : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1)); + }; + } + + function styleMaybeRemove(id, name) { + var on0, on1, listener0, key = "style." + name, event = "end." + key, remove; + return function () { + var schedule = set$1(this, id), + on = schedule.on, + listener = schedule.value[key] == null ? remove || (remove = styleRemove$1(name)) : undefined; + + // If this node shared a dispatch with the previous node, + // just assign the updated shared dispatch and we’re done! + // Otherwise, copy-on-write. + if (on !== on0 || listener0 !== listener) + (on1 = (on0 = on).copy()).on(event, listener0 = listener); + + schedule.on = on1; + }; + } + + function transition_style(name, value, priority) { + var i = (name += "") === "transform" ? interpolateTransformCss : interpolate; + return value == null ? this + .styleTween(name, styleNull(name, i)) + .on("end.style." + name, styleRemove$1(name)) + : typeof value === "function" ? this + .styleTween(name, styleFunction$1(name, i, tweenValue(this, "style." + name, value))) + .each(styleMaybeRemove(this._id, name)) + : this + .styleTween(name, styleConstant$1(name, i, value), priority) + .on("end.style." + name, null); + } + + function styleInterpolate(name, i, priority) { + return function (t) { + this.style.setProperty(name, i.call(this, t), priority); + }; + } + + function styleTween(name, value, priority) { + var t, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t = (i0 = i) && styleInterpolate(name, i, priority); + return t; + } + tween._value = value; + return tween; + } + + function transition_styleTween(name, value, priority) { + var key = "style." + (name += ""); + if (arguments.length < 2) + return (key = this.tween(key)) && key._value; + if (value == null) + return this.tween(key, null); + if (typeof value !== "function") + throw new Error; + return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); + } + + function textConstant$1(value) { + return function () { + this.textContent = value; + }; + } + + function textFunction$1(value) { + return function () { + var value1 = value(this); + this.textContent = value1 == null ? "" : value1; + }; + } + + function transition_text(value) { + return this.tween("text", typeof value === "function" + ? textFunction$1(tweenValue(this, "text", value)) + : textConstant$1(value == null ? "" : value + "")); + } + + function textInterpolate(i) { + return function (t) { + this.textContent = i.call(this, t); + }; + } + + function textTween(value) { + var t0, i0; + function tween() { + var i = value.apply(this, arguments); + if (i !== i0) + t0 = (i0 = i) && textInterpolate(i); + return t0; + } + tween._value = value; + return tween; + } + + function transition_textTween(value) { + var key = "text"; + if (arguments.length < 1) + return (key = this.tween(key)) && key._value; + if (value == null) + return this.tween(key, null); + if (typeof value !== "function") + throw new Error; + return this.tween(key, textTween(value)); + } + + function transition_transition() { + var name = this._name, + id0 = this._id, + id1 = newId(); + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + var inherit = get$1(node, id0); + schedule(node, name, id1, i, group, { + time: inherit.time + inherit.delay + inherit.duration, + delay: 0, + duration: inherit.duration, + ease: inherit.ease + }); + } + } + } + + return new Transition(groups, this._parents, name, id1); + } + + function transition_end() { + var on0, on1, that = this, id = that._id, size = that.size(); + return new Promise(function (resolve, reject) { + var cancel = {value: reject}, + end = {value: function () { + if (--size === 0) + resolve(); + }}; + + that.each(function () { + var schedule = set$1(this, id), + on = schedule.on; + + // If this node shared a dispatch with the previous node, + // just assign the updated shared dispatch and we’re done! + // Otherwise, copy-on-write. + if (on !== on0) { + on1 = (on0 = on).copy(); + on1._.cancel.push(cancel); + on1._.interrupt.push(cancel); + on1._.end.push(end); + } + + schedule.on = on1; + }); + }); + } + + var id = 0; + + function Transition(groups, parents, name, id) { + this._groups = groups; + this._parents = parents; + this._name = name; + this._id = id; + } + + function transition(name) { + return selection().transition(name); + } + + function newId() { + return ++id; + } + + var selection_prototype = selection.prototype; + + Transition.prototype = transition.prototype = { + constructor: Transition, + select: transition_select, + selectAll: transition_selectAll, + filter: transition_filter, + merge: transition_merge, + selection: transition_selection, + transition: transition_transition, + call: selection_prototype.call, + nodes: selection_prototype.nodes, + node: selection_prototype.node, + size: selection_prototype.size, + empty: selection_prototype.empty, + each: selection_prototype.each, + on: transition_on, + attr: transition_attr, + attrTween: transition_attrTween, + style: transition_style, + styleTween: transition_styleTween, + text: transition_text, + textTween: transition_textTween, + remove: transition_remove, + tween: transition_tween, + delay: transition_delay, + duration: transition_duration, + ease: transition_ease, + end: transition_end + }; + + function linear$1(t) { + return +t; + } + + function quadIn(t) { + return t * t; + } + + function quadOut(t) { + return t * (2 - t); + } + + function quadInOut(t) { + return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2; + } + + function cubicIn(t) { + return t * t * t; + } + + function cubicOut(t) { + return --t * t * t + 1; + } + + function cubicInOut(t) { + return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; + } + + var exponent = 3; + + var polyIn = (function custom(e) { + e = +e; + + function polyIn(t) { + return Math.pow(t, e); + } + + polyIn.exponent = custom; + + return polyIn; + })(exponent); + + var polyOut = (function custom(e) { + e = +e; + + function polyOut(t) { + return 1 - Math.pow(1 - t, e); + } + + polyOut.exponent = custom; + + return polyOut; + })(exponent); + + var polyInOut = (function custom(e) { + e = +e; + + function polyInOut(t) { + return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2; + } + + polyInOut.exponent = custom; + + return polyInOut; + })(exponent); + + var pi = Math.PI, + halfPi = pi / 2; + + function sinIn(t) { + return 1 - Math.cos(t * halfPi); + } + + function sinOut(t) { + return Math.sin(t * halfPi); + } + + function sinInOut(t) { + return (1 - Math.cos(pi * t)) / 2; + } + + function expIn(t) { + return Math.pow(2, 10 * t - 10); + } + + function expOut(t) { + return 1 - Math.pow(2, -10 * t); + } + + function expInOut(t) { + return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2; + } + + function circleIn(t) { + return 1 - Math.sqrt(1 - t * t); + } + + function circleOut(t) { + return Math.sqrt(1 - --t * t); + } + + function circleInOut(t) { + return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2; + } + + var b1 = 4 / 11, + b2 = 6 / 11, + b3 = 8 / 11, + b4 = 3 / 4, + b5 = 9 / 11, + b6 = 10 / 11, + b7 = 15 / 16, + b8 = 21 / 22, + b9 = 63 / 64, + b0 = 1 / b1 / b1; + + function bounceIn(t) { + return 1 - bounceOut(1 - t); + } + + function bounceOut(t) { + return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : t < b6 ? b0 * (t -= b5) * t + b7 : b0 * (t -= b8) * t + b9; + } + + function bounceInOut(t) { + return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2; + } + + var overshoot = 1.70158; + + var backIn = (function custom(s) { + s = +s; + + function backIn(t) { + return t * t * ((s + 1) * t - s); + } + + backIn.overshoot = custom; + + return backIn; + })(overshoot); + + var backOut = (function custom(s) { + s = +s; + + function backOut(t) { + return --t * t * ((s + 1) * t + s) + 1; + } + + backOut.overshoot = custom; + + return backOut; + })(overshoot); + + var backInOut = (function custom(s) { + s = +s; + + function backInOut(t) { + return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2; + } + + backInOut.overshoot = custom; + + return backInOut; + })(overshoot); + + var tau = 2 * Math.PI, + amplitude = 1, + period = 0.3; + + var elasticIn = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticIn(t) { + return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p); + } + + elasticIn.amplitude = function (a) { + return custom(a, p * tau); + }; + elasticIn.period = function (p) { + return custom(a, p); + }; + + return elasticIn; + })(amplitude, period); + + var elasticOut = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticOut(t) { + return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p); + } + + elasticOut.amplitude = function (a) { + return custom(a, p * tau); + }; + elasticOut.period = function (p) { + return custom(a, p); + }; + + return elasticOut; + })(amplitude, period); + + var elasticInOut = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticInOut(t) { + return ((t = t * 2 - 1) < 0 + ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p) + : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2; + } + + elasticInOut.amplitude = function (a) { + return custom(a, p * tau); + }; + elasticInOut.period = function (p) { + return custom(a, p); + }; + + return elasticInOut; + })(amplitude, period); + + var defaultTiming = { + time: null, // Set on use. + delay: 0, + duration: 250, + ease: cubicInOut + }; + + function inherit(node, id) { + var timing; + while (!(timing = node.__transition) || !(timing = timing[id])) { + if (!(node = node.parentNode)) { + return defaultTiming.time = now(), defaultTiming; + } + } + return timing; + } + + function selection_transition(name) { + var id, + timing; + + if (name instanceof Transition) { + id = name._id, name = name._name; + } else { + id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + ""; + } + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + schedule(node, name, id, i, group, timing || inherit(node, id)); + } + } + } + + return new Transition(groups, this._parents, name, id); + } + + selection.prototype.interrupt = selection_interrupt; + selection.prototype.transition = selection_transition; + + var root$1 = [null]; + + function active(node, name) { + var schedules = node.__transition, + schedule, + i; + + if (schedules) { + name = name == null ? null : name + ""; + for (i in schedules) { + if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) { + return new Transition([[node]], root$1, name, +i); + } + } + } + + return null; + } + + function constant$4(x) { + return function () { + return x; + }; + } + + function BrushEvent(target, type, selection) { + this.target = target; + this.type = type; + this.selection = selection; + } + + function nopropagation$1() { + exports.event.stopImmediatePropagation(); + } + + function noevent$1() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); + } + + var MODE_DRAG = {name: "drag"}, + MODE_SPACE = {name: "space"}, + MODE_HANDLE = {name: "handle"}, + MODE_CENTER = {name: "center"}; + + function number1(e) { + return [+e[0], +e[1]]; + } + + function number2(e) { + return [number1(e[0]), number1(e[1])]; + } + + function toucher(identifier) { + return function (target) { + return touch(target, exports.event.touches, identifier); + }; + } + + var X = { + name: "x", + handles: ["w", "e"].map(type), + input: function (x, e) { + return x == null ? null : [[+x[0], e[0][1]], [+x[1], e[1][1]]]; + }, + output: function (xy) { + return xy && [xy[0][0], xy[1][0]]; + } + }; + + var Y = { + name: "y", + handles: ["n", "s"].map(type), + input: function (y, e) { + return y == null ? null : [[e[0][0], +y[0]], [e[1][0], +y[1]]]; + }, + output: function (xy) { + return xy && [xy[0][1], xy[1][1]]; + } + }; + + var XY = { + name: "xy", + handles: ["n", "w", "e", "s", "nw", "ne", "sw", "se"].map(type), + input: function (xy) { + return xy == null ? null : number2(xy); + }, + output: function (xy) { + return xy; + } + }; + + var cursors = { + overlay: "crosshair", + selection: "move", + n: "ns-resize", + e: "ew-resize", + s: "ns-resize", + w: "ew-resize", + nw: "nwse-resize", + ne: "nesw-resize", + se: "nwse-resize", + sw: "nesw-resize" + }; + + var flipX = { + e: "w", + w: "e", + nw: "ne", + ne: "nw", + se: "sw", + sw: "se" + }; + + var flipY = { + n: "s", + s: "n", + nw: "sw", + ne: "se", + se: "ne", + sw: "nw" + }; + + var signsX = { + overlay: +1, + selection: +1, + n: null, + e: +1, + s: null, + w: -1, + nw: -1, + ne: +1, + se: +1, + sw: -1 + }; + + var signsY = { + overlay: +1, + selection: +1, + n: -1, + e: null, + s: +1, + w: null, + nw: -1, + ne: -1, + se: +1, + sw: +1 + }; + + function type(t) { + return {type: t}; + } + +// Ignore right-click, since that should open the context menu. + function defaultFilter$1() { + return !exports.event.ctrlKey && !exports.event.button; + } + + function defaultExtent() { + var svg = this.ownerSVGElement || this; + if (svg.hasAttribute("viewBox")) { + svg = svg.viewBox.baseVal; + return [[svg.x, svg.y], [svg.x + svg.width, svg.y + svg.height]]; + } + return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]]; + } + + function defaultTouchable$1() { + return navigator.maxTouchPoints || ("ontouchstart" in this); + } + +// Like d3.local, but with the name “__brush” rather than auto-generated. + function local$1(node) { + while (!node.__brush) + if (!(node = node.parentNode)) + return; + return node.__brush; + } + + function empty$1(extent) { + return extent[0][0] === extent[1][0] + || extent[0][1] === extent[1][1]; + } + + function brushSelection(node) { + var state = node.__brush; + return state ? state.dim.output(state.selection) : null; + } + + function brushX() { + return brush$1(X); + } + + function brushY() { + return brush$1(Y); + } + + function brush() { + return brush$1(XY); + } + + function brush$1(dim) { + var extent = defaultExtent, + filter = defaultFilter$1, + touchable = defaultTouchable$1, + keys = true, + listeners = dispatch("start", "brush", "end"), + handleSize = 6, + touchending; + + function brush(group) { + var overlay = group + .property("__brush", initialize) + .selectAll(".overlay") + .data([type("overlay")]); + + overlay.enter().append("rect") + .attr("class", "overlay") + .attr("pointer-events", "all") + .attr("cursor", cursors.overlay) + .merge(overlay) + .each(function () { + var extent = local$1(this).extent; + select(this) + .attr("x", extent[0][0]) + .attr("y", extent[0][1]) + .attr("width", extent[1][0] - extent[0][0]) + .attr("height", extent[1][1] - extent[0][1]); + }); + + group.selectAll(".selection") + .data([type("selection")]) + .enter().append("rect") + .attr("class", "selection") + .attr("cursor", cursors.selection) + .attr("fill", "#777") + .attr("fill-opacity", 0.3) + .attr("stroke", "#fff") + .attr("shape-rendering", "crispEdges"); + + var handle = group.selectAll(".handle") + .data(dim.handles, function (d) { + return d.type; + }); + + handle.exit().remove(); + + handle.enter().append("rect") + .attr("class", function (d) { + return "handle handle--" + d.type; + }) + .attr("cursor", function (d) { + return cursors[d.type]; + }); + + group + .each(redraw) + .attr("fill", "none") + .attr("pointer-events", "all") + .on("mousedown.brush", started) + .filter(touchable) + .on("touchstart.brush", started) + .on("touchmove.brush", touchmoved) + .on("touchend.brush touchcancel.brush", touchended) + .style("touch-action", "none") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + + brush.move = function (group, selection) { + if (group.selection) { + group + .on("start.brush", function () { + emitter(this, arguments).beforestart().start(); + }) + .on("interrupt.brush end.brush", function () { + emitter(this, arguments).end(); + }) + .tween("brush", function () { + var that = this, + state = that.__brush, + emit = emitter(that, arguments), + selection0 = state.selection, + selection1 = dim.input(typeof selection === "function" ? selection.apply(this, arguments) : selection, state.extent), + i = interpolateValue(selection0, selection1); + + function tween(t) { + state.selection = t === 1 && selection1 === null ? null : i(t); + redraw.call(that); + emit.brush(); + } + + return selection0 !== null && selection1 !== null ? tween : tween(1); + }); + } else { + group + .each(function () { + var that = this, + args = arguments, + state = that.__brush, + selection1 = dim.input(typeof selection === "function" ? selection.apply(that, args) : selection, state.extent), + emit = emitter(that, args).beforestart(); + + interrupt(that); + state.selection = selection1 === null ? null : selection1; + redraw.call(that); + emit.start().brush().end(); + }); + } + }; + + brush.clear = function (group) { + brush.move(group, null); + }; + + function redraw() { + var group = select(this), + selection = local$1(this).selection; + + if (selection) { + group.selectAll(".selection") + .style("display", null) + .attr("x", selection[0][0]) + .attr("y", selection[0][1]) + .attr("width", selection[1][0] - selection[0][0]) + .attr("height", selection[1][1] - selection[0][1]); + + group.selectAll(".handle") + .style("display", null) + .attr("x", function (d) { + return d.type[d.type.length - 1] === "e" ? selection[1][0] - handleSize / 2 : selection[0][0] - handleSize / 2; + }) + .attr("y", function (d) { + return d.type[0] === "s" ? selection[1][1] - handleSize / 2 : selection[0][1] - handleSize / 2; + }) + .attr("width", function (d) { + return d.type === "n" || d.type === "s" ? selection[1][0] - selection[0][0] + handleSize : handleSize; + }) + .attr("height", function (d) { + return d.type === "e" || d.type === "w" ? selection[1][1] - selection[0][1] + handleSize : handleSize; + }); + } else { + group.selectAll(".selection,.handle") + .style("display", "none") + .attr("x", null) + .attr("y", null) + .attr("width", null) + .attr("height", null); + } + } + + function emitter(that, args, clean) { + return (!clean && that.__brush.emitter) || new Emitter(that, args); + } + + function Emitter(that, args) { + this.that = that; + this.args = args; + this.state = that.__brush; + this.active = 0; + } + + Emitter.prototype = { + beforestart: function () { + if (++this.active === 1) + this.state.emitter = this, this.starting = true; + return this; + }, + start: function () { + if (this.starting) + this.starting = false, this.emit("start"); + else + this.emit("brush"); + return this; + }, + brush: function () { + this.emit("brush"); + return this; + }, + end: function () { + if (--this.active === 0) + delete this.state.emitter, this.emit("end"); + return this; + }, + emit: function (type) { + customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]); + } + }; + + function started() { + if (touchending && !exports.event.touches) + return; + if (!filter.apply(this, arguments)) + return; + + var that = this, + type = exports.event.target.__data__.type, + mode = (keys && exports.event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (keys && exports.event.altKey ? MODE_CENTER : MODE_HANDLE), + signX = dim === Y ? null : signsX[type], + signY = dim === X ? null : signsY[type], + state = local$1(that), + extent = state.extent, + selection = state.selection, + W = extent[0][0], w0, w1, + N = extent[0][1], n0, n1, + E = extent[1][0], e0, e1, + S = extent[1][1], s0, s1, + dx = 0, + dy = 0, + moving, + shifting = signX && signY && keys && exports.event.shiftKey, + lockX, + lockY, + pointer = exports.event.touches ? toucher(exports.event.changedTouches[0].identifier) : mouse, + point0 = pointer(that), + point = point0, + emit = emitter(that, arguments, true).beforestart(); + + if (type === "overlay") { + if (selection) + moving = true; + state.selection = selection = [ + [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]], + [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0] + ]; + } else { + w0 = selection[0][0]; + n0 = selection[0][1]; + e0 = selection[1][0]; + s0 = selection[1][1]; + } + + w1 = w0; + n1 = n0; + e1 = e0; + s1 = s0; + + var group = select(that) + .attr("pointer-events", "none"); + + var overlay = group.selectAll(".overlay") + .attr("cursor", cursors[type]); + + if (exports.event.touches) { + emit.moved = moved; + emit.ended = ended; + } else { + var view = select(exports.event.view) + .on("mousemove.brush", moved, true) + .on("mouseup.brush", ended, true); + if (keys) + view + .on("keydown.brush", keydowned, true) + .on("keyup.brush", keyupped, true); + + dragDisable(exports.event.view); + } + + nopropagation$1(); + interrupt(that); + redraw.call(that); + emit.start(); + + function moved() { + var point1 = pointer(that); + if (shifting && !lockX && !lockY) { + if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) + lockY = true; + else + lockX = true; + } + point = point1; + moving = true; + noevent$1(); + move(); + } + + function move() { + var t; + + dx = point[0] - point0[0]; + dy = point[1] - point0[1]; + + switch (mode) { + case MODE_SPACE: + case MODE_DRAG: + { + if (signX) + dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx; + if (signY) + dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy; + break; + } + case MODE_HANDLE: + { + if (signX < 0) + dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0; + else if (signX > 0) + dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx; + if (signY < 0) + dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0; + else if (signY > 0) + dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy; + break; + } + case MODE_CENTER: + { + if (signX) + w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX)); + if (signY) + n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY)); + break; + } + } + + if (e1 < w1) { + signX *= -1; + t = w0, w0 = e0, e0 = t; + t = w1, w1 = e1, e1 = t; + if (type in flipX) + overlay.attr("cursor", cursors[type = flipX[type]]); + } + + if (s1 < n1) { + signY *= -1; + t = n0, n0 = s0, s0 = t; + t = n1, n1 = s1, s1 = t; + if (type in flipY) + overlay.attr("cursor", cursors[type = flipY[type]]); + } + + if (state.selection) + selection = state.selection; // May be set by brush.move! + if (lockX) + w1 = selection[0][0], e1 = selection[1][0]; + if (lockY) + n1 = selection[0][1], s1 = selection[1][1]; + + if (selection[0][0] !== w1 + || selection[0][1] !== n1 + || selection[1][0] !== e1 + || selection[1][1] !== s1) { + state.selection = [[w1, n1], [e1, s1]]; + redraw.call(that); + emit.brush(); + } + } + + function ended() { + nopropagation$1(); + if (exports.event.touches) { + if (exports.event.touches.length) + return; + if (touchending) + clearTimeout(touchending); + touchending = setTimeout(function () { + touchending = null; + }, 500); // Ghost clicks are delayed! + } else { + yesdrag(exports.event.view, moving); + view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null); + } + group.attr("pointer-events", "all"); + overlay.attr("cursor", cursors.overlay); + if (state.selection) + selection = state.selection; // May be set by brush.move (on start)! + if (empty$1(selection)) + state.selection = null, redraw.call(that); + emit.end(); + } + + function keydowned() { + switch (exports.event.keyCode) { + case 16: + { // SHIFT + shifting = signX && signY; + break; + } + case 18: + { // ALT + if (mode === MODE_HANDLE) { + if (signX) + e0 = e1 - dx * signX, w0 = w1 + dx * signX; + if (signY) + s0 = s1 - dy * signY, n0 = n1 + dy * signY; + mode = MODE_CENTER; + move(); + } + break; + } + case 32: + { // SPACE; takes priority over ALT + if (mode === MODE_HANDLE || mode === MODE_CENTER) { + if (signX < 0) + e0 = e1 - dx; + else if (signX > 0) + w0 = w1 - dx; + if (signY < 0) + s0 = s1 - dy; + else if (signY > 0) + n0 = n1 - dy; + mode = MODE_SPACE; + overlay.attr("cursor", cursors.selection); + move(); + } + break; + } + default: + return; + } + noevent$1(); + } + + function keyupped() { + switch (exports.event.keyCode) { + case 16: + { // SHIFT + if (shifting) { + lockX = lockY = shifting = false; + move(); + } + break; + } + case 18: + { // ALT + if (mode === MODE_CENTER) { + if (signX < 0) + e0 = e1; + else if (signX > 0) + w0 = w1; + if (signY < 0) + s0 = s1; + else if (signY > 0) + n0 = n1; + mode = MODE_HANDLE; + move(); + } + break; + } + case 32: + { // SPACE + if (mode === MODE_SPACE) { + if (exports.event.altKey) { + if (signX) + e0 = e1 - dx * signX, w0 = w1 + dx * signX; + if (signY) + s0 = s1 - dy * signY, n0 = n1 + dy * signY; + mode = MODE_CENTER; + } else { + if (signX < 0) + e0 = e1; + else if (signX > 0) + w0 = w1; + if (signY < 0) + s0 = s1; + else if (signY > 0) + n0 = n1; + mode = MODE_HANDLE; + } + overlay.attr("cursor", cursors[type]); + move(); + } + break; + } + default: + return; + } + noevent$1(); + } + } + + function touchmoved() { + emitter(this, arguments).moved(); + } + + function touchended() { + emitter(this, arguments).ended(); + } + + function initialize() { + var state = this.__brush || {selection: null}; + state.extent = number2(extent.apply(this, arguments)); + state.dim = dim; + return state; + } + + brush.extent = function (_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant$4(number2(_)), brush) : extent; + }; + + brush.filter = function (_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$4(!!_), brush) : filter; + }; + + brush.touchable = function (_) { + return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$4(!!_), brush) : touchable; + }; + + brush.handleSize = function (_) { + return arguments.length ? (handleSize = +_, brush) : handleSize; + }; + + brush.keyModifiers = function (_) { + return arguments.length ? (keys = !!_, brush) : keys; + }; + + brush.on = function () { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? brush : value; + }; + + return brush; + } + + var cos = Math.cos; + var sin = Math.sin; + var pi$1 = Math.PI; + var halfPi$1 = pi$1 / 2; + var tau$1 = pi$1 * 2; + var max$1 = Math.max; + + function compareValue(compare) { + return function (a, b) { + return compare( + a.source.value + a.target.value, + b.source.value + b.target.value + ); + }; + } + + function chord() { + var padAngle = 0, + sortGroups = null, + sortSubgroups = null, + sortChords = null; + + function chord(matrix) { + var n = matrix.length, + groupSums = [], + groupIndex = sequence(n), + subgroupIndex = [], + chords = [], + groups = chords.groups = new Array(n), + subgroups = new Array(n * n), + k, + x, + x0, + dx, + i, + j; + + // Compute the sum. + k = 0, i = -1; + while (++i < n) { + x = 0, j = -1; + while (++j < n) { + x += matrix[i][j]; + } + groupSums.push(x); + subgroupIndex.push(sequence(n)); + k += x; + } + + // Sort groups… + if (sortGroups) + groupIndex.sort(function (a, b) { + return sortGroups(groupSums[a], groupSums[b]); + }); + + // Sort subgroups… + if (sortSubgroups) + subgroupIndex.forEach(function (d, i) { + d.sort(function (a, b) { + return sortSubgroups(matrix[i][a], matrix[i][b]); + }); + }); + + // Convert the sum to scaling factor for [0, 2pi]. + // TODO Allow start and end angle to be specified? + // TODO Allow padding to be specified as percentage? + k = max$1(0, tau$1 - padAngle * n) / k; + dx = k ? padAngle : tau$1 / n; + + // Compute the start and end angle for each group and subgroup. + // Note: Opera has a bug reordering object literal properties! + x = 0, i = -1; + while (++i < n) { + x0 = x, j = -1; + while (++j < n) { + var di = groupIndex[i], + dj = subgroupIndex[di][j], + v = matrix[di][dj], + a0 = x, + a1 = x += v * k; + subgroups[dj * n + di] = { + index: di, + subindex: dj, + startAngle: a0, + endAngle: a1, + value: v + }; + } + groups[di] = { + index: di, + startAngle: x0, + endAngle: x, + value: groupSums[di] + }; + x += dx; + } + + // Generate chords for each (non-empty) subgroup-subgroup link. + i = -1; + while (++i < n) { + j = i - 1; + while (++j < n) { + var source = subgroups[j * n + i], + target = subgroups[i * n + j]; + if (source.value || target.value) { + chords.push(source.value < target.value + ? {source: target, target: source} + : {source: source, target: target}); + } + } + } + + return sortChords ? chords.sort(sortChords) : chords; + } + + chord.padAngle = function (_) { + return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle; + }; + + chord.sortGroups = function (_) { + return arguments.length ? (sortGroups = _, chord) : sortGroups; + }; + + chord.sortSubgroups = function (_) { + return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups; + }; + + chord.sortChords = function (_) { + return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._; + }; + + return chord; + } + + var slice$2 = Array.prototype.slice; + + function constant$5(x) { + return function () { + return x; + }; + } + + var pi$2 = Math.PI, + tau$2 = 2 * pi$2, + epsilon$1 = 1e-6, + tauEpsilon = tau$2 - epsilon$1; + + function Path() { + this._x0 = this._y0 = // start of current subpath + this._x1 = this._y1 = null; // end of current subpath + this._ = ""; + } + + function path() { + return new Path; + } + + Path.prototype = path.prototype = { + constructor: Path, + moveTo: function (x, y) { + this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y); + }, + closePath: function () { + if (this._x1 !== null) { + this._x1 = this._x0, this._y1 = this._y0; + this._ += "Z"; + } + }, + lineTo: function (x, y) { + this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y); + }, + quadraticCurveTo: function (x1, y1, x, y) { + this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y); + }, + bezierCurveTo: function (x1, y1, x2, y2, x, y) { + this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y); + }, + arcTo: function (x1, y1, x2, y2, r) { + x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r; + var x0 = this._x1, + y0 = this._y1, + x21 = x2 - x1, + y21 = y2 - y1, + x01 = x0 - x1, + y01 = y0 - y1, + l01_2 = x01 * x01 + y01 * y01; + + // Is the radius negative? Error. + if (r < 0) + throw new Error("negative radius: " + r); + + // Is this path empty? Move to (x1,y1). + if (this._x1 === null) { + this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1); + } + + // Or, is (x1,y1) coincident with (x0,y0)? Do nothing. + else if (!(l01_2 > epsilon$1)) + ; + + // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear? + // Equivalently, is (x1,y1) coincident with (x2,y2)? + // Or, is the radius zero? Line to (x1,y1). + else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon$1) || !r) { + this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1); + } + + // Otherwise, draw an arc! + else { + var x20 = x2 - x0, + y20 = y2 - y0, + l21_2 = x21 * x21 + y21 * y21, + l20_2 = x20 * x20 + y20 * y20, + l21 = Math.sqrt(l21_2), + l01 = Math.sqrt(l01_2), + l = r * Math.tan((pi$2 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), + t01 = l / l01, + t21 = l / l21; + + // If the start tangent is not coincident with (x0,y0), line to. + if (Math.abs(t01 - 1) > epsilon$1) { + this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01); + } + + this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21); + } + }, + arc: function (x, y, r, a0, a1, ccw) { + x = +x, y = +y, r = +r, ccw = !!ccw; + var dx = r * Math.cos(a0), + dy = r * Math.sin(a0), + x0 = x + dx, + y0 = y + dy, + cw = 1 ^ ccw, + da = ccw ? a0 - a1 : a1 - a0; + + // Is the radius negative? Error. + if (r < 0) + throw new Error("negative radius: " + r); + + // Is this path empty? Move to (x0,y0). + if (this._x1 === null) { + this._ += "M" + x0 + "," + y0; + } + + // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). + else if (Math.abs(this._x1 - x0) > epsilon$1 || Math.abs(this._y1 - y0) > epsilon$1) { + this._ += "L" + x0 + "," + y0; + } + + // Is this arc empty? We’re done. + if (!r) + return; + + // Does the angle go the wrong way? Flip the direction. + if (da < 0) + da = da % tau$2 + tau$2; + + // Is this a complete circle? Draw two arcs to complete the circle. + if (da > tauEpsilon) { + this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0); + } + + // Is this arc non-empty? Draw an arc! + else if (da > epsilon$1) { + this._ += "A" + r + "," + r + ",0," + (+(da >= pi$2)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1)); + } + }, + rect: function (x, y, w, h) { + this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z"; + }, + toString: function () { + return this._; + } + }; + + function defaultSource(d) { + return d.source; + } + + function defaultTarget(d) { + return d.target; + } + + function defaultRadius(d) { + return d.radius; + } + + function defaultStartAngle(d) { + return d.startAngle; + } + + function defaultEndAngle(d) { + return d.endAngle; + } + + function ribbon() { + var source = defaultSource, + target = defaultTarget, + radius = defaultRadius, + startAngle = defaultStartAngle, + endAngle = defaultEndAngle, + context = null; + + function ribbon() { + var buffer, + argv = slice$2.call(arguments), + s = source.apply(this, argv), + t = target.apply(this, argv), + sr = +radius.apply(this, (argv[0] = s, argv)), + sa0 = startAngle.apply(this, argv) - halfPi$1, + sa1 = endAngle.apply(this, argv) - halfPi$1, + sx0 = sr * cos(sa0), + sy0 = sr * sin(sa0), + tr = +radius.apply(this, (argv[0] = t, argv)), + ta0 = startAngle.apply(this, argv) - halfPi$1, + ta1 = endAngle.apply(this, argv) - halfPi$1; + + if (!context) + context = buffer = path(); + + context.moveTo(sx0, sy0); + context.arc(0, 0, sr, sa0, sa1); + if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr? + context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0)); + context.arc(0, 0, tr, ta0, ta1); + } + context.quadraticCurveTo(0, 0, sx0, sy0); + context.closePath(); + + if (buffer) + return context = null, buffer + "" || null; + } + + ribbon.radius = function (_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$5(+_), ribbon) : radius; + }; + + ribbon.startAngle = function (_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : startAngle; + }; + + ribbon.endAngle = function (_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$5(+_), ribbon) : endAngle; + }; + + ribbon.source = function (_) { + return arguments.length ? (source = _, ribbon) : source; + }; + + ribbon.target = function (_) { + return arguments.length ? (target = _, ribbon) : target; + }; + + ribbon.context = function (_) { + return arguments.length ? ((context = _ == null ? null : _), ribbon) : context; + }; + + return ribbon; + } + + var prefix = "$"; + + function Map() {} + + Map.prototype = map$1.prototype = { + constructor: Map, + has: function (key) { + return (prefix + key) in this; + }, + get: function (key) { + return this[prefix + key]; + }, + set: function (key, value) { + this[prefix + key] = value; + return this; + }, + remove: function (key) { + var property = prefix + key; + return property in this && delete this[property]; + }, + clear: function () { + for (var property in this) + if (property[0] === prefix) + delete this[property]; + }, + keys: function () { + var keys = []; + for (var property in this) + if (property[0] === prefix) + keys.push(property.slice(1)); + return keys; + }, + values: function () { + var values = []; + for (var property in this) + if (property[0] === prefix) + values.push(this[property]); + return values; + }, + entries: function () { + var entries = []; + for (var property in this) + if (property[0] === prefix) + entries.push({key: property.slice(1), value: this[property]}); + return entries; + }, + size: function () { + var size = 0; + for (var property in this) + if (property[0] === prefix) + ++size; + return size; + }, + empty: function () { + for (var property in this) + if (property[0] === prefix) + return false; + return true; + }, + each: function (f) { + for (var property in this) + if (property[0] === prefix) + f(this[property], property.slice(1), this); + } + }; + + function map$1(object, f) { + var map = new Map; + + // Copy constructor. + if (object instanceof Map) + object.each(function (value, key) { + map.set(key, value); + }); + + // Index array by numeric index or specified key function. + else if (Array.isArray(object)) { + var i = -1, + n = object.length, + o; + + if (f == null) + while (++i < n) + map.set(i, object[i]); + else + while (++i < n) + map.set(f(o = object[i], i, object), o); + } + + // Convert object to map. + else if (object) + for (var key in object) + map.set(key, object[key]); + + return map; + } + + function nest() { + var keys = [], + sortKeys = [], + sortValues, + rollup, + nest; + + function apply(array, depth, createResult, setResult) { + if (depth >= keys.length) { + if (sortValues != null) + array.sort(sortValues); + return rollup != null ? rollup(array) : array; + } + + var i = -1, + n = array.length, + key = keys[depth++], + keyValue, + value, + valuesByKey = map$1(), + values, + result = createResult(); + + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { + values.push(value); + } else { + valuesByKey.set(keyValue, [value]); + } + } + + valuesByKey.each(function (values, key) { + setResult(result, key, apply(values, depth, createResult, setResult)); + }); + + return result; + } + + function entries(map, depth) { + if (++depth > keys.length) + return map; + var array, sortKey = sortKeys[depth - 1]; + if (rollup != null && depth >= keys.length) + array = map.entries(); + else + array = [], map.each(function (v, k) { + array.push({key: k, values: entries(v, depth)}); + }); + return sortKey != null ? array.sort(function (a, b) { + return sortKey(a.key, b.key); + }) : array; + } + + return nest = { + object: function (array) { + return apply(array, 0, createObject, setObject); + }, + map: function (array) { + return apply(array, 0, createMap, setMap); + }, + entries: function (array) { + return entries(apply(array, 0, createMap, setMap), 0); + }, + key: function (d) { + keys.push(d); + return nest; + }, + sortKeys: function (order) { + sortKeys[keys.length - 1] = order; + return nest; + }, + sortValues: function (order) { + sortValues = order; + return nest; + }, + rollup: function (f) { + rollup = f; + return nest; + } + }; + } + + function createObject() { + return {}; + } + + function setObject(object, key, value) { + object[key] = value; + } + + function createMap() { + return map$1(); + } + + function setMap(map, key, value) { + map.set(key, value); + } + + function Set() {} + + var proto = map$1.prototype; + + Set.prototype = set$2.prototype = { + constructor: Set, + has: proto.has, + add: function (value) { + value += ""; + this[prefix + value] = value; + return this; + }, + remove: proto.remove, + clear: proto.clear, + values: proto.keys, + size: proto.size, + empty: proto.empty, + each: proto.each + }; + + function set$2(object, f) { + var set = new Set; + + // Copy constructor. + if (object instanceof Set) + object.each(function (value) { + set.add(value); + }); + + // Otherwise, assume it’s an array. + else if (object) { + var i = -1, n = object.length; + if (f == null) + while (++i < n) + set.add(object[i]); + else + while (++i < n) + set.add(f(object[i], i, object)); + } + + return set; + } + + function keys(map) { + var keys = []; + for (var key in map) + keys.push(key); + return keys; + } + + function values(map) { + var values = []; + for (var key in map) + values.push(map[key]); + return values; + } + + function entries(map) { + var entries = []; + for (var key in map) + entries.push({key: key, value: map[key]}); + return entries; + } + + var array$2 = Array.prototype; + + var slice$3 = array$2.slice; + + function ascending$2(a, b) { + return a - b; + } + + function area(ring) { + var i = 0, n = ring.length, area = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1]; + while (++i < n) + area += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1]; + return area; + } + + function constant$6(x) { + return function () { + return x; + }; + } + + function contains(ring, hole) { + var i = -1, n = hole.length, c; + while (++i < n) + if (c = ringContains(ring, hole[i])) + return c; + return 0; + } + + function ringContains(ring, point) { + var x = point[0], y = point[1], contains = -1; + for (var i = 0, n = ring.length, j = n - 1; i < n; j = i++) { + var pi = ring[i], xi = pi[0], yi = pi[1], pj = ring[j], xj = pj[0], yj = pj[1]; + if (segmentContains(pi, pj, point)) + return 0; + if (((yi > y) !== (yj > y)) && ((x < (xj - xi) * (y - yi) / (yj - yi) + xi))) + contains = -contains; + } + return contains; + } + + function segmentContains(a, b, c) { + var i; + return collinear(a, b, c) && within(a[i = +(a[0] === b[0])], c[i], b[i]); + } + + function collinear(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) === (c[0] - a[0]) * (b[1] - a[1]); + } + + function within(p, q, r) { + return p <= q && q <= r || r <= q && q <= p; + } + + function noop$1() {} + + var cases = [ + [], + [[[1.0, 1.5], [0.5, 1.0]]], + [[[1.5, 1.0], [1.0, 1.5]]], + [[[1.5, 1.0], [0.5, 1.0]]], + [[[1.0, 0.5], [1.5, 1.0]]], + [[[1.0, 1.5], [0.5, 1.0]], [[1.0, 0.5], [1.5, 1.0]]], + [[[1.0, 0.5], [1.0, 1.5]]], + [[[1.0, 0.5], [0.5, 1.0]]], + [[[0.5, 1.0], [1.0, 0.5]]], + [[[1.0, 1.5], [1.0, 0.5]]], + [[[0.5, 1.0], [1.0, 0.5]], [[1.5, 1.0], [1.0, 1.5]]], + [[[1.5, 1.0], [1.0, 0.5]]], + [[[0.5, 1.0], [1.5, 1.0]]], + [[[1.0, 1.5], [1.5, 1.0]]], + [[[0.5, 1.0], [1.0, 1.5]]], + [] + ]; + + function contours() { + var dx = 1, + dy = 1, + threshold = thresholdSturges, + smooth = smoothLinear; + + function contours(values) { + var tz = threshold(values); + + // Convert number of thresholds into uniform thresholds. + if (!Array.isArray(tz)) { + var domain = extent(values), start = domain[0], stop = domain[1]; + tz = tickStep(start, stop, tz); + tz = sequence(Math.floor(start / tz) * tz, Math.floor(stop / tz) * tz, tz); + } else { + tz = tz.slice().sort(ascending$2); + } + + return tz.map(function (value) { + return contour(values, value); + }); + } + + // Accumulate, smooth contour rings, assign holes to exterior rings. + // Based on https://github.com/mbostock/shapefile/blob/v0.6.2/shp/polygon.js + function contour(values, value) { + var polygons = [], + holes = []; + + isorings(values, value, function (ring) { + smooth(ring, values, value); + if (area(ring) > 0) + polygons.push([ring]); + else + holes.push(ring); + }); + + holes.forEach(function (hole) { + for (var i = 0, n = polygons.length, polygon; i < n; ++i) { + if (contains((polygon = polygons[i])[0], hole) !== -1) { + polygon.push(hole); + return; + } + } + }); + + return { + type: "MultiPolygon", + value: value, + coordinates: polygons + }; + } + + // Marching squares with isolines stitched into rings. + // Based on https://github.com/topojson/topojson-client/blob/v3.0.0/src/stitch.js + function isorings(values, value, callback) { + var fragmentByStart = new Array, + fragmentByEnd = new Array, + x, y, t0, t1, t2, t3; + + // Special case for the first row (y = -1, t2 = t3 = 0). + x = y = -1; + t1 = values[0] >= value; + cases[t1 << 1].forEach(stitch); + while (++x < dx - 1) { + t0 = t1, t1 = values[x + 1] >= value; + cases[t0 | t1 << 1].forEach(stitch); + } + cases[t1 << 0].forEach(stitch); + + // General case for the intermediate rows. + while (++y < dy - 1) { + x = -1; + t1 = values[y * dx + dx] >= value; + t2 = values[y * dx] >= value; + cases[t1 << 1 | t2 << 2].forEach(stitch); + while (++x < dx - 1) { + t0 = t1, t1 = values[y * dx + dx + x + 1] >= value; + t3 = t2, t2 = values[y * dx + x + 1] >= value; + cases[t0 | t1 << 1 | t2 << 2 | t3 << 3].forEach(stitch); + } + cases[t1 | t2 << 3].forEach(stitch); + } + + // Special case for the last row (y = dy - 1, t0 = t1 = 0). + x = -1; + t2 = values[y * dx] >= value; + cases[t2 << 2].forEach(stitch); + while (++x < dx - 1) { + t3 = t2, t2 = values[y * dx + x + 1] >= value; + cases[t2 << 2 | t3 << 3].forEach(stitch); + } + cases[t2 << 3].forEach(stitch); + + function stitch(line) { + var start = [line[0][0] + x, line[0][1] + y], + end = [line[1][0] + x, line[1][1] + y], + startIndex = index(start), + endIndex = index(end), + f, g; + if (f = fragmentByEnd[startIndex]) { + if (g = fragmentByStart[endIndex]) { + delete fragmentByEnd[f.end]; + delete fragmentByStart[g.start]; + if (f === g) { + f.ring.push(end); + callback(f.ring); + } else { + fragmentByStart[f.start] = fragmentByEnd[g.end] = {start: f.start, end: g.end, ring: f.ring.concat(g.ring)}; + } + } else { + delete fragmentByEnd[f.end]; + f.ring.push(end); + fragmentByEnd[f.end = endIndex] = f; + } + } else if (f = fragmentByStart[endIndex]) { + if (g = fragmentByEnd[startIndex]) { + delete fragmentByStart[f.start]; + delete fragmentByEnd[g.end]; + if (f === g) { + f.ring.push(end); + callback(f.ring); + } else { + fragmentByStart[g.start] = fragmentByEnd[f.end] = {start: g.start, end: f.end, ring: g.ring.concat(f.ring)}; + } + } else { + delete fragmentByStart[f.start]; + f.ring.unshift(start); + fragmentByStart[f.start = startIndex] = f; + } + } else { + fragmentByStart[startIndex] = fragmentByEnd[endIndex] = {start: startIndex, end: endIndex, ring: [start, end]}; + } + } + } + + function index(point) { + return point[0] * 2 + point[1] * (dx + 1) * 4; + } + + function smoothLinear(ring, values, value) { + ring.forEach(function (point) { + var x = point[0], + y = point[1], + xt = x | 0, + yt = y | 0, + v0, + v1 = values[yt * dx + xt]; + if (x > 0 && x < dx && xt === x) { + v0 = values[yt * dx + xt - 1]; + point[0] = x + (value - v0) / (v1 - v0) - 0.5; + } + if (y > 0 && y < dy && yt === y) { + v0 = values[(yt - 1) * dx + xt]; + point[1] = y + (value - v0) / (v1 - v0) - 0.5; + } + }); + } + + contours.contour = contour; + + contours.size = function (_) { + if (!arguments.length) + return [dx, dy]; + var _0 = Math.ceil(_[0]), _1 = Math.ceil(_[1]); + if (!(_0 > 0) || !(_1 > 0)) + throw new Error("invalid size"); + return dx = _0, dy = _1, contours; + }; + + contours.thresholds = function (_) { + return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant$6(slice$3.call(_)) : constant$6(_), contours) : threshold; + }; + + contours.smooth = function (_) { + return arguments.length ? (smooth = _ ? smoothLinear : noop$1, contours) : smooth === smoothLinear; + }; + + return contours; + } + +// TODO Optimize edge cases. +// TODO Optimize index calculation. +// TODO Optimize arguments. + function blurX(source, target, r) { + var n = source.width, + m = source.height, + w = (r << 1) + 1; + for (var j = 0; j < m; ++j) { + for (var i = 0, sr = 0; i < n + r; ++i) { + if (i < n) { + sr += source.data[i + j * n]; + } + if (i >= r) { + if (i >= w) { + sr -= source.data[i - w + j * n]; + } + target.data[i - r + j * n] = sr / Math.min(i + 1, n - 1 + w - i, w); + } + } + } + } + +// TODO Optimize edge cases. +// TODO Optimize index calculation. +// TODO Optimize arguments. + function blurY(source, target, r) { + var n = source.width, + m = source.height, + w = (r << 1) + 1; + for (var i = 0; i < n; ++i) { + for (var j = 0, sr = 0; j < m + r; ++j) { + if (j < m) { + sr += source.data[i + j * n]; + } + if (j >= r) { + if (j >= w) { + sr -= source.data[i + (j - w) * n]; + } + target.data[i + (j - r) * n] = sr / Math.min(j + 1, m - 1 + w - j, w); + } + } + } + } + + function defaultX(d) { + return d[0]; + } + + function defaultY(d) { + return d[1]; + } + + function defaultWeight() { + return 1; + } + + function density() { + var x = defaultX, + y = defaultY, + weight = defaultWeight, + dx = 960, + dy = 500, + r = 20, // blur radius + k = 2, // log2(grid cell size) + o = r * 3, // grid offset, to pad for blur + n = (dx + o * 2) >> k, // grid width + m = (dy + o * 2) >> k, // grid height + threshold = constant$6(20); + + function density(data) { + var values0 = new Float32Array(n * m), + values1 = new Float32Array(n * m); + + data.forEach(function (d, i, data) { + var xi = (+x(d, i, data) + o) >> k, + yi = (+y(d, i, data) + o) >> k, + wi = +weight(d, i, data); + if (xi >= 0 && xi < n && yi >= 0 && yi < m) { + values0[xi + yi * n] += wi; + } + }); + + // TODO Optimize. + blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k); + blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k); + blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k); + blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k); + blurX({width: n, height: m, data: values0}, {width: n, height: m, data: values1}, r >> k); + blurY({width: n, height: m, data: values1}, {width: n, height: m, data: values0}, r >> k); + + var tz = threshold(values0); + + // Convert number of thresholds into uniform thresholds. + if (!Array.isArray(tz)) { + var stop = max(values0); + tz = tickStep(0, stop, tz); + tz = sequence(0, Math.floor(stop / tz) * tz, tz); + tz.shift(); + } + + return contours() + .thresholds(tz) + .size([n, m]) + (values0) + .map(transform); + } + + function transform(geometry) { + geometry.value *= Math.pow(2, -2 * k); // Density in points per square pixel. + geometry.coordinates.forEach(transformPolygon); + return geometry; + } + + function transformPolygon(coordinates) { + coordinates.forEach(transformRing); + } + + function transformRing(coordinates) { + coordinates.forEach(transformPoint); + } + + // TODO Optimize. + function transformPoint(coordinates) { + coordinates[0] = coordinates[0] * Math.pow(2, k) - o; + coordinates[1] = coordinates[1] * Math.pow(2, k) - o; + } + + function resize() { + o = r * 3; + n = (dx + o * 2) >> k; + m = (dy + o * 2) >> k; + return density; + } + + density.x = function (_) { + return arguments.length ? (x = typeof _ === "function" ? _ : constant$6(+_), density) : x; + }; + + density.y = function (_) { + return arguments.length ? (y = typeof _ === "function" ? _ : constant$6(+_), density) : y; + }; + + density.weight = function (_) { + return arguments.length ? (weight = typeof _ === "function" ? _ : constant$6(+_), density) : weight; + }; + + density.size = function (_) { + if (!arguments.length) + return [dx, dy]; + var _0 = Math.ceil(_[0]), _1 = Math.ceil(_[1]); + if (!(_0 >= 0) && !(_0 >= 0)) + throw new Error("invalid size"); + return dx = _0, dy = _1, resize(); + }; + + density.cellSize = function (_) { + if (!arguments.length) + return 1 << k; + if (!((_ = +_) >= 1)) + throw new Error("invalid cell size"); + return k = Math.floor(Math.log(_) / Math.LN2), resize(); + }; + + density.thresholds = function (_) { + return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant$6(slice$3.call(_)) : constant$6(_), density) : threshold; + }; + + density.bandwidth = function (_) { + if (!arguments.length) + return Math.sqrt(r * (r + 1)); + if (!((_ = +_) >= 0)) + throw new Error("invalid bandwidth"); + return r = Math.round((Math.sqrt(4 * _ * _ + 1) - 1) / 2), resize(); + }; + + return density; + } + + var EOL = {}, + EOF = {}, + QUOTE = 34, + NEWLINE = 10, + RETURN = 13; + + function objectConverter(columns) { + return new Function("d", "return {" + columns.map(function (name, i) { + return JSON.stringify(name) + ": d[" + i + "] || \"\""; + }).join(",") + "}"); + } + + function customConverter(columns, f) { + var object = objectConverter(columns); + return function (row, i) { + return f(object(row), i, columns); + }; + } + +// Compute unique columns in order of discovery. + function inferColumns(rows) { + var columnSet = Object.create(null), + columns = []; + + rows.forEach(function (row) { + for (var column in row) { + if (!(column in columnSet)) { + columns.push(columnSet[column] = column); + } + } + }); + + return columns; + } + + function pad(value, width) { + var s = value + "", length = s.length; + return length < width ? new Array(width - length + 1).join(0) + s : s; + } + + function formatYear(year) { + return year < 0 ? "-" + pad(-year, 6) + : year > 9999 ? "+" + pad(year, 6) + : pad(year, 4); + } + + function formatDate(date) { + var hours = date.getUTCHours(), + minutes = date.getUTCMinutes(), + seconds = date.getUTCSeconds(), + milliseconds = date.getUTCMilliseconds(); + return isNaN(date) ? "Invalid Date" + : formatYear(date.getUTCFullYear()) + "-" + pad(date.getUTCMonth() + 1, 2) + "-" + pad(date.getUTCDate(), 2) + + (milliseconds ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + "." + pad(milliseconds, 3) + "Z" + : seconds ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2) + "Z" + : minutes || hours ? "T" + pad(hours, 2) + ":" + pad(minutes, 2) + "Z" + : ""); + } + + function dsvFormat(delimiter) { + var reFormat = new RegExp("[\"" + delimiter + "\n\r]"), + DELIMITER = delimiter.charCodeAt(0); + + function parse(text, f) { + var convert, columns, rows = parseRows(text, function (row, i) { + if (convert) + return convert(row, i - 1); + columns = row, convert = f ? customConverter(row, f) : objectConverter(row); + }); + rows.columns = columns || []; + return rows; + } + + function parseRows(text, f) { + var rows = [], // output rows + N = text.length, + I = 0, // current character index + n = 0, // current line number + t, // current token + eof = N <= 0, // current token followed by EOF? + eol = false; // current token followed by EOL? + + // Strip the trailing newline. + if (text.charCodeAt(N - 1) === NEWLINE) + --N; + if (text.charCodeAt(N - 1) === RETURN) + --N; + + function token() { + if (eof) + return EOF; + if (eol) + return eol = false, EOL; + + // Unescape quotes. + var i, j = I, c; + if (text.charCodeAt(j) === QUOTE) { + while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE) + ; + if ((i = I) >= N) + eof = true; + else if ((c = text.charCodeAt(I++)) === NEWLINE) + eol = true; + else if (c === RETURN) { + eol = true; + if (text.charCodeAt(I) === NEWLINE) + ++I; + } + return text.slice(j + 1, i - 1).replace(/""/g, "\""); + } + + // Find next delimiter or newline. + while (I < N) { + if ((c = text.charCodeAt(i = I++)) === NEWLINE) + eol = true; + else if (c === RETURN) { + eol = true; + if (text.charCodeAt(I) === NEWLINE) + ++I; + } else if (c !== DELIMITER) + continue; + return text.slice(j, i); + } + + // Return last token before EOF. + return eof = true, text.slice(j, N); + } + + while ((t = token()) !== EOF) { + var row = []; + while (t !== EOL && t !== EOF) + row.push(t), t = token(); + if (f && (row = f(row, n++)) == null) + continue; + rows.push(row); + } + + return rows; + } + + function preformatBody(rows, columns) { + return rows.map(function (row) { + return columns.map(function (column) { + return formatValue(row[column]); + }).join(delimiter); + }); + } + + function format(rows, columns) { + if (columns == null) + columns = inferColumns(rows); + return [columns.map(formatValue).join(delimiter)].concat(preformatBody(rows, columns)).join("\n"); + } + + function formatBody(rows, columns) { + if (columns == null) + columns = inferColumns(rows); + return preformatBody(rows, columns).join("\n"); + } + + function formatRows(rows) { + return rows.map(formatRow).join("\n"); + } + + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + + function formatValue(value) { + return value == null ? "" + : value instanceof Date ? formatDate(value) + : reFormat.test(value += "") ? "\"" + value.replace(/"/g, "\"\"") + "\"" + : value; + } + + return { + parse: parse, + parseRows: parseRows, + format: format, + formatBody: formatBody, + formatRows: formatRows, + formatRow: formatRow, + formatValue: formatValue + }; + } + + var csv = dsvFormat(","); + + var csvParse = csv.parse; + var csvParseRows = csv.parseRows; + var csvFormat = csv.format; + var csvFormatBody = csv.formatBody; + var csvFormatRows = csv.formatRows; + var csvFormatRow = csv.formatRow; + var csvFormatValue = csv.formatValue; + + var tsv = dsvFormat("\t"); + + var tsvParse = tsv.parse; + var tsvParseRows = tsv.parseRows; + var tsvFormat = tsv.format; + var tsvFormatBody = tsv.formatBody; + var tsvFormatRows = tsv.formatRows; + var tsvFormatRow = tsv.formatRow; + var tsvFormatValue = tsv.formatValue; + + function autoType(object) { + for (var key in object) { + var value = object[key].trim(), number, m; + if (!value) + value = null; + else if (value === "true") + value = true; + else if (value === "false") + value = false; + else if (value === "NaN") + value = NaN; + else if (!isNaN(number = +value)) + value = number; + else if (m = value.match(/^([-+]\d{2})?\d{4}(-\d{2}(-\d{2})?)?(T\d{2}:\d{2}(:\d{2}(\.\d{3})?)?(Z|[-+]\d{2}:\d{2})?)?$/)) { + if (fixtz && !!m[4] && !m[7]) + value = value.replace(/-/g, "/").replace(/T/, " "); + value = new Date(value); + } else + continue; + object[key] = value; + } + return object; + } + +// https://github.com/d3/d3-dsv/issues/45 + var fixtz = new Date("2019-01-01T00:00").getHours() || new Date("2019-07-01T00:00").getHours(); + + function responseBlob(response) { + if (!response.ok) + throw new Error(response.status + " " + response.statusText); + return response.blob(); + } + + function blob(input, init) { + return fetch(input, init).then(responseBlob); + } + + function responseArrayBuffer(response) { + if (!response.ok) + throw new Error(response.status + " " + response.statusText); + return response.arrayBuffer(); + } + + function buffer(input, init) { + return fetch(input, init).then(responseArrayBuffer); + } + + function responseText(response) { + if (!response.ok) + throw new Error(response.status + " " + response.statusText); + return response.text(); + } + + function text(input, init) { + return fetch(input, init).then(responseText); + } + + function dsvParse(parse) { + return function (input, init, row) { + if (arguments.length === 2 && typeof init === "function") + row = init, init = undefined; + return text(input, init).then(function (response) { + return parse(response, row); + }); + }; + } + + function dsv(delimiter, input, init, row) { + if (arguments.length === 3 && typeof init === "function") + row = init, init = undefined; + var format = dsvFormat(delimiter); + return text(input, init).then(function (response) { + return format.parse(response, row); + }); + } + + var csv$1 = dsvParse(csvParse); + var tsv$1 = dsvParse(tsvParse); + + function image(input, init) { + return new Promise(function (resolve, reject) { + var image = new Image; + for (var key in init) + image[key] = init[key]; + image.onerror = reject; + image.onload = function () { + resolve(image); + }; + image.src = input; + }); + } + + function responseJson(response) { + if (!response.ok) + throw new Error(response.status + " " + response.statusText); + return response.json(); + } + + function json(input, init) { + return fetch(input, init).then(responseJson); + } + + function parser(type) { + return function (input, init) { + return text(input, init).then(function (text) { + return (new DOMParser).parseFromString(text, type); + }); + }; + } + + var xml = parser("application/xml"); + + var html = parser("text/html"); + + var svg = parser("image/svg+xml"); + + function center$1(x, y) { + var nodes; + + if (x == null) + x = 0; + if (y == null) + y = 0; + + function force() { + var i, + n = nodes.length, + node, + sx = 0, + sy = 0; + + for (i = 0; i < n; ++i) { + node = nodes[i], sx += node.x, sy += node.y; + } + + for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) { + node = nodes[i], node.x -= sx, node.y -= sy; + } + } + + force.initialize = function (_) { + nodes = _; + }; + + force.x = function (_) { + return arguments.length ? (x = +_, force) : x; + }; + + force.y = function (_) { + return arguments.length ? (y = +_, force) : y; + }; + + return force; + } + + function constant$7(x) { + return function () { + return x; + }; + } + + function jiggle() { + return (Math.random() - 0.5) * 1e-6; + } + + function tree_add(d) { + var x = +this._x.call(null, d), + y = +this._y.call(null, d); + return add(this.cover(x, y), x, y, d); + } + + function add(tree, x, y, d) { + if (isNaN(x) || isNaN(y)) + return tree; // ignore invalid points + + var parent, + node = tree._root, + leaf = {data: d}, + x0 = tree._x0, + y0 = tree._y0, + x1 = tree._x1, + y1 = tree._y1, + xm, + ym, + xp, + yp, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) + return tree._root = leaf, tree; + + // Find the existing leaf for the new point, or add it. + while (node.length) { + if (right = x >= (xm = (x0 + x1) / 2)) + x0 = xm; + else + x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) + y0 = ym; + else + y1 = ym; + if (parent = node, !(node = node[i = bottom << 1 | right])) + return parent[i] = leaf, tree; + } + + // Is the new point is exactly coincident with the existing point? + xp = +tree._x.call(null, node.data); + yp = +tree._y.call(null, node.data); + if (x === xp && y === yp) + return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; + + // Otherwise, split the leaf node until the old and new point are separated. + do { + parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); + if (right = x >= (xm = (x0 + x1) / 2)) + x0 = xm; + else + x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) + y0 = ym; + else + y1 = ym; + } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); + return parent[j] = node, parent[i] = leaf, tree; + } + + function addAll(data) { + var d, i, n = data.length, + x, + y, + xz = new Array(n), + yz = new Array(n), + x0 = Infinity, + y0 = Infinity, + x1 = -Infinity, + y1 = -Infinity; + + // Compute the points and their extent. + for (i = 0; i < n; ++i) { + if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) + continue; + xz[i] = x; + yz[i] = y; + if (x < x0) + x0 = x; + if (x > x1) + x1 = x; + if (y < y0) + y0 = y; + if (y > y1) + y1 = y; + } + + // If there were no (valid) points, abort. + if (x0 > x1 || y0 > y1) + return this; + + // Expand the tree to cover the new points. + this.cover(x0, y0).cover(x1, y1); + + // Add the new points. + for (i = 0; i < n; ++i) { + add(this, xz[i], yz[i], data[i]); + } + + return this; + } + + function tree_cover(x, y) { + if (isNaN(x = +x) || isNaN(y = +y)) + return this; // ignore invalid points + + var x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1; + + // If the quadtree has no extent, initialize them. + // Integer extent are necessary so that if we later double the extent, + // the existing quadrant boundaries don’t change due to floating point error! + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x)) + 1; + y1 = (y0 = Math.floor(y)) + 1; + } + + // Otherwise, double repeatedly to cover. + else { + var z = x1 - x0, + node = this._root, + parent, + i; + + while (x0 > x || x >= x1 || y0 > y || y >= y1) { + i = (y < y0) << 1 | (x < x0); + parent = new Array(4), parent[i] = node, node = parent, z *= 2; + switch (i) { + case 0: + x1 = x0 + z, y1 = y0 + z; + break; + case 1: + x0 = x1 - z, y1 = y0 + z; + break; + case 2: + x1 = x0 + z, y0 = y1 - z; + break; + case 3: + x0 = x1 - z, y0 = y1 - z; + break; + } + } + + if (this._root && this._root.length) + this._root = node; + } + + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + return this; + } + + function tree_data() { + var data = []; + this.visit(function (node) { + if (!node.length) + do + data.push(node.data); + while (node = node.next) + }); + return data; + } + + function tree_extent(_) { + return arguments.length + ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) + : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; + } + + function Quad(node, x0, y0, x1, y1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.x1 = x1; + this.y1 = y1; + } + + function tree_find(x, y, radius) { + var data, + x0 = this._x0, + y0 = this._y0, + x1, + y1, + x2, + y2, + x3 = this._x1, + y3 = this._y1, + quads = [], + node = this._root, + q, + i; + + if (node) + quads.push(new Quad(node, x0, y0, x3, y3)); + if (radius == null) + radius = Infinity; + else { + x0 = x - radius, y0 = y - radius; + x3 = x + radius, y3 = y + radius; + radius *= radius; + } + + while (q = quads.pop()) { + + // Stop searching if this quadrant can’t contain a closer node. + if (!(node = q.node) + || (x1 = q.x0) > x3 + || (y1 = q.y0) > y3 + || (x2 = q.x1) < x0 + || (y2 = q.y1) < y0) + continue; + + // Bisect the current quadrant. + if (node.length) { + var xm = (x1 + x2) / 2, + ym = (y1 + y2) / 2; + + quads.push( + new Quad(node[3], xm, ym, x2, y2), + new Quad(node[2], x1, ym, xm, y2), + new Quad(node[1], xm, y1, x2, ym), + new Quad(node[0], x1, y1, xm, ym) + ); + + // Visit the closest quadrant first. + if (i = (y >= ym) << 1 | (x >= xm)) { + q = quads[quads.length - 1]; + quads[quads.length - 1] = quads[quads.length - 1 - i]; + quads[quads.length - 1 - i] = q; + } + } + + // Visit this point. (Visiting coincident points isn’t necessary!) + else { + var dx = x - +this._x.call(null, node.data), + dy = y - +this._y.call(null, node.data), + d2 = dx * dx + dy * dy; + if (d2 < radius) { + var d = Math.sqrt(radius = d2); + x0 = x - d, y0 = y - d; + x3 = x + d, y3 = y + d; + data = node.data; + } + } + } + + return data; + } + + function tree_remove(d) { + if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) + return this; // ignore invalid points + + var parent, + node = this._root, + retainer, + previous, + next, + x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1, + x, + y, + xm, + ym, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) + return this; + + // Find the leaf node for the point. + // While descending, also retain the deepest parent with a non-removed sibling. + if (node.length) + while (true) { + if (right = x >= (xm = (x0 + x1) / 2)) + x0 = xm; + else + x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) + y0 = ym; + else + y1 = ym; + if (!(parent = node, node = node[i = bottom << 1 | right])) + return this; + if (!node.length) + break; + if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) + retainer = parent, j = i; + } + + // Find the point to remove. + while (node.data !== d) + if (!(previous = node, node = node.next)) + return this; + if (next = node.next) + delete node.next; + + // If there are multiple coincident points, remove just the point. + if (previous) + return (next ? previous.next = next : delete previous.next), this; + + // If this is the root point, remove it. + if (!parent) + return this._root = next, this; + + // Remove this leaf. + next ? parent[i] = next : delete parent[i]; + + // If the parent now contains exactly one leaf, collapse superfluous parents. + if ((node = parent[0] || parent[1] || parent[2] || parent[3]) + && node === (parent[3] || parent[2] || parent[1] || parent[0]) + && !node.length) { + if (retainer) + retainer[j] = node; + else + this._root = node; + } + + return this; + } + + function removeAll(data) { + for (var i = 0, n = data.length; i < n; ++i) + this.remove(data[i]); + return this; + } + + function tree_root() { + return this._root; + } + + function tree_size() { + var size = 0; + this.visit(function (node) { + if (!node.length) + do + ++size; + while (node = node.next) + }); + return size; + } + + function tree_visit(callback) { + var quads = [], q, node = this._root, child, x0, y0, x1, y1; + if (node) + quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { + var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[3]) + quads.push(new Quad(child, xm, ym, x1, y1)); + if (child = node[2]) + quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[1]) + quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[0]) + quads.push(new Quad(child, x0, y0, xm, ym)); + } + } + return this; + } + + function tree_visitAfter(callback) { + var quads = [], next = [], q; + if (this._root) + quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[0]) + quads.push(new Quad(child, x0, y0, xm, ym)); + if (child = node[1]) + quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[2]) + quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[3]) + quads.push(new Quad(child, xm, ym, x1, y1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.y0, q.x1, q.y1); + } + return this; + } + + function defaultX$1(d) { + return d[0]; + } + + function tree_x(_) { + return arguments.length ? (this._x = _, this) : this._x; + } + + function defaultY$1(d) { + return d[1]; + } + + function tree_y(_) { + return arguments.length ? (this._y = _, this) : this._y; + } + + function quadtree(nodes, x, y) { + var tree = new Quadtree(x == null ? defaultX$1 : x, y == null ? defaultY$1 : y, NaN, NaN, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); + } + + function Quadtree(x, y, x0, y0, x1, y1) { + this._x = x; + this._y = y; + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + this._root = undefined; + } + + function leaf_copy(leaf) { + var copy = {data: leaf.data}, next = copy; + while (leaf = leaf.next) + next = next.next = {data: leaf.data}; + return copy; + } + + var treeProto = quadtree.prototype = Quadtree.prototype; + + treeProto.copy = function () { + var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), + node = this._root, + nodes, + child; + + if (!node) + return copy; + + if (!node.length) + return copy._root = leaf_copy(node), copy; + + nodes = [{source: node, target: copy._root = new Array(4)}]; + while (node = nodes.pop()) { + for (var i = 0; i < 4; ++i) { + if (child = node.source[i]) { + if (child.length) + nodes.push({source: child, target: node.target[i] = new Array(4)}); + else + node.target[i] = leaf_copy(child); + } + } + } + + return copy; + }; + + treeProto.add = tree_add; + treeProto.addAll = addAll; + treeProto.cover = tree_cover; + treeProto.data = tree_data; + treeProto.extent = tree_extent; + treeProto.find = tree_find; + treeProto.remove = tree_remove; + treeProto.removeAll = removeAll; + treeProto.root = tree_root; + treeProto.size = tree_size; + treeProto.visit = tree_visit; + treeProto.visitAfter = tree_visitAfter; + treeProto.x = tree_x; + treeProto.y = tree_y; + + function x(d) { + return d.x + d.vx; + } + + function y(d) { + return d.y + d.vy; + } + + function collide(radius) { + var nodes, + radii, + strength = 1, + iterations = 1; + + if (typeof radius !== "function") + radius = constant$7(radius == null ? 1 : +radius); + + function force() { + var i, n = nodes.length, + tree, + node, + xi, + yi, + ri, + ri2; + + for (var k = 0; k < iterations; ++k) { + tree = quadtree(nodes, x, y).visitAfter(prepare); + for (i = 0; i < n; ++i) { + node = nodes[i]; + ri = radii[node.index], ri2 = ri * ri; + xi = node.x + node.vx; + yi = node.y + node.vy; + tree.visit(apply); + } + } + + function apply(quad, x0, y0, x1, y1) { + var data = quad.data, rj = quad.r, r = ri + rj; + if (data) { + if (data.index > node.index) { + var x = xi - data.x - data.vx, + y = yi - data.y - data.vy, + l = x * x + y * y; + if (l < r * r) { + if (x === 0) + x = jiggle(), l += x * x; + if (y === 0) + y = jiggle(), l += y * y; + l = (r - (l = Math.sqrt(l))) / l * strength; + node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj)); + node.vy += (y *= l) * r; + data.vx -= x * (r = 1 - r); + data.vy -= y * r; + } + } + return; + } + return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; + } + } + + function prepare(quad) { + if (quad.data) + return quad.r = radii[quad.data.index]; + for (var i = quad.r = 0; i < 4; ++i) { + if (quad[i] && quad[i].r > quad.r) { + quad.r = quad[i].r; + } + } + } + + function initialize() { + if (!nodes) + return; + var i, n = nodes.length, node; + radii = new Array(n); + for (i = 0; i < n; ++i) + node = nodes[i], radii[node.index] = +radius(node, i, nodes); + } + + force.initialize = function (_) { + nodes = _; + initialize(); + }; + + force.iterations = function (_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function (_) { + return arguments.length ? (strength = +_, force) : strength; + }; + + force.radius = function (_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : radius; + }; + + return force; + } + + function index(d) { + return d.index; + } + + function find(nodeById, nodeId) { + var node = nodeById.get(nodeId); + if (!node) + throw new Error("missing: " + nodeId); + return node; + } + + function link(links) { + var id = index, + strength = defaultStrength, + strengths, + distance = constant$7(30), + distances, + nodes, + count, + bias, + iterations = 1; + + if (links == null) + links = []; + + function defaultStrength(link) { + return 1 / Math.min(count[link.source.index], count[link.target.index]); + } + + function force(alpha) { + for (var k = 0, n = links.length; k < iterations; ++k) { + for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { + link = links[i], source = link.source, target = link.target; + x = target.x + target.vx - source.x - source.vx || jiggle(); + y = target.y + target.vy - source.y - source.vy || jiggle(); + l = Math.sqrt(x * x + y * y); + l = (l - distances[i]) / l * alpha * strengths[i]; + x *= l, y *= l; + target.vx -= x * (b = bias[i]); + target.vy -= y * b; + source.vx += x * (b = 1 - b); + source.vy += y * b; + } + } + } + + function initialize() { + if (!nodes) + return; + + var i, + n = nodes.length, + m = links.length, + nodeById = map$1(nodes, id), + link; + + for (i = 0, count = new Array(n); i < m; ++i) { + link = links[i], link.index = i; + if (typeof link.source !== "object") + link.source = find(nodeById, link.source); + if (typeof link.target !== "object") + link.target = find(nodeById, link.target); + count[link.source.index] = (count[link.source.index] || 0) + 1; + count[link.target.index] = (count[link.target.index] || 0) + 1; + } + + for (i = 0, bias = new Array(m); i < m; ++i) { + link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + } + + strengths = new Array(m), initializeStrength(); + distances = new Array(m), initializeDistance(); + } + + function initializeStrength() { + if (!nodes) + return; + + for (var i = 0, n = links.length; i < n; ++i) { + strengths[i] = +strength(links[i], i, links); + } + } + + function initializeDistance() { + if (!nodes) + return; + + for (var i = 0, n = links.length; i < n; ++i) { + distances[i] = +distance(links[i], i, links); + } + } + + force.initialize = function (_) { + nodes = _; + initialize(); + }; + + force.links = function (_) { + return arguments.length ? (links = _, initialize(), force) : links; + }; + + force.id = function (_) { + return arguments.length ? (id = _, force) : id; + }; + + force.iterations = function (_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function (_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initializeStrength(), force) : strength; + }; + + force.distance = function (_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant$7(+_), initializeDistance(), force) : distance; + }; + + return force; + } + + function x$1(d) { + return d.x; + } + + function y$1(d) { + return d.y; + } + + var initialRadius = 10, + initialAngle = Math.PI * (3 - Math.sqrt(5)); + + function simulation(nodes) { + var simulation, + alpha = 1, + alphaMin = 0.001, + alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), + alphaTarget = 0, + velocityDecay = 0.6, + forces = map$1(), + stepper = timer(step), + event = dispatch("tick", "end"); + + if (nodes == null) + nodes = []; + + function step() { + tick(); + event.call("tick", simulation); + if (alpha < alphaMin) { + stepper.stop(); + event.call("end", simulation); + } + } + + function tick(iterations) { + var i, n = nodes.length, node; + + if (iterations === undefined) + iterations = 1; + + for (var k = 0; k < iterations; ++k) { + alpha += (alphaTarget - alpha) * alphaDecay; + + forces.each(function (force) { + force(alpha); + }); + + for (i = 0; i < n; ++i) { + node = nodes[i]; + if (node.fx == null) + node.x += node.vx *= velocityDecay; + else + node.x = node.fx, node.vx = 0; + if (node.fy == null) + node.y += node.vy *= velocityDecay; + else + node.y = node.fy, node.vy = 0; + } + } + + return simulation; + } + + function initializeNodes() { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.index = i; + if (node.fx != null) + node.x = node.fx; + if (node.fy != null) + node.y = node.fy; + if (isNaN(node.x) || isNaN(node.y)) { + var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; + node.x = radius * Math.cos(angle); + node.y = radius * Math.sin(angle); + } + if (isNaN(node.vx) || isNaN(node.vy)) { + node.vx = node.vy = 0; + } + } + } + + function initializeForce(force) { + if (force.initialize) + force.initialize(nodes); + return force; + } + + initializeNodes(); + + return simulation = { + tick: tick, + + restart: function () { + return stepper.restart(step), simulation; + }, + + stop: function () { + return stepper.stop(), simulation; + }, + + nodes: function (_) { + return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; + }, + + alpha: function (_) { + return arguments.length ? (alpha = +_, simulation) : alpha; + }, + + alphaMin: function (_) { + return arguments.length ? (alphaMin = +_, simulation) : alphaMin; + }, + + alphaDecay: function (_) { + return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; + }, + + alphaTarget: function (_) { + return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; + }, + + velocityDecay: function (_) { + return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; + }, + + force: function (name, _) { + return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); + }, + + find: function (x, y, radius) { + var i = 0, + n = nodes.length, + dx, + dy, + d2, + node, + closest; + + if (radius == null) + radius = Infinity; + else + radius *= radius; + + for (i = 0; i < n; ++i) { + node = nodes[i]; + dx = x - node.x; + dy = y - node.y; + d2 = dx * dx + dy * dy; + if (d2 < radius) + closest = node, radius = d2; + } + + return closest; + }, + + on: function (name, _) { + return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); + } + }; + } + + function manyBody() { + var nodes, + node, + alpha, + strength = constant$7(-30), + strengths, + distanceMin2 = 1, + distanceMax2 = Infinity, + theta2 = 0.81; + + function force(_) { + var i, n = nodes.length, tree = quadtree(nodes, x$1, y$1).visitAfter(accumulate); + for (alpha = _, i = 0; i < n; ++i) + node = nodes[i], tree.visit(apply); + } + + function initialize() { + if (!nodes) + return; + var i, n = nodes.length, node; + strengths = new Array(n); + for (i = 0; i < n; ++i) + node = nodes[i], strengths[node.index] = +strength(node, i, nodes); + } + + function accumulate(quad) { + var strength = 0, q, c, weight = 0, x, y, i; + + // For internal nodes, accumulate forces from child quadrants. + if (quad.length) { + for (x = y = i = 0; i < 4; ++i) { + if ((q = quad[i]) && (c = Math.abs(q.value))) { + strength += q.value, weight += c, x += c * q.x, y += c * q.y; + } + } + quad.x = x / weight; + quad.y = y / weight; + } + + // For leaf nodes, accumulate forces from coincident quadrants. + else { + q = quad; + q.x = q.data.x; + q.y = q.data.y; + do + strength += strengths[q.data.index]; + while (q = q.next); + } + + quad.value = strength; + } + + function apply(quad, x1, _, x2) { + if (!quad.value) + return true; + + var x = quad.x - node.x, + y = quad.y - node.y, + w = x2 - x1, + l = x * x + y * y; + + // Apply the Barnes-Hut approximation if possible. + // Limit forces for very close nodes; randomize direction if coincident. + if (w * w / theta2 < l) { + if (l < distanceMax2) { + if (x === 0) + x = jiggle(), l += x * x; + if (y === 0) + y = jiggle(), l += y * y; + if (l < distanceMin2) + l = Math.sqrt(distanceMin2 * l); + node.vx += x * quad.value * alpha / l; + node.vy += y * quad.value * alpha / l; + } + return true; + } + + // Otherwise, process points directly. + else if (quad.length || l >= distanceMax2) + return; + + // Limit forces for very close nodes; randomize direction if coincident. + if (quad.data !== node || quad.next) { + if (x === 0) + x = jiggle(), l += x * x; + if (y === 0) + y = jiggle(), l += y * y; + if (l < distanceMin2) + l = Math.sqrt(distanceMin2 * l); + } + + do + if (quad.data !== node) { + w = strengths[quad.data.index] * alpha / l; + node.vx += x * w; + node.vy += y * w; + } + while (quad = quad.next); + } + + force.initialize = function (_) { + nodes = _; + initialize(); + }; + + force.strength = function (_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength; + }; + + force.distanceMin = function (_) { + return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); + }; + + force.distanceMax = function (_) { + return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); + }; + + force.theta = function (_) { + return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); + }; + + return force; + } + + function radial(radius, x, y) { + var nodes, + strength = constant$7(0.1), + strengths, + radiuses; + + if (typeof radius !== "function") + radius = constant$7(+radius); + if (x == null) + x = 0; + if (y == null) + y = 0; + + function force(alpha) { + for (var i = 0, n = nodes.length; i < n; ++i) { + var node = nodes[i], + dx = node.x - x || 1e-6, + dy = node.y - y || 1e-6, + r = Math.sqrt(dx * dx + dy * dy), + k = (radiuses[i] - r) * strengths[i] * alpha / r; + node.vx += dx * k; + node.vy += dy * k; + } + } + + function initialize() { + if (!nodes) + return; + var i, n = nodes.length; + strengths = new Array(n); + radiuses = new Array(n); + for (i = 0; i < n; ++i) { + radiuses[i] = +radius(nodes[i], i, nodes); + strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function (_) { + nodes = _, initialize(); + }; + + force.strength = function (_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength; + }; + + force.radius = function (_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : radius; + }; + + force.x = function (_) { + return arguments.length ? (x = +_, force) : x; + }; + + force.y = function (_) { + return arguments.length ? (y = +_, force) : y; + }; + + return force; + } + + function x$2(x) { + var strength = constant$7(0.1), + nodes, + strengths, + xz; + + if (typeof x !== "function") + x = constant$7(x == null ? 0 : +x); + + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha; + } + } + + function initialize() { + if (!nodes) + return; + var i, n = nodes.length; + strengths = new Array(n); + xz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function (_) { + nodes = _; + initialize(); + }; + + force.strength = function (_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength; + }; + + force.x = function (_) { + return arguments.length ? (x = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : x; + }; + + return force; + } + + function y$2(y) { + var strength = constant$7(0.1), + nodes, + strengths, + yz; + + if (typeof y !== "function") + y = constant$7(y == null ? 0 : +y); + + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha; + } + } + + function initialize() { + if (!nodes) + return; + var i, n = nodes.length; + strengths = new Array(n); + yz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function (_) { + nodes = _; + initialize(); + }; + + force.strength = function (_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength; + }; + + force.y = function (_) { + return arguments.length ? (y = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : y; + }; + + return force; + } + +// Computes the decimal coefficient and exponent of the specified number x with +// significant digits p, where x is positive and p is in [1, 21] or undefined. +// For example, formatDecimal(1.23) returns ["123", 0]. + function formatDecimal(x, p) { + if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) + return null; // NaN, ±Infinity + var i, coefficient = x.slice(0, i); + + // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ + // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). + return [ + coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, + +x.slice(i + 1) + ]; + } + + function exponent$1(x) { + return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN; + } + + function formatGroup(grouping, thousands) { + return function (value, width) { + var i = value.length, + t = [], + j = 0, + g = grouping[0], + length = 0; + + while (i > 0 && g > 0) { + if (length + g + 1 > width) + g = Math.max(1, width - length); + t.push(value.substring(i -= g, i + g)); + if ((length += g + 1) > width) + break; + g = grouping[j = (j + 1) % grouping.length]; + } + + return t.reverse().join(thousands); + }; + } + + function formatNumerals(numerals) { + return function (value) { + return value.replace(/[0-9]/g, function (i) { + return numerals[+i]; + }); + }; + } + +// [[fill]align][sign][symbol][0][width][,][.precision][~][type] + var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i; + + function formatSpecifier(specifier) { + if (!(match = re.exec(specifier))) + throw new Error("invalid format: " + specifier); + var match; + return new FormatSpecifier({ + fill: match[1], + align: match[2], + sign: match[3], + symbol: match[4], + zero: match[5], + width: match[6], + comma: match[7], + precision: match[8] && match[8].slice(1), + trim: match[9], + type: match[10] + }); + } + + formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof + + function FormatSpecifier(specifier) { + this.fill = specifier.fill === undefined ? " " : specifier.fill + ""; + this.align = specifier.align === undefined ? ">" : specifier.align + ""; + this.sign = specifier.sign === undefined ? "-" : specifier.sign + ""; + this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + ""; + this.zero = !!specifier.zero; + this.width = specifier.width === undefined ? undefined : +specifier.width; + this.comma = !!specifier.comma; + this.precision = specifier.precision === undefined ? undefined : +specifier.precision; + this.trim = !!specifier.trim; + this.type = specifier.type === undefined ? "" : specifier.type + ""; + } + + FormatSpecifier.prototype.toString = function () { + return this.fill + + this.align + + this.sign + + this.symbol + + (this.zero ? "0" : "") + + (this.width === undefined ? "" : Math.max(1, this.width | 0)) + + (this.comma ? "," : "") + + (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0)) + + (this.trim ? "~" : "") + + this.type; + }; + +// Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k. + function formatTrim(s) { + out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) { + switch (s[i]) { + case ".": + i0 = i1 = i; + break; + case "0": + if (i0 === 0) + i0 = i; + i1 = i; + break; + default: + if (!+s[i]) + break out; + if (i0 > 0) + i0 = 0; + break; + } + } + return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s; + } + + var prefixExponent; + + function formatPrefixAuto(x, p) { + var d = formatDecimal(x, p); + if (!d) + return x + ""; + var coefficient = d[0], + exponent = d[1], + i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, + n = coefficient.length; + return i === n ? coefficient + : i > n ? coefficient + new Array(i - n + 1).join("0") + : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) + : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y! + } + + function formatRounded(x, p) { + var d = formatDecimal(x, p); + if (!d) + return x + ""; + var coefficient = d[0], + exponent = d[1]; + return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient + : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) + : coefficient + new Array(exponent - coefficient.length + 2).join("0"); + } + + var formatTypes = { + "%": function (x, p) { + return (x * 100).toFixed(p); + }, + "b": function (x) { + return Math.round(x).toString(2); + }, + "c": function (x) { + return x + ""; + }, + "d": function (x) { + return Math.round(x).toString(10); + }, + "e": function (x, p) { + return x.toExponential(p); + }, + "f": function (x, p) { + return x.toFixed(p); + }, + "g": function (x, p) { + return x.toPrecision(p); + }, + "o": function (x) { + return Math.round(x).toString(8); + }, + "p": function (x, p) { + return formatRounded(x * 100, p); + }, + "r": formatRounded, + "s": formatPrefixAuto, + "X": function (x) { + return Math.round(x).toString(16).toUpperCase(); + }, + "x": function (x) { + return Math.round(x).toString(16); + } + }; + + function identity$3(x) { + return x; + } + + var map$2 = Array.prototype.map, + prefixes = ["y", "z", "a", "f", "p", "n", "\xB5", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"]; + + function formatLocale(locale) { + var group = locale.grouping === undefined || locale.thousands === undefined ? identity$3 : formatGroup(map$2.call(locale.grouping, Number), locale.thousands + ""), + currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "", + currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "", + decimal = locale.decimal === undefined ? "." : locale.decimal + "", + numerals = locale.numerals === undefined ? identity$3 : formatNumerals(map$2.call(locale.numerals, String)), + percent = locale.percent === undefined ? "%" : locale.percent + "", + minus = locale.minus === undefined ? "-" : locale.minus + "", + nan = locale.nan === undefined ? "NaN" : locale.nan + ""; + + function newFormat(specifier) { + specifier = formatSpecifier(specifier); + + var fill = specifier.fill, + align = specifier.align, + sign = specifier.sign, + symbol = specifier.symbol, + zero = specifier.zero, + width = specifier.width, + comma = specifier.comma, + precision = specifier.precision, + trim = specifier.trim, + type = specifier.type; + + // The "n" type is an alias for ",g". + if (type === "n") + comma = true, type = "g"; + + // The "" type, and any invalid type, is an alias for ".12~g". + else if (!formatTypes[type]) + precision === undefined && (precision = 12), trim = true, type = "g"; + + // If zero fill is specified, padding goes after sign and before digits. + if (zero || (fill === "0" && align === "=")) + zero = true, fill = "0", align = "="; + + // Compute the prefix and suffix. + // For SI-prefix, the suffix is lazily computed. + var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", + suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : ""; + + // What format function should we use? + // Is this an integer type? + // Can this type generate exponential notation? + var formatType = formatTypes[type], + maybeSuffix = /[defgprs%]/.test(type); + + // Set the default precision if not specified, + // or clamp the specified precision to the supported range. + // For significant precision, it must be in [1, 21]. + // For fixed precision, it must be in [0, 20]. + precision = precision === undefined ? 6 + : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) + : Math.max(0, Math.min(20, precision)); + + function format(value) { + var valuePrefix = prefix, + valueSuffix = suffix, + i, n, c; + + if (type === "c") { + valueSuffix = formatType(value) + valueSuffix; + value = ""; + } else { + value = +value; + + // Determine the sign. -0 is not less than 0, but 1 / -0 is! + var valueNegative = value < 0 || 1 / value < 0; + + // Perform the initial formatting. + value = isNaN(value) ? nan : formatType(Math.abs(value), precision); + + // Trim insignificant zeros. + if (trim) + value = formatTrim(value); + + // If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign. + if (valueNegative && +value === 0 && sign !== "+") + valueNegative = false; + + // Compute the prefix and suffix. + valuePrefix = (valueNegative ? (sign === "(" ? sign : minus) : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; + valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); + + // Break the formatted value into the integer “value” part that can be + // grouped, and fractional or exponential “suffix” part that is not. + if (maybeSuffix) { + i = -1, n = value.length; + while (++i < n) { + if (c = value.charCodeAt(i), 48 > c || c > 57) { + valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; + value = value.slice(0, i); + break; + } + } + } + } + + // If the fill character is not "0", grouping is applied before padding. + if (comma && !zero) + value = group(value, Infinity); + + // Compute the padding. + var length = valuePrefix.length + value.length + valueSuffix.length, + padding = length < width ? new Array(width - length + 1).join(fill) : ""; + + // If the fill character is "0", grouping is applied after padding. + if (comma && zero) + value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; + + // Reconstruct the final output based on the desired alignment. + switch (align) { + case "<": + value = valuePrefix + value + valueSuffix + padding; + break; + case "=": + value = valuePrefix + padding + value + valueSuffix; + break; + case "^": + value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); + break; + default: + value = padding + valuePrefix + value + valueSuffix; + break; + } + + return numerals(value); + } + + format.toString = function () { + return specifier + ""; + }; + + return format; + } + + function formatPrefix(specifier, value) { + var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), + e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3, + k = Math.pow(10, -e), + prefix = prefixes[8 + e / 3]; + return function (value) { + return f(k * value) + prefix; + }; + } + + return { + format: newFormat, + formatPrefix: formatPrefix + }; + } + + var locale; + + defaultLocale({ + decimal: ".", + thousands: ",", + grouping: [3], + currency: ["$", ""], + minus: "-" + }); + + function defaultLocale(definition) { + locale = formatLocale(definition); + exports.format = locale.format; + exports.formatPrefix = locale.formatPrefix; + return locale; + } + + function precisionFixed(step) { + return Math.max(0, -exponent$1(Math.abs(step))); + } + + function precisionPrefix(step, value) { + return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step))); + } + + function precisionRound(step, max) { + step = Math.abs(step), max = Math.abs(max) - step; + return Math.max(0, exponent$1(max) - exponent$1(step)) + 1; + } + +// Adds floating point numbers with twice the normal precision. +// Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and +// Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3) +// 305–363 (1997). +// Code adapted from GeographicLib by Charles F. F. Karney, +// http://geographiclib.sourceforge.net/ + + function adder() { + return new Adder; + } + + function Adder() { + this.reset(); + } + + Adder.prototype = { + constructor: Adder, + reset: function () { + this.s = // rounded value + this.t = 0; // exact error + }, + add: function (y) { + add$1(temp, y, this.t); + add$1(this, temp.s, this.s); + if (this.s) + this.t += temp.t; + else + this.s = temp.t; + }, + valueOf: function () { + return this.s; + } + }; + + var temp = new Adder; + + function add$1(adder, a, b) { + var x = adder.s = a + b, + bv = x - a, + av = x - bv; + adder.t = (a - av) + (b - bv); + } + + var epsilon$2 = 1e-6; + var epsilon2$1 = 1e-12; + var pi$3 = Math.PI; + var halfPi$2 = pi$3 / 2; + var quarterPi = pi$3 / 4; + var tau$3 = pi$3 * 2; + + var degrees$1 = 180 / pi$3; + var radians = pi$3 / 180; + + var abs = Math.abs; + var atan = Math.atan; + var atan2 = Math.atan2; + var cos$1 = Math.cos; + var ceil = Math.ceil; + var exp = Math.exp; + var log = Math.log; + var pow = Math.pow; + var sin$1 = Math.sin; + var sign = Math.sign || function (x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; + }; + var sqrt = Math.sqrt; + var tan = Math.tan; + + function acos(x) { + return x > 1 ? 0 : x < -1 ? pi$3 : Math.acos(x); + } + + function asin(x) { + return x > 1 ? halfPi$2 : x < -1 ? -halfPi$2 : Math.asin(x); + } + + function haversin(x) { + return (x = sin$1(x / 2)) * x; + } + + function noop$2() {} + + function streamGeometry(geometry, stream) { + if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) { + streamGeometryType[geometry.type](geometry, stream); + } + } + + var streamObjectType = { + Feature: function (object, stream) { + streamGeometry(object.geometry, stream); + }, + FeatureCollection: function (object, stream) { + var features = object.features, i = -1, n = features.length; + while (++i < n) + streamGeometry(features[i].geometry, stream); + } + }; + + var streamGeometryType = { + Sphere: function (object, stream) { + stream.sphere(); + }, + Point: function (object, stream) { + object = object.coordinates; + stream.point(object[0], object[1], object[2]); + }, + MultiPoint: function (object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) + object = coordinates[i], stream.point(object[0], object[1], object[2]); + }, + LineString: function (object, stream) { + streamLine(object.coordinates, stream, 0); + }, + MultiLineString: function (object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) + streamLine(coordinates[i], stream, 0); + }, + Polygon: function (object, stream) { + streamPolygon(object.coordinates, stream); + }, + MultiPolygon: function (object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) + streamPolygon(coordinates[i], stream); + }, + GeometryCollection: function (object, stream) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) + streamGeometry(geometries[i], stream); + } + }; + + function streamLine(coordinates, stream, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + stream.lineStart(); + while (++i < n) + coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]); + stream.lineEnd(); + } + + function streamPolygon(coordinates, stream) { + var i = -1, n = coordinates.length; + stream.polygonStart(); + while (++i < n) + streamLine(coordinates[i], stream, 1); + stream.polygonEnd(); + } + + function geoStream(object, stream) { + if (object && streamObjectType.hasOwnProperty(object.type)) { + streamObjectType[object.type](object, stream); + } else { + streamGeometry(object, stream); + } + } + + var areaRingSum = adder(); + + var areaSum = adder(), + lambda00, + phi00, + lambda0, + cosPhi0, + sinPhi0; + + var areaStream = { + point: noop$2, + lineStart: noop$2, + lineEnd: noop$2, + polygonStart: function () { + areaRingSum.reset(); + areaStream.lineStart = areaRingStart; + areaStream.lineEnd = areaRingEnd; + }, + polygonEnd: function () { + var areaRing = +areaRingSum; + areaSum.add(areaRing < 0 ? tau$3 + areaRing : areaRing); + this.lineStart = this.lineEnd = this.point = noop$2; + }, + sphere: function () { + areaSum.add(tau$3); + } + }; + + function areaRingStart() { + areaStream.point = areaPointFirst; + } + + function areaRingEnd() { + areaPoint(lambda00, phi00); + } + + function areaPointFirst(lambda, phi) { + areaStream.point = areaPoint; + lambda00 = lambda, phi00 = phi; + lambda *= radians, phi *= radians; + lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi); + } + + function areaPoint(lambda, phi) { + lambda *= radians, phi *= radians; + phi = phi / 2 + quarterPi; // half the angular distance from south pole + + // Spherical excess E for a spherical triangle with vertices: south pole, + // previous point, current point. Uses a formula derived from Cagnoli’s + // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2). + var dLambda = lambda - lambda0, + sdLambda = dLambda >= 0 ? 1 : -1, + adLambda = sdLambda * dLambda, + cosPhi = cos$1(phi), + sinPhi = sin$1(phi), + k = sinPhi0 * sinPhi, + u = cosPhi0 * cosPhi + k * cos$1(adLambda), + v = k * sdLambda * sin$1(adLambda); + areaRingSum.add(atan2(v, u)); + + // Advance the previous points. + lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; + } + + function area$1(object) { + areaSum.reset(); + geoStream(object, areaStream); + return areaSum * 2; + } + + function spherical(cartesian) { + return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])]; + } + + function cartesian(spherical) { + var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi); + return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)]; + } + + function cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + } + + function cartesianCross(a, b) { + return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]]; + } + +// TODO return a + function cartesianAddInPlace(a, b) { + a[0] += b[0], a[1] += b[1], a[2] += b[2]; + } + + function cartesianScale(vector, k) { + return [vector[0] * k, vector[1] * k, vector[2] * k]; + } + +// TODO return d + function cartesianNormalizeInPlace(d) { + var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l, d[1] /= l, d[2] /= l; + } + + var lambda0$1, phi0, lambda1, phi1, // bounds + lambda2, // previous lambda-coordinate + lambda00$1, phi00$1, // first point + p0, // previous 3D point + deltaSum = adder(), + ranges, + range; + + var boundsStream = { + point: boundsPoint, + lineStart: boundsLineStart, + lineEnd: boundsLineEnd, + polygonStart: function () { + boundsStream.point = boundsRingPoint; + boundsStream.lineStart = boundsRingStart; + boundsStream.lineEnd = boundsRingEnd; + deltaSum.reset(); + areaStream.polygonStart(); + }, + polygonEnd: function () { + areaStream.polygonEnd(); + boundsStream.point = boundsPoint; + boundsStream.lineStart = boundsLineStart; + boundsStream.lineEnd = boundsLineEnd; + if (areaRingSum < 0) + lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90); + else if (deltaSum > epsilon$2) + phi1 = 90; + else if (deltaSum < -epsilon$2) + phi0 = -90; + range[0] = lambda0$1, range[1] = lambda1; + }, + sphere: function () { + lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90); + } + }; + + function boundsPoint(lambda, phi) { + ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]); + if (phi < phi0) + phi0 = phi; + if (phi > phi1) + phi1 = phi; + } + + function linePoint(lambda, phi) { + var p = cartesian([lambda * radians, phi * radians]); + if (p0) { + var normal = cartesianCross(p0, p), + equatorial = [normal[1], -normal[0], 0], + inflection = cartesianCross(equatorial, normal); + cartesianNormalizeInPlace(inflection); + inflection = spherical(inflection); + var delta = lambda - lambda2, + sign = delta > 0 ? 1 : -1, + lambdai = inflection[0] * degrees$1 * sign, + phii, + antimeridian = abs(delta) > 180; + if (antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) { + phii = inflection[1] * degrees$1; + if (phii > phi1) + phi1 = phii; + } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) { + phii = -inflection[1] * degrees$1; + if (phii < phi0) + phi0 = phii; + } else { + if (phi < phi0) + phi0 = phi; + if (phi > phi1) + phi1 = phi; + } + if (antimeridian) { + if (lambda < lambda2) { + if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) + lambda1 = lambda; + } else { + if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) + lambda0$1 = lambda; + } + } else { + if (lambda1 >= lambda0$1) { + if (lambda < lambda0$1) + lambda0$1 = lambda; + if (lambda > lambda1) + lambda1 = lambda; + } else { + if (lambda > lambda2) { + if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) + lambda1 = lambda; + } else { + if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) + lambda0$1 = lambda; + } + } + } + } else { + ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]); + } + if (phi < phi0) + phi0 = phi; + if (phi > phi1) + phi1 = phi; + p0 = p, lambda2 = lambda; + } + + function boundsLineStart() { + boundsStream.point = linePoint; + } + + function boundsLineEnd() { + range[0] = lambda0$1, range[1] = lambda1; + boundsStream.point = boundsPoint; + p0 = null; + } + + function boundsRingPoint(lambda, phi) { + if (p0) { + var delta = lambda - lambda2; + deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta); + } else { + lambda00$1 = lambda, phi00$1 = phi; + } + areaStream.point(lambda, phi); + linePoint(lambda, phi); + } + + function boundsRingStart() { + areaStream.lineStart(); + } + + function boundsRingEnd() { + boundsRingPoint(lambda00$1, phi00$1); + areaStream.lineEnd(); + if (abs(deltaSum) > epsilon$2) + lambda0$1 = -(lambda1 = 180); + range[0] = lambda0$1, range[1] = lambda1; + p0 = null; + } + +// Finds the left-right distance between two longitudes. +// This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want +// the distance between ±180° to be 360°. + function angle(lambda0, lambda1) { + return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1; + } + + function rangeCompare(a, b) { + return a[0] - b[0]; + } + + function rangeContains(range, x) { + return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; + } + + function bounds(feature) { + var i, n, a, b, merged, deltaMax, delta; + + phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity); + ranges = []; + geoStream(feature, boundsStream); + + // First, sort ranges by their minimum longitudes. + if (n = ranges.length) { + ranges.sort(rangeCompare); + + // Then, merge any ranges that overlap. + for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) { + b = ranges[i]; + if (rangeContains(a, b[0]) || rangeContains(a, b[1])) { + if (angle(a[0], b[1]) > angle(a[0], a[1])) + a[1] = b[1]; + if (angle(b[0], a[1]) > angle(a[0], a[1])) + a[0] = b[0]; + } else { + merged.push(a = b); + } + } + + // Finally, find the largest gap between the merged ranges. + // The final bounding box will be the inverse of this gap. + for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) { + b = merged[i]; + if ((delta = angle(a[1], b[0])) > deltaMax) + deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1]; + } + } + + ranges = range = null; + + return lambda0$1 === Infinity || phi0 === Infinity + ? [[NaN, NaN], [NaN, NaN]] + : [[lambda0$1, phi0], [lambda1, phi1]]; + } + + var W0, W1, + X0, Y0, Z0, + X1, Y1, Z1, + X2, Y2, Z2, + lambda00$2, phi00$2, // first point + x0, y0, z0; // previous point + + var centroidStream = { + sphere: noop$2, + point: centroidPoint, + lineStart: centroidLineStart, + lineEnd: centroidLineEnd, + polygonStart: function () { + centroidStream.lineStart = centroidRingStart; + centroidStream.lineEnd = centroidRingEnd; + }, + polygonEnd: function () { + centroidStream.lineStart = centroidLineStart; + centroidStream.lineEnd = centroidLineEnd; + } + }; + +// Arithmetic mean of Cartesian vectors. + function centroidPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi); + centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)); + } + + function centroidPointCartesian(x, y, z) { + ++W0; + X0 += (x - X0) / W0; + Y0 += (y - Y0) / W0; + Z0 += (z - Z0) / W0; + } + + function centroidLineStart() { + centroidStream.point = centroidLinePointFirst; + } + + function centroidLinePointFirst(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi); + x0 = cosPhi * cos$1(lambda); + y0 = cosPhi * sin$1(lambda); + z0 = sin$1(phi); + centroidStream.point = centroidLinePoint; + centroidPointCartesian(x0, y0, z0); + } + + function centroidLinePoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi), + x = cosPhi * cos$1(lambda), + y = cosPhi * sin$1(lambda), + z = sin$1(phi), + w = atan2(sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); + W1 += w; + X1 += w * (x0 + (x0 = x)); + Y1 += w * (y0 + (y0 = y)); + Z1 += w * (z0 + (z0 = z)); + centroidPointCartesian(x0, y0, z0); + } + + function centroidLineEnd() { + centroidStream.point = centroidPoint; + } + +// See J. E. Brock, The Inertia Tensor for a Spherical Triangle, +// J. Applied Mechanics 42, 239 (1975). + function centroidRingStart() { + centroidStream.point = centroidRingPointFirst; + } + + function centroidRingEnd() { + centroidRingPoint(lambda00$2, phi00$2); + centroidStream.point = centroidPoint; + } + + function centroidRingPointFirst(lambda, phi) { + lambda00$2 = lambda, phi00$2 = phi; + lambda *= radians, phi *= radians; + centroidStream.point = centroidRingPoint; + var cosPhi = cos$1(phi); + x0 = cosPhi * cos$1(lambda); + y0 = cosPhi * sin$1(lambda); + z0 = sin$1(phi); + centroidPointCartesian(x0, y0, z0); + } + + function centroidRingPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos$1(phi), + x = cosPhi * cos$1(lambda), + y = cosPhi * sin$1(lambda), + z = sin$1(phi), + cx = y0 * z - z0 * y, + cy = z0 * x - x0 * z, + cz = x0 * y - y0 * x, + m = sqrt(cx * cx + cy * cy + cz * cz), + w = asin(m), // line weight = angle + v = m && -w / m; // area weight multiplier + X2 += v * cx; + Y2 += v * cy; + Z2 += v * cz; + W1 += w; + X1 += w * (x0 + (x0 = x)); + Y1 += w * (y0 + (y0 = y)); + Z1 += w * (z0 + (z0 = z)); + centroidPointCartesian(x0, y0, z0); + } + + function centroid(object) { + W0 = W1 = + X0 = Y0 = Z0 = + X1 = Y1 = Z1 = + X2 = Y2 = Z2 = 0; + geoStream(object, centroidStream); + + var x = X2, + y = Y2, + z = Z2, + m = x * x + y * y + z * z; + + // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid. + if (m < epsilon2$1) { + x = X1, y = Y1, z = Z1; + // If the feature has zero length, fall back to arithmetic mean of point vectors. + if (W1 < epsilon$2) + x = X0, y = Y0, z = Z0; + m = x * x + y * y + z * z; + // If the feature still has an undefined ccentroid, then return. + if (m < epsilon2$1) + return [NaN, NaN]; + } + + return [atan2(y, x) * degrees$1, asin(z / sqrt(m)) * degrees$1]; + } + + function constant$8(x) { + return function () { + return x; + }; + } + + function compose(a, b) { + + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); + } + + if (a.invert && b.invert) + compose.invert = function (x, y) { + return x = b.invert(x, y), x && a.invert(x[0], x[1]); + }; + + return compose; + } + + function rotationIdentity(lambda, phi) { + return [abs(lambda) > pi$3 ? lambda + Math.round(-lambda / tau$3) * tau$3 : lambda, phi]; + } + + rotationIdentity.invert = rotationIdentity; + + function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { + return (deltaLambda %= tau$3) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) + : rotationLambda(deltaLambda)) + : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) + : rotationIdentity); + } + + function forwardRotationLambda(deltaLambda) { + return function (lambda, phi) { + return lambda += deltaLambda, [lambda > pi$3 ? lambda - tau$3 : lambda < -pi$3 ? lambda + tau$3 : lambda, phi]; + }; + } + + function rotationLambda(deltaLambda) { + var rotation = forwardRotationLambda(deltaLambda); + rotation.invert = forwardRotationLambda(-deltaLambda); + return rotation; + } + + function rotationPhiGamma(deltaPhi, deltaGamma) { + var cosDeltaPhi = cos$1(deltaPhi), + sinDeltaPhi = sin$1(deltaPhi), + cosDeltaGamma = cos$1(deltaGamma), + sinDeltaGamma = sin$1(deltaGamma); + + function rotation(lambda, phi) { + var cosPhi = cos$1(phi), + x = cos$1(lambda) * cosPhi, + y = sin$1(lambda) * cosPhi, + z = sin$1(phi), + k = z * cosDeltaPhi + x * sinDeltaPhi; + return [ + atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), + asin(k * cosDeltaGamma + y * sinDeltaGamma) + ]; + } + + rotation.invert = function (lambda, phi) { + var cosPhi = cos$1(phi), + x = cos$1(lambda) * cosPhi, + y = sin$1(lambda) * cosPhi, + z = sin$1(phi), + k = z * cosDeltaGamma - y * sinDeltaGamma; + return [ + atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), + asin(k * cosDeltaPhi - x * sinDeltaPhi) + ]; + }; + + return rotation; + } + + function rotation(rotate) { + rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0); + + function forward(coordinates) { + coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians); + return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; + } + + forward.invert = function (coordinates) { + coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians); + return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates; + }; + + return forward; + } + +// Generates a circle centered at [0°, 0°], with a given radius and precision. + function circleStream(stream, radius, delta, direction, t0, t1) { + if (!delta) + return; + var cosRadius = cos$1(radius), + sinRadius = sin$1(radius), + step = direction * delta; + if (t0 == null) { + t0 = radius + direction * tau$3; + t1 = radius - step / 2; + } else { + t0 = circleRadius(cosRadius, t0); + t1 = circleRadius(cosRadius, t1); + if (direction > 0 ? t0 < t1 : t0 > t1) + t0 += direction * tau$3; + } + for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { + point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]); + stream.point(point[0], point[1]); + } + } + +// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. + function circleRadius(cosRadius, point) { + point = cartesian(point), point[0] -= cosRadius; + cartesianNormalizeInPlace(point); + var radius = acos(-point[1]); + return ((-point[2] < 0 ? -radius : radius) + tau$3 - epsilon$2) % tau$3; + } + + function circle() { + var center = constant$8([0, 0]), + radius = constant$8(90), + precision = constant$8(6), + ring, + rotate, + stream = {point: point}; + + function point(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= degrees$1, x[1] *= degrees$1; + } + + function circle() { + var c = center.apply(this, arguments), + r = radius.apply(this, arguments) * radians, + p = precision.apply(this, arguments) * radians; + ring = []; + rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert; + circleStream(stream, r, p, 1); + c = {type: "Polygon", coordinates: [ring]}; + ring = rotate = null; + return c; + } + + circle.center = function (_) { + return arguments.length ? (center = typeof _ === "function" ? _ : constant$8([+_[0], +_[1]]), circle) : center; + }; + + circle.radius = function (_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant$8(+_), circle) : radius; + }; + + circle.precision = function (_) { + return arguments.length ? (precision = typeof _ === "function" ? _ : constant$8(+_), circle) : precision; + }; + + return circle; + } + + function clipBuffer() { + var lines = [], + line; + return { + point: function (x, y) { + line.push([x, y]); + }, + lineStart: function () { + lines.push(line = []); + }, + lineEnd: noop$2, + rejoin: function () { + if (lines.length > 1) + lines.push(lines.pop().concat(lines.shift())); + }, + result: function () { + var result = lines; + lines = []; + line = null; + return result; + } + }; + } + + function pointEqual(a, b) { + return abs(a[0] - b[0]) < epsilon$2 && abs(a[1] - b[1]) < epsilon$2; + } + + function Intersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; // another intersection + this.e = entry; // is an entry? + this.v = false; // visited + this.n = this.p = null; // next & previous + } + +// A generalized polygon clipping algorithm: given a polygon that has been cut +// into its visible line segments, and rejoins the segments by interpolating +// along the clip edge. + function clipRejoin(segments, compareIntersection, startInside, interpolate, stream) { + var subject = [], + clip = [], + i, + n; + + segments.forEach(function (segment) { + if ((n = segment.length - 1) <= 0) + return; + var n, p0 = segment[0], p1 = segment[n], x; + + // If the first and last points of a segment are coincident, then treat as a + // closed ring. TODO if all rings are closed, then the winding order of the + // exterior ring should be checked. + if (pointEqual(p0, p1)) { + stream.lineStart(); + for (i = 0; i < n; ++i) + stream.point((p0 = segment[i])[0], p0[1]); + stream.lineEnd(); + return; + } + + subject.push(x = new Intersection(p0, segment, null, true)); + clip.push(x.o = new Intersection(p0, null, x, false)); + subject.push(x = new Intersection(p1, segment, null, false)); + clip.push(x.o = new Intersection(p1, null, x, true)); + }); + + if (!subject.length) + return; + + clip.sort(compareIntersection); + link$1(subject); + link$1(clip); + + for (i = 0, n = clip.length; i < n; ++i) { + clip[i].e = startInside = !startInside; + } + + var start = subject[0], + points, + point; + + while (1) { + // Find first unvisited intersection. + var current = start, + isSubject = true; + while (current.v) + if ((current = current.n) === start) + return; + points = current.z; + stream.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (i = 0, n = points.length; i < n; ++i) + stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, stream); + } + current = current.n; + } else { + if (isSubject) { + points = current.p.z; + for (i = points.length - 1; i >= 0; --i) + stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.p.x, -1, stream); + } + current = current.p; + } + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + stream.lineEnd(); + } + } + + function link$1(array) { + if (!(n = array.length)) + return; + var n, + i = 0, + a = array[0], + b; + while (++i < n) { + a.n = b = array[i]; + b.p = a; + a = b; + } + a.n = b = array[0]; + b.p = a; + } + + var sum$1 = adder(); + + function longitude(point) { + if (abs(point[0]) <= pi$3) + return point[0]; + else + return sign(point[0]) * ((abs(point[0]) + pi$3) % tau$3 - pi$3); + } + + function polygonContains(polygon, point) { + var lambda = longitude(point), + phi = point[1], + sinPhi = sin$1(phi), + normal = [sin$1(lambda), -cos$1(lambda), 0], + angle = 0, + winding = 0; + + sum$1.reset(); + + if (sinPhi === 1) + phi = halfPi$2 + epsilon$2; + else if (sinPhi === -1) + phi = -halfPi$2 - epsilon$2; + + for (var i = 0, n = polygon.length; i < n; ++i) { + if (!(m = (ring = polygon[i]).length)) + continue; + var ring, + m, + point0 = ring[m - 1], + lambda0 = longitude(point0), + phi0 = point0[1] / 2 + quarterPi, + sinPhi0 = sin$1(phi0), + cosPhi0 = cos$1(phi0); + + for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) { + var point1 = ring[j], + lambda1 = longitude(point1), + phi1 = point1[1] / 2 + quarterPi, + sinPhi1 = sin$1(phi1), + cosPhi1 = cos$1(phi1), + delta = lambda1 - lambda0, + sign = delta >= 0 ? 1 : -1, + absDelta = sign * delta, + antimeridian = absDelta > pi$3, + k = sinPhi0 * sinPhi1; + + sum$1.add(atan2(k * sign * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta))); + angle += antimeridian ? delta + sign * tau$3 : delta; + + // Are the longitudes either side of the point’s meridian (lambda), + // and are the latitudes smaller than the parallel (phi)? + if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) { + var arc = cartesianCross(cartesian(point0), cartesian(point1)); + cartesianNormalizeInPlace(arc); + var intersection = cartesianCross(normal, arc); + cartesianNormalizeInPlace(intersection); + var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]); + if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) { + winding += antimeridian ^ delta >= 0 ? 1 : -1; + } + } + } + } + + // First, determine whether the South pole is inside or outside: + // + // It is inside if: + // * the polygon winds around it in a clockwise direction. + // * the polygon does not (cumulatively) wind around it, but has a negative + // (counter-clockwise) area. + // + // Second, count the (signed) number of times a segment crosses a lambda + // from the point to the South pole. If it is zero, then the point is the + // same side as the South pole. + + return (angle < -epsilon$2 || angle < epsilon$2 && sum$1 < -epsilon$2) ^ (winding & 1); + } + + function clip(pointVisible, clipLine, interpolate, start) { + return function (sink) { + var line = clipLine(sink), + ringBuffer = clipBuffer(), + ringSink = clipLine(ringBuffer), + polygonStarted = false, + polygon, + segments, + ring; + + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function () { + clip.point = pointRing; + clip.lineStart = ringStart; + clip.lineEnd = ringEnd; + segments = []; + polygon = []; + }, + polygonEnd: function () { + clip.point = point; + clip.lineStart = lineStart; + clip.lineEnd = lineEnd; + segments = merge(segments); + var startInside = polygonContains(polygon, start); + if (segments.length) { + if (!polygonStarted) + sink.polygonStart(), polygonStarted = true; + clipRejoin(segments, compareIntersection, startInside, interpolate, sink); + } else if (startInside) { + if (!polygonStarted) + sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + } + if (polygonStarted) + sink.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function () { + sink.polygonStart(); + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + sink.polygonEnd(); + } + }; + + function point(lambda, phi) { + if (pointVisible(lambda, phi)) + sink.point(lambda, phi); + } + + function pointLine(lambda, phi) { + line.point(lambda, phi); + } + + function lineStart() { + clip.point = pointLine; + line.lineStart(); + } + + function lineEnd() { + clip.point = point; + line.lineEnd(); + } + + function pointRing(lambda, phi) { + ring.push([lambda, phi]); + ringSink.point(lambda, phi); + } + + function ringStart() { + ringSink.lineStart(); + ring = []; + } + + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringSink.lineEnd(); + + var clean = ringSink.clean(), + ringSegments = ringBuffer.result(), + i, n = ringSegments.length, m, + segment, + point; + + ring.pop(); + polygon.push(ring); + ring = null; + + if (!n) + return; + + // No intersections. + if (clean & 1) { + segment = ringSegments[0]; + if ((m = segment.length - 1) > 0) { + if (!polygonStarted) + sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + for (i = 0; i < m; ++i) + sink.point((point = segment[i])[0], point[1]); + sink.lineEnd(); + } + return; + } + + // Rejoin connected segments. + // TODO reuse ringBuffer.rejoin()? + if (n > 1 && clean & 2) + ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + + segments.push(ringSegments.filter(validSegment)); + } + + return clip; + }; + } + + function validSegment(segment) { + return segment.length > 1; + } + +// Intersections are sorted along the clip edge. For both antimeridian cutting +// and circle clipping, the same comparison is used. + function compareIntersection(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - halfPi$2 - epsilon$2 : halfPi$2 - a[1]) + - ((b = b.x)[0] < 0 ? b[1] - halfPi$2 - epsilon$2 : halfPi$2 - b[1]); + } + + var clipAntimeridian = clip( + function () { + return true; + }, + clipAntimeridianLine, + clipAntimeridianInterpolate, + [-pi$3, -halfPi$2] + ); + +// Takes a line and cuts into visible segments. Return values: 0 - there were +// intersections or the line was empty; 1 - no intersections; 2 - there were +// intersections, and the first and last segments should be rejoined. + function clipAntimeridianLine(stream) { + var lambda0 = NaN, + phi0 = NaN, + sign0 = NaN, + clean; // no intersections + + return { + lineStart: function () { + stream.lineStart(); + clean = 1; + }, + point: function (lambda1, phi1) { + var sign1 = lambda1 > 0 ? pi$3 : -pi$3, + delta = abs(lambda1 - lambda0); + if (abs(delta - pi$3) < epsilon$2) { // line crosses a pole + stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$2 : -halfPi$2); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + stream.point(lambda1, phi0); + clean = 0; + } else if (sign0 !== sign1 && delta >= pi$3) { // line crosses antimeridian + if (abs(lambda0 - sign0) < epsilon$2) + lambda0 -= sign0 * epsilon$2; // handle degeneracies + if (abs(lambda1 - sign1) < epsilon$2) + lambda1 -= sign1 * epsilon$2; + phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + clean = 0; + } + stream.point(lambda0 = lambda1, phi0 = phi1); + sign0 = sign1; + }, + lineEnd: function () { + stream.lineEnd(); + lambda0 = phi0 = NaN; + }, + clean: function () { + return 2 - clean; // if intersections, rejoin first and last segments + } + }; + } + + function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) { + var cosPhi0, + cosPhi1, + sinLambda0Lambda1 = sin$1(lambda0 - lambda1); + return abs(sinLambda0Lambda1) > epsilon$2 + ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1) + - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0)) + / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) + : (phi0 + phi1) / 2; + } + + function clipAntimeridianInterpolate(from, to, direction, stream) { + var phi; + if (from == null) { + phi = direction * halfPi$2; + stream.point(-pi$3, phi); + stream.point(0, phi); + stream.point(pi$3, phi); + stream.point(pi$3, 0); + stream.point(pi$3, -phi); + stream.point(0, -phi); + stream.point(-pi$3, -phi); + stream.point(-pi$3, 0); + stream.point(-pi$3, phi); + } else if (abs(from[0] - to[0]) > epsilon$2) { + var lambda = from[0] < to[0] ? pi$3 : -pi$3; + phi = direction * lambda / 2; + stream.point(-lambda, phi); + stream.point(0, phi); + stream.point(lambda, phi); + } else { + stream.point(to[0], to[1]); + } + } + + function clipCircle(radius) { + var cr = cos$1(radius), + delta = 6 * radians, + smallRadius = cr > 0, + notHemisphere = abs(cr) > epsilon$2; // TODO optimise for this common case + + function interpolate(from, to, direction, stream) { + circleStream(stream, radius, delta, direction, from, to); + } + + function visible(lambda, phi) { + return cos$1(lambda) * cos$1(phi) > cr; + } + + // Takes a line and cuts into visible segments. Return values used for polygon + // clipping: 0 - there were intersections or the line was empty; 1 - no + // intersections 2 - there were intersections, and the first and last segments + // should be rejoined. + function clipLine(stream) { + var point0, // previous point + c0, // code for previous point + v0, // visibility of previous point + v00, // visibility of first point + clean; // no intersections + return { + lineStart: function () { + v00 = v0 = false; + clean = 1; + }, + point: function (lambda, phi) { + var point1 = [lambda, phi], + point2, + v = visible(lambda, phi), + c = smallRadius + ? v ? 0 : code(lambda, phi) + : v ? code(lambda + (lambda < 0 ? pi$3 : -pi$3), phi) : 0; + if (!point0 && (v00 = v0 = v)) + stream.lineStart(); + // Handle degeneracies. + // TODO ignore if not clipping polygons. + if (v !== v0) { + point2 = intersect(point0, point1); + if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) { + point1[0] += epsilon$2; + point1[1] += epsilon$2; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + // outside going in + stream.lineStart(); + point2 = intersect(point1, point0); + stream.point(point2[0], point2[1]); + } else { + // inside going out + point2 = intersect(point0, point1); + stream.point(point2[0], point2[1]); + stream.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + // If the codes for two points are different, or are both zero, + // and there this segment intersects with the small circle. + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + } else { + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !pointEqual(point0, point1))) { + stream.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function () { + if (v0) + stream.lineEnd(); + point0 = null; + }, + // Rejoin first and last segments if there were intersections and the first + // and last points were visible. + clean: function () { + return clean | ((v00 && v0) << 1); + } + }; + } + + // Intersects the great circle between a and b with the clip circle. + function intersect(a, b, two) { + var pa = cartesian(a), + pb = cartesian(b); + + // We have two planes, n1.p = d1 and n2.p = d2. + // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2). + var n1 = [1, 0, 0], // normal + n2 = cartesianCross(pa, pb), + n2n2 = cartesianDot(n2, n2), + n1n2 = n2[0], // cartesianDot(n1, n2), + determinant = n2n2 - n1n2 * n1n2; + + // Two polar points. + if (!determinant) + return !two && a; + + var c1 = cr * n2n2 / determinant, + c2 = -cr * n1n2 / determinant, + n1xn2 = cartesianCross(n1, n2), + A = cartesianScale(n1, c1), + B = cartesianScale(n2, c2); + cartesianAddInPlace(A, B); + + // Solve |p(t)|^2 = 1. + var u = n1xn2, + w = cartesianDot(A, u), + uu = cartesianDot(u, u), + t2 = w * w - uu * (cartesianDot(A, A) - 1); + + if (t2 < 0) + return; + + var t = sqrt(t2), + q = cartesianScale(u, (-w - t) / uu); + cartesianAddInPlace(q, A); + q = spherical(q); + + if (!two) + return q; + + // Two intersection points. + var lambda0 = a[0], + lambda1 = b[0], + phi0 = a[1], + phi1 = b[1], + z; + + if (lambda1 < lambda0) + z = lambda0, lambda0 = lambda1, lambda1 = z; + + var delta = lambda1 - lambda0, + polar = abs(delta - pi$3) < epsilon$2, + meridian = polar || delta < epsilon$2; + + if (!polar && phi1 < phi0) + z = phi0, phi0 = phi1, phi1 = z; + + // Check that the first point is between a and b. + if (meridian + ? polar + ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$2 ? phi0 : phi1) + : phi0 <= q[1] && q[1] <= phi1 + : delta > pi$3 ^ (lambda0 <= q[0] && q[0] <= lambda1)) { + var q1 = cartesianScale(u, (-w + t) / uu); + cartesianAddInPlace(q1, A); + return [q, spherical(q1)]; + } + } + + // Generates a 4-bit vector representing the location of a point relative to + // the small circle's bounding box. + function code(lambda, phi) { + var r = smallRadius ? radius : pi$3 - radius, + code = 0; + if (lambda < -r) + code |= 1; // left + else if (lambda > r) + code |= 2; // right + if (phi < -r) + code |= 4; // below + else if (phi > r) + code |= 8; // above + return code; + } + + return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$3, radius - pi$3]); + } + + function clipLine(a, b, x0, y0, x1, y1) { + var ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + t0 = 0, + t1 = 1, + dx = bx - ax, + dy = by - ay, + r; + + r = x0 - ax; + if (!dx && r > 0) + return; + r /= dx; + if (dx < 0) { + if (r < t0) + return; + if (r < t1) + t1 = r; + } else if (dx > 0) { + if (r > t1) + return; + if (r > t0) + t0 = r; + } + + r = x1 - ax; + if (!dx && r < 0) + return; + r /= dx; + if (dx < 0) { + if (r > t1) + return; + if (r > t0) + t0 = r; + } else if (dx > 0) { + if (r < t0) + return; + if (r < t1) + t1 = r; + } + + r = y0 - ay; + if (!dy && r > 0) + return; + r /= dy; + if (dy < 0) { + if (r < t0) + return; + if (r < t1) + t1 = r; + } else if (dy > 0) { + if (r > t1) + return; + if (r > t0) + t0 = r; + } + + r = y1 - ay; + if (!dy && r < 0) + return; + r /= dy; + if (dy < 0) { + if (r > t1) + return; + if (r > t0) + t0 = r; + } else if (dy > 0) { + if (r < t0) + return; + if (r < t1) + t1 = r; + } + + if (t0 > 0) + a[0] = ax + t0 * dx, a[1] = ay + t0 * dy; + if (t1 < 1) + b[0] = ax + t1 * dx, b[1] = ay + t1 * dy; + return true; + } + + var clipMax = 1e9, clipMin = -clipMax; + +// TODO Use d3-polygon’s polygonContains here for the ring check? +// TODO Eliminate duplicate buffering in clipBuffer and polygon.push? + + function clipRectangle(x0, y0, x1, y1) { + + function visible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; + } + + function interpolate(from, to, direction, stream) { + var a = 0, a1 = 0; + if (from == null + || (a = corner(from, direction)) !== (a1 = corner(to, direction)) + || comparePoint(from, to) < 0 ^ direction > 0) { + do + stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + while ((a = (a + direction + 4) % 4) !== a1); + } else { + stream.point(to[0], to[1]); + } + } + + function corner(p, direction) { + return abs(p[0] - x0) < epsilon$2 ? direction > 0 ? 0 : 3 + : abs(p[0] - x1) < epsilon$2 ? direction > 0 ? 2 : 1 + : abs(p[1] - y0) < epsilon$2 ? direction > 0 ? 1 : 0 + : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon + } + + function compareIntersection(a, b) { + return comparePoint(a.x, b.x); + } + + function comparePoint(a, b) { + var ca = corner(a, 1), + cb = corner(b, 1); + return ca !== cb ? ca - cb + : ca === 0 ? b[1] - a[1] + : ca === 1 ? a[0] - b[0] + : ca === 2 ? a[1] - b[1] + : b[0] - a[0]; + } + + return function (stream) { + var activeStream = stream, + bufferStream = clipBuffer(), + segments, + polygon, + ring, + x__, y__, v__, // first point + x_, y_, v_, // previous point + first, + clean; + + var clipStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: polygonStart, + polygonEnd: polygonEnd + }; + + function point(x, y) { + if (visible(x, y)) + activeStream.point(x, y); + } + + function polygonInside() { + var winding = 0; + + for (var i = 0, n = polygon.length; i < n; ++i) { + for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) { + a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1]; + if (a1 <= y1) { + if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) + ++winding; + } else { + if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) + --winding; + } + } + } + + return winding; + } + + // Buffer geometry within a polygon and then clip it en masse. + function polygonStart() { + activeStream = bufferStream, segments = [], polygon = [], clean = true; + } + + function polygonEnd() { + var startInside = polygonInside(), + cleanInside = clean && startInside, + visible = (segments = merge(segments)).length; + if (cleanInside || visible) { + stream.polygonStart(); + if (cleanInside) { + stream.lineStart(); + interpolate(null, null, 1, stream); + stream.lineEnd(); + } + if (visible) { + clipRejoin(segments, compareIntersection, startInside, interpolate, stream); + } + stream.polygonEnd(); + } + activeStream = stream, segments = polygon = ring = null; + } + + function lineStart() { + clipStream.point = linePoint; + if (polygon) + polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } + + // TODO rather than special-case polygons, simply handle them separately. + // Ideally, coincident intersection points should be jittered to avoid + // clipping issues. + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) + bufferStream.rejoin(); + segments.push(bufferStream.result()); + } + clipStream.point = point; + if (v_) + activeStream.lineEnd(); + } + + function linePoint(x, y) { + var v = visible(x, y); + if (polygon) + ring.push([x, y]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + } + } else { + if (v && v_) + activeStream.point(x, y); + else { + var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], + b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))]; + if (clipLine(a, b, x0, y0, x1, y1)) { + if (!v_) { + activeStream.lineStart(); + activeStream.point(a[0], a[1]); + } + activeStream.point(b[0], b[1]); + if (!v) + activeStream.lineEnd(); + clean = false; + } else if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + clean = false; + } + } + } + x_ = x, y_ = y, v_ = v; + } + + return clipStream; + }; + } + + function extent$1() { + var x0 = 0, + y0 = 0, + x1 = 960, + y1 = 500, + cache, + cacheStream, + clip; + + return clip = { + stream: function (stream) { + return cache && cacheStream === stream ? cache : cache = clipRectangle(x0, y0, x1, y1)(cacheStream = stream); + }, + extent: function (_) { + return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]]; + } + }; + } + + var lengthSum = adder(), + lambda0$2, + sinPhi0$1, + cosPhi0$1; + + var lengthStream = { + sphere: noop$2, + point: noop$2, + lineStart: lengthLineStart, + lineEnd: noop$2, + polygonStart: noop$2, + polygonEnd: noop$2 + }; + + function lengthLineStart() { + lengthStream.point = lengthPointFirst; + lengthStream.lineEnd = lengthLineEnd; + } + + function lengthLineEnd() { + lengthStream.point = lengthStream.lineEnd = noop$2; + } + + function lengthPointFirst(lambda, phi) { + lambda *= radians, phi *= radians; + lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi); + lengthStream.point = lengthPoint; + } + + function lengthPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var sinPhi = sin$1(phi), + cosPhi = cos$1(phi), + delta = abs(lambda - lambda0$2), + cosDelta = cos$1(delta), + sinDelta = sin$1(delta), + x = cosPhi * sinDelta, + y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta, + z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta; + lengthSum.add(atan2(sqrt(x * x + y * y), z)); + lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi; + } + + function length$1(object) { + lengthSum.reset(); + geoStream(object, lengthStream); + return +lengthSum; + } + + var coordinates = [null, null], + object$1 = {type: "LineString", coordinates: coordinates}; + + function distance(a, b) { + coordinates[0] = a; + coordinates[1] = b; + return length$1(object$1); + } + + var containsObjectType = { + Feature: function (object, point) { + return containsGeometry(object.geometry, point); + }, + FeatureCollection: function (object, point) { + var features = object.features, i = -1, n = features.length; + while (++i < n) + if (containsGeometry(features[i].geometry, point)) + return true; + return false; + } + }; + + var containsGeometryType = { + Sphere: function () { + return true; + }, + Point: function (object, point) { + return containsPoint(object.coordinates, point); + }, + MultiPoint: function (object, point) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) + if (containsPoint(coordinates[i], point)) + return true; + return false; + }, + LineString: function (object, point) { + return containsLine(object.coordinates, point); + }, + MultiLineString: function (object, point) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) + if (containsLine(coordinates[i], point)) + return true; + return false; + }, + Polygon: function (object, point) { + return containsPolygon(object.coordinates, point); + }, + MultiPolygon: function (object, point) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) + if (containsPolygon(coordinates[i], point)) + return true; + return false; + }, + GeometryCollection: function (object, point) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) + if (containsGeometry(geometries[i], point)) + return true; + return false; + } + }; + + function containsGeometry(geometry, point) { + return geometry && containsGeometryType.hasOwnProperty(geometry.type) + ? containsGeometryType[geometry.type](geometry, point) + : false; + } + + function containsPoint(coordinates, point) { + return distance(coordinates, point) === 0; + } + + function containsLine(coordinates, point) { + var ao, bo, ab; + for (var i = 0, n = coordinates.length; i < n; i++) { + bo = distance(coordinates[i], point); + if (bo === 0) + return true; + if (i > 0) { + ab = distance(coordinates[i], coordinates[i - 1]); + if ( + ab > 0 && + ao <= ab && + bo <= ab && + (ao + bo - ab) * (1 - Math.pow((ao - bo) / ab, 2)) < epsilon2$1 * ab + ) + return true; + } + ao = bo; + } + return false; + } + + function containsPolygon(coordinates, point) { + return !!polygonContains(coordinates.map(ringRadians), pointRadians(point)); + } + + function ringRadians(ring) { + return ring = ring.map(pointRadians), ring.pop(), ring; + } + + function pointRadians(point) { + return [point[0] * radians, point[1] * radians]; + } + + function contains$1(object, point) { + return (object && containsObjectType.hasOwnProperty(object.type) + ? containsObjectType[object.type] + : containsGeometry)(object, point); + } + + function graticuleX(y0, y1, dy) { + var y = sequence(y0, y1 - epsilon$2, dy).concat(y1); + return function (x) { + return y.map(function (y) { + return [x, y]; + }); + }; + } + + function graticuleY(x0, x1, dx) { + var x = sequence(x0, x1 - epsilon$2, dx).concat(x1); + return function (y) { + return x.map(function (x) { + return [x, y]; + }); + }; + } + + function graticule() { + var x1, x0, X1, X0, + y1, y0, Y1, Y0, + dx = 10, dy = dx, DX = 90, DY = 360, + x, y, X, Y, + precision = 2.5; + + function graticule() { + return {type: "MultiLineString", coordinates: lines()}; + } + + function lines() { + return sequence(ceil(X0 / DX) * DX, X1, DX).map(X) + .concat(sequence(ceil(Y0 / DY) * DY, Y1, DY).map(Y)) + .concat(sequence(ceil(x0 / dx) * dx, x1, dx).filter(function (x) { + return abs(x % DX) > epsilon$2; + }).map(x)) + .concat(sequence(ceil(y0 / dy) * dy, y1, dy).filter(function (y) { + return abs(y % DY) > epsilon$2; + }).map(y)); + } + + graticule.lines = function () { + return lines().map(function (coordinates) { + return {type: "LineString", coordinates: coordinates}; + }); + }; + + graticule.outline = function () { + return { + type: "Polygon", + coordinates: [ + X(X0).concat( + Y(Y1).slice(1), + X(X1).reverse().slice(1), + Y(Y0).reverse().slice(1)) + ] + }; + }; + + graticule.extent = function (_) { + if (!arguments.length) + return graticule.extentMinor(); + return graticule.extentMajor(_).extentMinor(_); + }; + + graticule.extentMajor = function (_) { + if (!arguments.length) + return [[X0, Y0], [X1, Y1]]; + X0 = +_[0][0], X1 = +_[1][0]; + Y0 = +_[0][1], Y1 = +_[1][1]; + if (X0 > X1) + _ = X0, X0 = X1, X1 = _; + if (Y0 > Y1) + _ = Y0, Y0 = Y1, Y1 = _; + return graticule.precision(precision); + }; + + graticule.extentMinor = function (_) { + if (!arguments.length) + return [[x0, y0], [x1, y1]]; + x0 = +_[0][0], x1 = +_[1][0]; + y0 = +_[0][1], y1 = +_[1][1]; + if (x0 > x1) + _ = x0, x0 = x1, x1 = _; + if (y0 > y1) + _ = y0, y0 = y1, y1 = _; + return graticule.precision(precision); + }; + + graticule.step = function (_) { + if (!arguments.length) + return graticule.stepMinor(); + return graticule.stepMajor(_).stepMinor(_); + }; + + graticule.stepMajor = function (_) { + if (!arguments.length) + return [DX, DY]; + DX = +_[0], DY = +_[1]; + return graticule; + }; + + graticule.stepMinor = function (_) { + if (!arguments.length) + return [dx, dy]; + dx = +_[0], dy = +_[1]; + return graticule; + }; + + graticule.precision = function (_) { + if (!arguments.length) + return precision; + precision = +_; + x = graticuleX(y0, y1, 90); + y = graticuleY(x0, x1, precision); + X = graticuleX(Y0, Y1, 90); + Y = graticuleY(X0, X1, precision); + return graticule; + }; + + return graticule + .extentMajor([[-180, -90 + epsilon$2], [180, 90 - epsilon$2]]) + .extentMinor([[-180, -80 - epsilon$2], [180, 80 + epsilon$2]]); + } + + function graticule10() { + return graticule()(); + } + + function interpolate$1(a, b) { + var x0 = a[0] * radians, + y0 = a[1] * radians, + x1 = b[0] * radians, + y1 = b[1] * radians, + cy0 = cos$1(y0), + sy0 = sin$1(y0), + cy1 = cos$1(y1), + sy1 = sin$1(y1), + kx0 = cy0 * cos$1(x0), + ky0 = cy0 * sin$1(x0), + kx1 = cy1 * cos$1(x1), + ky1 = cy1 * sin$1(x1), + d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))), + k = sin$1(d); + + var interpolate = d ? function (t) { + var B = sin$1(t *= d) / k, + A = sin$1(d - t) / k, + x = A * kx0 + B * kx1, + y = A * ky0 + B * ky1, + z = A * sy0 + B * sy1; + return [ + atan2(y, x) * degrees$1, + atan2(z, sqrt(x * x + y * y)) * degrees$1 + ]; + } : function () { + return [x0 * degrees$1, y0 * degrees$1]; + }; + + interpolate.distance = d; + + return interpolate; + } + + function identity$4(x) { + return x; + } + + var areaSum$1 = adder(), + areaRingSum$1 = adder(), + x00, + y00, + x0$1, + y0$1; + + var areaStream$1 = { + point: noop$2, + lineStart: noop$2, + lineEnd: noop$2, + polygonStart: function () { + areaStream$1.lineStart = areaRingStart$1; + areaStream$1.lineEnd = areaRingEnd$1; + }, + polygonEnd: function () { + areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$2; + areaSum$1.add(abs(areaRingSum$1)); + areaRingSum$1.reset(); + }, + result: function () { + var area = areaSum$1 / 2; + areaSum$1.reset(); + return area; + } + }; + + function areaRingStart$1() { + areaStream$1.point = areaPointFirst$1; + } + + function areaPointFirst$1(x, y) { + areaStream$1.point = areaPoint$1; + x00 = x0$1 = x, y00 = y0$1 = y; + } + + function areaPoint$1(x, y) { + areaRingSum$1.add(y0$1 * x - x0$1 * y); + x0$1 = x, y0$1 = y; + } + + function areaRingEnd$1() { + areaPoint$1(x00, y00); + } + + var x0$2 = Infinity, + y0$2 = x0$2, + x1 = -x0$2, + y1 = x1; + + var boundsStream$1 = { + point: boundsPoint$1, + lineStart: noop$2, + lineEnd: noop$2, + polygonStart: noop$2, + polygonEnd: noop$2, + result: function () { + var bounds = [[x0$2, y0$2], [x1, y1]]; + x1 = y1 = -(y0$2 = x0$2 = Infinity); + return bounds; + } + }; + + function boundsPoint$1(x, y) { + if (x < x0$2) + x0$2 = x; + if (x > x1) + x1 = x; + if (y < y0$2) + y0$2 = y; + if (y > y1) + y1 = y; + } + +// TODO Enforce positive area for exterior, negative area for interior? + + var X0$1 = 0, + Y0$1 = 0, + Z0$1 = 0, + X1$1 = 0, + Y1$1 = 0, + Z1$1 = 0, + X2$1 = 0, + Y2$1 = 0, + Z2$1 = 0, + x00$1, + y00$1, + x0$3, + y0$3; + + var centroidStream$1 = { + point: centroidPoint$1, + lineStart: centroidLineStart$1, + lineEnd: centroidLineEnd$1, + polygonStart: function () { + centroidStream$1.lineStart = centroidRingStart$1; + centroidStream$1.lineEnd = centroidRingEnd$1; + }, + polygonEnd: function () { + centroidStream$1.point = centroidPoint$1; + centroidStream$1.lineStart = centroidLineStart$1; + centroidStream$1.lineEnd = centroidLineEnd$1; + }, + result: function () { + var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1] + : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1] + : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1] + : [NaN, NaN]; + X0$1 = Y0$1 = Z0$1 = + X1$1 = Y1$1 = Z1$1 = + X2$1 = Y2$1 = Z2$1 = 0; + return centroid; + } + }; + + function centroidPoint$1(x, y) { + X0$1 += x; + Y0$1 += y; + ++Z0$1; + } + + function centroidLineStart$1() { + centroidStream$1.point = centroidPointFirstLine; + } + + function centroidPointFirstLine(x, y) { + centroidStream$1.point = centroidPointLine; + centroidPoint$1(x0$3 = x, y0$3 = y); + } + + function centroidPointLine(x, y) { + var dx = x - x0$3, dy = y - y0$3, z = sqrt(dx * dx + dy * dy); + X1$1 += z * (x0$3 + x) / 2; + Y1$1 += z * (y0$3 + y) / 2; + Z1$1 += z; + centroidPoint$1(x0$3 = x, y0$3 = y); + } + + function centroidLineEnd$1() { + centroidStream$1.point = centroidPoint$1; + } + + function centroidRingStart$1() { + centroidStream$1.point = centroidPointFirstRing; + } + + function centroidRingEnd$1() { + centroidPointRing(x00$1, y00$1); + } + + function centroidPointFirstRing(x, y) { + centroidStream$1.point = centroidPointRing; + centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y); + } + + function centroidPointRing(x, y) { + var dx = x - x0$3, + dy = y - y0$3, + z = sqrt(dx * dx + dy * dy); + + X1$1 += z * (x0$3 + x) / 2; + Y1$1 += z * (y0$3 + y) / 2; + Z1$1 += z; + + z = y0$3 * x - x0$3 * y; + X2$1 += z * (x0$3 + x); + Y2$1 += z * (y0$3 + y); + Z2$1 += z * 3; + centroidPoint$1(x0$3 = x, y0$3 = y); + } + + function PathContext(context) { + this._context = context; + } + + PathContext.prototype = { + _radius: 4.5, + pointRadius: function (_) { + return this._radius = _, this; + }, + polygonStart: function () { + this._line = 0; + }, + polygonEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._point = 0; + }, + lineEnd: function () { + if (this._line === 0) + this._context.closePath(); + this._point = NaN; + }, + point: function (x, y) { + switch (this._point) { + case 0: + { + this._context.moveTo(x, y); + this._point = 1; + break; + } + case 1: + { + this._context.lineTo(x, y); + break; + } + default: + { + this._context.moveTo(x + this._radius, y); + this._context.arc(x, y, this._radius, 0, tau$3); + break; + } + } + }, + result: noop$2 + }; + + var lengthSum$1 = adder(), + lengthRing, + x00$2, + y00$2, + x0$4, + y0$4; + + var lengthStream$1 = { + point: noop$2, + lineStart: function () { + lengthStream$1.point = lengthPointFirst$1; + }, + lineEnd: function () { + if (lengthRing) + lengthPoint$1(x00$2, y00$2); + lengthStream$1.point = noop$2; + }, + polygonStart: function () { + lengthRing = true; + }, + polygonEnd: function () { + lengthRing = null; + }, + result: function () { + var length = +lengthSum$1; + lengthSum$1.reset(); + return length; + } + }; + + function lengthPointFirst$1(x, y) { + lengthStream$1.point = lengthPoint$1; + x00$2 = x0$4 = x, y00$2 = y0$4 = y; + } + + function lengthPoint$1(x, y) { + x0$4 -= x, y0$4 -= y; + lengthSum$1.add(sqrt(x0$4 * x0$4 + y0$4 * y0$4)); + x0$4 = x, y0$4 = y; + } + + function PathString() { + this._string = []; + } + + PathString.prototype = { + _radius: 4.5, + _circle: circle$1(4.5), + pointRadius: function (_) { + if ((_ = +_) !== this._radius) + this._radius = _, this._circle = null; + return this; + }, + polygonStart: function () { + this._line = 0; + }, + polygonEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._point = 0; + }, + lineEnd: function () { + if (this._line === 0) + this._string.push("Z"); + this._point = NaN; + }, + point: function (x, y) { + switch (this._point) { + case 0: + { + this._string.push("M", x, ",", y); + this._point = 1; + break; + } + case 1: + { + this._string.push("L", x, ",", y); + break; + } + default: + { + if (this._circle == null) + this._circle = circle$1(this._radius); + this._string.push("M", x, ",", y, this._circle); + break; + } + } + }, + result: function () { + if (this._string.length) { + var result = this._string.join(""); + this._string = []; + return result; + } else { + return null; + } + } + }; + + function circle$1(radius) { + return "m0," + radius + + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + + "z"; + } + + function index$1(projection, context) { + var pointRadius = 4.5, + projectionStream, + contextStream; + + function path(object) { + if (object) { + if (typeof pointRadius === "function") + contextStream.pointRadius(+pointRadius.apply(this, arguments)); + geoStream(object, projectionStream(contextStream)); + } + return contextStream.result(); + } + + path.area = function (object) { + geoStream(object, projectionStream(areaStream$1)); + return areaStream$1.result(); + }; + + path.measure = function (object) { + geoStream(object, projectionStream(lengthStream$1)); + return lengthStream$1.result(); + }; + + path.bounds = function (object) { + geoStream(object, projectionStream(boundsStream$1)); + return boundsStream$1.result(); + }; + + path.centroid = function (object) { + geoStream(object, projectionStream(centroidStream$1)); + return centroidStream$1.result(); + }; + + path.projection = function (_) { + return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection; + }; + + path.context = function (_) { + if (!arguments.length) + return context; + contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _); + if (typeof pointRadius !== "function") + contextStream.pointRadius(pointRadius); + return path; + }; + + path.pointRadius = function (_) { + if (!arguments.length) + return pointRadius; + pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); + return path; + }; + + return path.projection(projection).context(context); + } + + function transform(methods) { + return { + stream: transformer(methods) + }; + } + + function transformer(methods) { + return function (stream) { + var s = new TransformStream; + for (var key in methods) + s[key] = methods[key]; + s.stream = stream; + return s; + }; + } + + function TransformStream() {} + + TransformStream.prototype = { + constructor: TransformStream, + point: function (x, y) { + this.stream.point(x, y); + }, + sphere: function () { + this.stream.sphere(); + }, + lineStart: function () { + this.stream.lineStart(); + }, + lineEnd: function () { + this.stream.lineEnd(); + }, + polygonStart: function () { + this.stream.polygonStart(); + }, + polygonEnd: function () { + this.stream.polygonEnd(); + } + }; + + function fit(projection, fitBounds, object) { + var clip = projection.clipExtent && projection.clipExtent(); + projection.scale(150).translate([0, 0]); + if (clip != null) + projection.clipExtent(null); + geoStream(object, projection.stream(boundsStream$1)); + fitBounds(boundsStream$1.result()); + if (clip != null) + projection.clipExtent(clip); + return projection; + } + + function fitExtent(projection, extent, object) { + return fit(projection, function (b) { + var w = extent[1][0] - extent[0][0], + h = extent[1][1] - extent[0][1], + k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), + x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2, + y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; + projection.scale(150 * k).translate([x, y]); + }, object); + } + + function fitSize(projection, size, object) { + return fitExtent(projection, [[0, 0], size], object); + } + + function fitWidth(projection, width, object) { + return fit(projection, function (b) { + var w = +width, + k = w / (b[1][0] - b[0][0]), + x = (w - k * (b[1][0] + b[0][0])) / 2, + y = -k * b[0][1]; + projection.scale(150 * k).translate([x, y]); + }, object); + } + + function fitHeight(projection, height, object) { + return fit(projection, function (b) { + var h = +height, + k = h / (b[1][1] - b[0][1]), + x = -k * b[0][0], + y = (h - k * (b[1][1] + b[0][1])) / 2; + projection.scale(150 * k).translate([x, y]); + }, object); + } + + var maxDepth = 16, // maximum depth of subdivision + cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance) + + function resample(project, delta2) { + return +delta2 ? resample$1(project, delta2) : resampleNone(project); + } + + function resampleNone(project) { + return transformer({ + point: function (x, y) { + x = project(x, y); + this.stream.point(x[0], x[1]); + } + }); + } + + function resample$1(project, delta2) { + + function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) { + var dx = x1 - x0, + dy = y1 - y0, + d2 = dx * dx + dy * dy; + if (d2 > 4 * delta2 && depth--) { + var a = a0 + a1, + b = b0 + b1, + c = c0 + c1, + m = sqrt(a * a + b * b + c * c), + phi2 = asin(c /= m), + lambda2 = abs(abs(c) - 1) < epsilon$2 || abs(lambda0 - lambda1) < epsilon$2 ? (lambda0 + lambda1) / 2 : atan2(b, a), + p = project(lambda2, phi2), + x2 = p[0], + y2 = p[1], + dx2 = x2 - x0, + dy2 = y2 - y0, + dz = dy * dx2 - dx * dy2; + if (dz * dz / d2 > delta2 // perpendicular projected distance + || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end + || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream); + stream.point(x2, y2); + resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream); + } + } + } + return function (stream) { + var lambda00, x00, y00, a00, b00, c00, // first point + lambda0, x0, y0, a0, b0, c0; // previous point + + var resampleStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function () { + stream.polygonStart(); + resampleStream.lineStart = ringStart; + }, + polygonEnd: function () { + stream.polygonEnd(); + resampleStream.lineStart = lineStart; + } + }; + + function point(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + } + + function lineStart() { + x0 = NaN; + resampleStream.point = linePoint; + stream.lineStart(); + } + + function linePoint(lambda, phi) { + var c = cartesian([lambda, phi]), p = project(lambda, phi); + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); + stream.point(x0, y0); + } + + function lineEnd() { + resampleStream.point = point; + stream.lineEnd(); + } + + function ringStart() { + lineStart(); + resampleStream.point = ringPoint; + resampleStream.lineEnd = ringEnd; + } + + function ringPoint(lambda, phi) { + linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; + resampleStream.point = linePoint; + } + + function ringEnd() { + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream); + resampleStream.lineEnd = lineEnd; + lineEnd(); + } + + return resampleStream; + }; + } + + var transformRadians = transformer({ + point: function (x, y) { + this.stream.point(x * radians, y * radians); + } + }); + + function transformRotate(rotate) { + return transformer({ + point: function (x, y) { + var r = rotate(x, y); + return this.stream.point(r[0], r[1]); + } + }); + } + + function scaleTranslate(k, dx, dy, sx, sy) { + function transform(x, y) { + x *= sx; + y *= sy; + return [dx + k * x, dy - k * y]; + } + transform.invert = function (x, y) { + return [(x - dx) / k * sx, (dy - y) / k * sy]; + }; + return transform; + } + + function scaleTranslateRotate(k, dx, dy, sx, sy, alpha) { + var cosAlpha = cos$1(alpha), + sinAlpha = sin$1(alpha), + a = cosAlpha * k, + b = sinAlpha * k, + ai = cosAlpha / k, + bi = sinAlpha / k, + ci = (sinAlpha * dy - cosAlpha * dx) / k, + fi = (sinAlpha * dx + cosAlpha * dy) / k; + function transform(x, y) { + x *= sx; + y *= sy; + return [a * x - b * y + dx, dy - b * x - a * y]; + } + transform.invert = function (x, y) { + return [sx * (ai * x - bi * y + ci), sy * (fi - bi * x - ai * y)]; + }; + return transform; + } + + function projection(project) { + return projectionMutator(function () { + return project; + })(); + } + + function projectionMutator(projectAt) { + var project, + k = 150, // scale + x = 480, y = 250, // translate + lambda = 0, phi = 0, // center + deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, // pre-rotate + alpha = 0, // post-rotate angle + sx = 1, // reflectX + sy = 1, // reflectX + theta = null, preclip = clipAntimeridian, // pre-clip angle + x0 = null, y0, x1, y1, postclip = identity$4, // post-clip extent + delta2 = 0.5, // precision + projectResample, + projectTransform, + projectRotateTransform, + cache, + cacheStream; + + function projection(point) { + return projectRotateTransform(point[0] * radians, point[1] * radians); + } + + function invert(point) { + point = projectRotateTransform.invert(point[0], point[1]); + return point && [point[0] * degrees$1, point[1] * degrees$1]; + } + + projection.stream = function (stream) { + return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream))))); + }; + + projection.preclip = function (_) { + return arguments.length ? (preclip = _, theta = undefined, reset()) : preclip; + }; + + projection.postclip = function (_) { + return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip; + }; + + projection.clipAngle = function (_) { + return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1; + }; + + projection.clipExtent = function (_) { + return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; + + projection.scale = function (_) { + return arguments.length ? (k = +_, recenter()) : k; + }; + + projection.translate = function (_) { + return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y]; + }; + + projection.center = function (_) { + return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1]; + }; + + projection.rotate = function (_) { + return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees$1, deltaPhi * degrees$1, deltaGamma * degrees$1]; + }; + + projection.angle = function (_) { + return arguments.length ? (alpha = _ % 360 * radians, recenter()) : alpha * degrees$1; + }; + + projection.reflectX = function (_) { + return arguments.length ? (sx = _ ? -1 : 1, recenter()) : sx < 0; + }; + + projection.reflectY = function (_) { + return arguments.length ? (sy = _ ? -1 : 1, recenter()) : sy < 0; + }; + + projection.precision = function (_) { + return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2); + }; + + projection.fitExtent = function (extent, object) { + return fitExtent(projection, extent, object); + }; + + projection.fitSize = function (size, object) { + return fitSize(projection, size, object); + }; + + projection.fitWidth = function (width, object) { + return fitWidth(projection, width, object); + }; + + projection.fitHeight = function (height, object) { + return fitHeight(projection, height, object); + }; + + function recenter() { + var center = scaleTranslateRotate(k, 0, 0, sx, sy, alpha).apply(null, project(lambda, phi)), + transform = (alpha ? scaleTranslateRotate : scaleTranslate)(k, x - center[0], y - center[1], sx, sy, alpha); + rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma); + projectTransform = compose(project, transform); + projectRotateTransform = compose(rotate, projectTransform); + projectResample = resample(projectTransform, delta2); + return reset(); + } + + function reset() { + cache = cacheStream = null; + return projection; + } + + return function () { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return recenter(); + }; + } + + function conicProjection(projectAt) { + var phi0 = 0, + phi1 = pi$3 / 3, + m = projectionMutator(projectAt), + p = m(phi0, phi1); + + p.parallels = function (_) { + return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1]; + }; + + return p; + } + + function cylindricalEqualAreaRaw(phi0) { + var cosPhi0 = cos$1(phi0); + + function forward(lambda, phi) { + return [lambda * cosPhi0, sin$1(phi) / cosPhi0]; + } + + forward.invert = function (x, y) { + return [x / cosPhi0, asin(y * cosPhi0)]; + }; + + return forward; + } + + function conicEqualAreaRaw(y0, y1) { + var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2; + + // Are the parallels symmetrical around the Equator? + if (abs(n) < epsilon$2) + return cylindricalEqualAreaRaw(y0); + + var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n; + + function project(x, y) { + var r = sqrt(c - 2 * n * sin$1(y)) / n; + return [r * sin$1(x *= n), r0 - r * cos$1(x)]; + } + + project.invert = function (x, y) { + var r0y = r0 - y, + l = atan2(x, abs(r0y)) * sign(r0y); + if (r0y * n < 0) + l -= pi$3 * sign(x) * sign(r0y); + return [l / n, asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))]; + }; + + return project; + } + + function conicEqualArea() { + return conicProjection(conicEqualAreaRaw) + .scale(155.424) + .center([0, 33.6442]); + } + + function albers() { + return conicEqualArea() + .parallels([29.5, 45.5]) + .scale(1070) + .translate([480, 250]) + .rotate([96, 0]) + .center([-0.6, 38.7]); + } + +// The projections must have mutually exclusive clip regions on the sphere, +// as this will avoid emitting interleaving lines and polygons. + function multiplex(streams) { + var n = streams.length; + return { + point: function (x, y) { + var i = -1; + while (++i < n) + streams[i].point(x, y); + }, + sphere: function () { + var i = -1; + while (++i < n) + streams[i].sphere(); + }, + lineStart: function () { + var i = -1; + while (++i < n) + streams[i].lineStart(); + }, + lineEnd: function () { + var i = -1; + while (++i < n) + streams[i].lineEnd(); + }, + polygonStart: function () { + var i = -1; + while (++i < n) + streams[i].polygonStart(); + }, + polygonEnd: function () { + var i = -1; + while (++i < n) + streams[i].polygonEnd(); + } + }; + } + +// A composite projection for the United States, configured by default for +// 960×500. The projection also works quite well at 960×600 if you change the +// scale to 1285 and adjust the translate accordingly. The set of standard +// parallels for each region comes from USGS, which is published here: +// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers + function albersUsa() { + var cache, + cacheStream, + lower48 = albers(), lower48Point, + alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338 + hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007 + point, pointStream = {point: function (x, y) { + point = [x, y]; + }}; + + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + return point = null, + (lower48Point.point(x, y), point) + || (alaskaPoint.point(x, y), point) + || (hawaiiPoint.point(x, y), point); + } + + albersUsa.invert = function (coordinates) { + var k = lower48.scale(), + t = lower48.translate(), + x = (coordinates[0] - t[0]) / k, + y = (coordinates[1] - t[1]) / k; + return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska + : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii + : lower48).invert(coordinates); + }; + + albersUsa.stream = function (stream) { + return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]); + }; + + albersUsa.precision = function (_) { + if (!arguments.length) + return lower48.precision(); + lower48.precision(_), alaska.precision(_), hawaii.precision(_); + return reset(); + }; + + albersUsa.scale = function (_) { + if (!arguments.length) + return lower48.scale(); + lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_); + return albersUsa.translate(lower48.translate()); + }; + + albersUsa.translate = function (_) { + if (!arguments.length) + return lower48.translate(); + var k = lower48.scale(), x = +_[0], y = +_[1]; + + lower48Point = lower48 + .translate(_) + .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]]) + .stream(pointStream); + + alaskaPoint = alaska + .translate([x - 0.307 * k, y + 0.201 * k]) + .clipExtent([[x - 0.425 * k + epsilon$2, y + 0.120 * k + epsilon$2], [x - 0.214 * k - epsilon$2, y + 0.234 * k - epsilon$2]]) + .stream(pointStream); + + hawaiiPoint = hawaii + .translate([x - 0.205 * k, y + 0.212 * k]) + .clipExtent([[x - 0.214 * k + epsilon$2, y + 0.166 * k + epsilon$2], [x - 0.115 * k - epsilon$2, y + 0.234 * k - epsilon$2]]) + .stream(pointStream); + + return reset(); + }; + + albersUsa.fitExtent = function (extent, object) { + return fitExtent(albersUsa, extent, object); + }; + + albersUsa.fitSize = function (size, object) { + return fitSize(albersUsa, size, object); + }; + + albersUsa.fitWidth = function (width, object) { + return fitWidth(albersUsa, width, object); + }; + + albersUsa.fitHeight = function (height, object) { + return fitHeight(albersUsa, height, object); + }; + + function reset() { + cache = cacheStream = null; + return albersUsa; + } + + return albersUsa.scale(1070); + } + + function azimuthalRaw(scale) { + return function (x, y) { + var cx = cos$1(x), + cy = cos$1(y), + k = scale(cx * cy); + return [ + k * cy * sin$1(x), + k * sin$1(y) + ]; + } + } + + function azimuthalInvert(angle) { + return function (x, y) { + var z = sqrt(x * x + y * y), + c = angle(z), + sc = sin$1(c), + cc = cos$1(c); + return [ + atan2(x * sc, z * cc), + asin(z && y * sc / z) + ]; + } + } + + var azimuthalEqualAreaRaw = azimuthalRaw(function (cxcy) { + return sqrt(2 / (1 + cxcy)); + }); + + azimuthalEqualAreaRaw.invert = azimuthalInvert(function (z) { + return 2 * asin(z / 2); + }); + + function azimuthalEqualArea() { + return projection(azimuthalEqualAreaRaw) + .scale(124.75) + .clipAngle(180 - 1e-3); + } + + var azimuthalEquidistantRaw = azimuthalRaw(function (c) { + return (c = acos(c)) && c / sin$1(c); + }); + + azimuthalEquidistantRaw.invert = azimuthalInvert(function (z) { + return z; + }); + + function azimuthalEquidistant() { + return projection(azimuthalEquidistantRaw) + .scale(79.4188) + .clipAngle(180 - 1e-3); + } + + function mercatorRaw(lambda, phi) { + return [lambda, log(tan((halfPi$2 + phi) / 2))]; + } + + mercatorRaw.invert = function (x, y) { + return [x, 2 * atan(exp(y)) - halfPi$2]; + }; + + function mercator() { + return mercatorProjection(mercatorRaw) + .scale(961 / tau$3); + } + + function mercatorProjection(project) { + var m = projection(project), + center = m.center, + scale = m.scale, + translate = m.translate, + clipExtent = m.clipExtent, + x0 = null, y0, x1, y1; // clip extent + + m.scale = function (_) { + return arguments.length ? (scale(_), reclip()) : scale(); + }; + + m.translate = function (_) { + return arguments.length ? (translate(_), reclip()) : translate(); + }; + + m.center = function (_) { + return arguments.length ? (center(_), reclip()) : center(); + }; + + m.clipExtent = function (_) { + return arguments.length ? ((_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1])), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; + + function reclip() { + var k = pi$3 * scale(), + t = m(rotation(m.rotate()).invert([0, 0])); + return clipExtent(x0 == null + ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw + ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]] + : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]); + } + + return reclip(); + } + + function tany(y) { + return tan((halfPi$2 + y) / 2); + } + + function conicConformalRaw(y0, y1) { + var cy0 = cos$1(y0), + n = y0 === y1 ? sin$1(y0) : log(cy0 / cos$1(y1)) / log(tany(y1) / tany(y0)), + f = cy0 * pow(tany(y0), n) / n; + + if (!n) + return mercatorRaw; + + function project(x, y) { + if (f > 0) { + if (y < -halfPi$2 + epsilon$2) + y = -halfPi$2 + epsilon$2; + } else { + if (y > halfPi$2 - epsilon$2) + y = halfPi$2 - epsilon$2; + } + var r = f / pow(tany(y), n); + return [r * sin$1(n * x), f - r * cos$1(n * x)]; + } + + project.invert = function (x, y) { + var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy), + l = atan2(x, abs(fy)) * sign(fy); + if (fy * n < 0) + l -= pi$3 * sign(x) * sign(fy); + return [l / n, 2 * atan(pow(f / r, 1 / n)) - halfPi$2]; + }; + + return project; + } + + function conicConformal() { + return conicProjection(conicConformalRaw) + .scale(109.5) + .parallels([30, 30]); + } + + function equirectangularRaw(lambda, phi) { + return [lambda, phi]; + } + + equirectangularRaw.invert = equirectangularRaw; + + function equirectangular() { + return projection(equirectangularRaw) + .scale(152.63); + } + + function conicEquidistantRaw(y0, y1) { + var cy0 = cos$1(y0), + n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0), + g = cy0 / n + y0; + + if (abs(n) < epsilon$2) + return equirectangularRaw; + + function project(x, y) { + var gy = g - y, nx = n * x; + return [gy * sin$1(nx), g - gy * cos$1(nx)]; + } + + project.invert = function (x, y) { + var gy = g - y, + l = atan2(x, abs(gy)) * sign(gy); + if (gy * n < 0) + l -= pi$3 * sign(x) * sign(gy); + return [l / n, g - sign(n) * sqrt(x * x + gy * gy)]; + }; + + return project; + } + + function conicEquidistant() { + return conicProjection(conicEquidistantRaw) + .scale(131.154) + .center([0, 13.9389]); + } + + var A1 = 1.340264, + A2 = -0.081106, + A3 = 0.000893, + A4 = 0.003796, + M = sqrt(3) / 2, + iterations = 12; + + function equalEarthRaw(lambda, phi) { + var l = asin(M * sin$1(phi)), l2 = l * l, l6 = l2 * l2 * l2; + return [ + lambda * cos$1(l) / (M * (A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2))), + l * (A1 + A2 * l2 + l6 * (A3 + A4 * l2)) + ]; + } + + equalEarthRaw.invert = function (x, y) { + var l = y, l2 = l * l, l6 = l2 * l2 * l2; + for (var i = 0, delta, fy, fpy; i < iterations; ++i) { + fy = l * (A1 + A2 * l2 + l6 * (A3 + A4 * l2)) - y; + fpy = A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2); + l -= delta = fy / fpy, l2 = l * l, l6 = l2 * l2 * l2; + if (abs(delta) < epsilon2$1) + break; + } + return [ + M * x * (A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2)) / cos$1(l), + asin(sin$1(l) / M) + ]; + }; + + function equalEarth() { + return projection(equalEarthRaw) + .scale(177.158); + } + + function gnomonicRaw(x, y) { + var cy = cos$1(y), k = cos$1(x) * cy; + return [cy * sin$1(x) / k, sin$1(y) / k]; + } + + gnomonicRaw.invert = azimuthalInvert(atan); + + function gnomonic() { + return projection(gnomonicRaw) + .scale(144.049) + .clipAngle(60); + } + + function identity$5() { + var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, // scale, translate and reflect + alpha = 0, ca, sa, // angle + x0 = null, y0, x1, y1, // clip extent + kx = 1, ky = 1, + transform = transformer({ + point: function (x, y) { + var p = projection([x, y]); + this.stream.point(p[0], p[1]); + } + }), + postclip = identity$4, + cache, + cacheStream; + + function reset() { + kx = k * sx; + ky = k * sy; + cache = cacheStream = null; + return projection; + } + + function projection(p) { + var x = p[0] * kx, y = p[1] * ky; + if (alpha) { + var t = y * ca - x * sa; + x = x * ca + y * sa; + y = t; + } + return [x + tx, y + ty]; + } + projection.invert = function (p) { + var x = p[0] - tx, y = p[1] - ty; + if (alpha) { + var t = y * ca + x * sa; + x = x * ca - y * sa; + y = t; + } + return [x / kx, y / ky]; + }; + projection.stream = function (stream) { + return cache && cacheStream === stream ? cache : cache = transform(postclip(cacheStream = stream)); + }; + projection.postclip = function (_) { + return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip; + }; + projection.clipExtent = function (_) { + return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; + projection.scale = function (_) { + return arguments.length ? (k = +_, reset()) : k; + }; + projection.translate = function (_) { + return arguments.length ? (tx = +_[0], ty = +_[1], reset()) : [tx, ty]; + }; + projection.angle = function (_) { + return arguments.length ? (alpha = _ % 360 * radians, sa = sin$1(alpha), ca = cos$1(alpha), reset()) : alpha * degrees$1; + }; + projection.reflectX = function (_) { + return arguments.length ? (sx = _ ? -1 : 1, reset()) : sx < 0; + }; + projection.reflectY = function (_) { + return arguments.length ? (sy = _ ? -1 : 1, reset()) : sy < 0; + }; + projection.fitExtent = function (extent, object) { + return fitExtent(projection, extent, object); + }; + projection.fitSize = function (size, object) { + return fitSize(projection, size, object); + }; + projection.fitWidth = function (width, object) { + return fitWidth(projection, width, object); + }; + projection.fitHeight = function (height, object) { + return fitHeight(projection, height, object); + }; + + return projection; + } + + function naturalEarth1Raw(lambda, phi) { + var phi2 = phi * phi, phi4 = phi2 * phi2; + return [ + lambda * (0.8707 - 0.131979 * phi2 + phi4 * (-0.013791 + phi4 * (0.003971 * phi2 - 0.001529 * phi4))), + phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4))) + ]; + } + + naturalEarth1Raw.invert = function (x, y) { + var phi = y, i = 25, delta; + do { + var phi2 = phi * phi, phi4 = phi2 * phi2; + phi -= delta = (phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4))) - y) / + (1.007226 + phi2 * (0.015085 * 3 + phi4 * (-0.044475 * 7 + 0.028874 * 9 * phi2 - 0.005916 * 11 * phi4))); + } while (abs(delta) > epsilon$2 && --i > 0); + return [ + x / (0.8707 + (phi2 = phi * phi) * (-0.131979 + phi2 * (-0.013791 + phi2 * phi2 * phi2 * (0.003971 - 0.001529 * phi2)))), + phi + ]; + }; + + function naturalEarth1() { + return projection(naturalEarth1Raw) + .scale(175.295); + } + + function orthographicRaw(x, y) { + return [cos$1(y) * sin$1(x), sin$1(y)]; + } + + orthographicRaw.invert = azimuthalInvert(asin); + + function orthographic() { + return projection(orthographicRaw) + .scale(249.5) + .clipAngle(90 + epsilon$2); + } + + function stereographicRaw(x, y) { + var cy = cos$1(y), k = 1 + cos$1(x) * cy; + return [cy * sin$1(x) / k, sin$1(y) / k]; + } + + stereographicRaw.invert = azimuthalInvert(function (z) { + return 2 * atan(z); + }); + + function stereographic() { + return projection(stereographicRaw) + .scale(250) + .clipAngle(142); + } + + function transverseMercatorRaw(lambda, phi) { + return [log(tan((halfPi$2 + phi) / 2)), -lambda]; + } + + transverseMercatorRaw.invert = function (x, y) { + return [-y, 2 * atan(exp(x)) - halfPi$2]; + }; + + function transverseMercator() { + var m = mercatorProjection(transverseMercatorRaw), + center = m.center, + rotate = m.rotate; + + m.center = function (_) { + return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]); + }; + + m.rotate = function (_) { + return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]); + }; + + return rotate([0, 0, 90]) + .scale(159.155); + } + + function defaultSeparation(a, b) { + return a.parent === b.parent ? 1 : 2; + } + + function meanX(children) { + return children.reduce(meanXReduce, 0) / children.length; + } + + function meanXReduce(x, c) { + return x + c.x; + } + + function maxY(children) { + return 1 + children.reduce(maxYReduce, 0); + } + + function maxYReduce(y, c) { + return Math.max(y, c.y); + } + + function leafLeft(node) { + var children; + while (children = node.children) + node = children[0]; + return node; + } + + function leafRight(node) { + var children; + while (children = node.children) + node = children[children.length - 1]; + return node; + } + + function cluster() { + var separation = defaultSeparation, + dx = 1, + dy = 1, + nodeSize = false; + + function cluster(root) { + var previousNode, + x = 0; + + // First walk, computing the initial x & y values. + root.eachAfter(function (node) { + var children = node.children; + if (children) { + node.x = meanX(children); + node.y = maxY(children); + } else { + node.x = previousNode ? x += separation(node, previousNode) : 0; + node.y = 0; + previousNode = node; + } + }); + + var left = leafLeft(root), + right = leafRight(root), + x0 = left.x - separation(left, right) / 2, + x1 = right.x + separation(right, left) / 2; + + // Second walk, normalizing x & y to the desired size. + return root.eachAfter(nodeSize ? function (node) { + node.x = (node.x - root.x) * dx; + node.y = (root.y - node.y) * dy; + } : function (node) { + node.x = (node.x - x0) / (x1 - x0) * dx; + node.y = (1 - (root.y ? node.y / root.y : 1)) * dy; + }); + } + + cluster.separation = function (x) { + return arguments.length ? (separation = x, cluster) : separation; + }; + + cluster.size = function (x) { + return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]); + }; + + cluster.nodeSize = function (x) { + return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null); + }; + + return cluster; + } + + function count(node) { + var sum = 0, + children = node.children, + i = children && children.length; + if (!i) + sum = 1; + else + while (--i >= 0) + sum += children[i].value; + node.value = sum; + } + + function node_count() { + return this.eachAfter(count); + } + + function node_each(callback) { + var node = this, current, next = [node], children, i, n; + do { + current = next.reverse(), next = []; + while (node = current.pop()) { + callback(node), children = node.children; + if (children) + for (i = 0, n = children.length; i < n; ++i) { + next.push(children[i]); + } + } + } while (next.length); + return this; + } + + function node_eachBefore(callback) { + var node = this, nodes = [node], children, i; + while (node = nodes.pop()) { + callback(node), children = node.children; + if (children) + for (i = children.length - 1; i >= 0; --i) { + nodes.push(children[i]); + } + } + return this; + } + + function node_eachAfter(callback) { + var node = this, nodes = [node], next = [], children, i, n; + while (node = nodes.pop()) { + next.push(node), children = node.children; + if (children) + for (i = 0, n = children.length; i < n; ++i) { + nodes.push(children[i]); + } + } + while (node = next.pop()) { + callback(node); + } + return this; + } + + function node_sum(value) { + return this.eachAfter(function (node) { + var sum = +value(node.data) || 0, + children = node.children, + i = children && children.length; + while (--i >= 0) + sum += children[i].value; + node.value = sum; + }); + } + + function node_sort(compare) { + return this.eachBefore(function (node) { + if (node.children) { + node.children.sort(compare); + } + }); + } + + function node_path(end) { + var start = this, + ancestor = leastCommonAncestor(start, end), + nodes = [start]; + while (start !== ancestor) { + start = start.parent; + nodes.push(start); + } + var k = nodes.length; + while (end !== ancestor) { + nodes.splice(k, 0, end); + end = end.parent; + } + return nodes; + } + + function leastCommonAncestor(a, b) { + if (a === b) + return a; + var aNodes = a.ancestors(), + bNodes = b.ancestors(), + c = null; + a = aNodes.pop(); + b = bNodes.pop(); + while (a === b) { + c = a; + a = aNodes.pop(); + b = bNodes.pop(); + } + return c; + } + + function node_ancestors() { + var node = this, nodes = [node]; + while (node = node.parent) { + nodes.push(node); + } + return nodes; + } + + function node_descendants() { + var nodes = []; + this.each(function (node) { + nodes.push(node); + }); + return nodes; + } + + function node_leaves() { + var leaves = []; + this.eachBefore(function (node) { + if (!node.children) { + leaves.push(node); + } + }); + return leaves; + } + + function node_links() { + var root = this, links = []; + root.each(function (node) { + if (node !== root) { // Don’t include the root’s parent, if any. + links.push({source: node.parent, target: node}); + } + }); + return links; + } + + function hierarchy(data, children) { + var root = new Node(data), + valued = +data.value && (root.value = data.value), + node, + nodes = [root], + child, + childs, + i, + n; + + if (children == null) + children = defaultChildren; + + while (node = nodes.pop()) { + if (valued) + node.value = +node.data.value; + if ((childs = children(node.data)) && (n = childs.length)) { + node.children = new Array(n); + for (i = n - 1; i >= 0; --i) { + nodes.push(child = node.children[i] = new Node(childs[i])); + child.parent = node; + child.depth = node.depth + 1; + } + } + } + + return root.eachBefore(computeHeight); + } + + function node_copy() { + return hierarchy(this).eachBefore(copyData); + } + + function defaultChildren(d) { + return d.children; + } + + function copyData(node) { + node.data = node.data.data; + } + + function computeHeight(node) { + var height = 0; + do + node.height = height; + while ((node = node.parent) && (node.height < ++height)); + } + + function Node(data) { + this.data = data; + this.depth = + this.height = 0; + this.parent = null; + } + + Node.prototype = hierarchy.prototype = { + constructor: Node, + count: node_count, + each: node_each, + eachAfter: node_eachAfter, + eachBefore: node_eachBefore, + sum: node_sum, + sort: node_sort, + path: node_path, + ancestors: node_ancestors, + descendants: node_descendants, + leaves: node_leaves, + links: node_links, + copy: node_copy + }; + + var slice$4 = Array.prototype.slice; + + function shuffle$1(array) { + var m = array.length, + t, + i; + + while (m) { + i = Math.random() * m-- | 0; + t = array[m]; + array[m] = array[i]; + array[i] = t; + } + + return array; + } + + function enclose(circles) { + var i = 0, n = (circles = shuffle$1(slice$4.call(circles))).length, B = [], p, e; + + while (i < n) { + p = circles[i]; + if (e && enclosesWeak(e, p)) + ++i; + else + e = encloseBasis(B = extendBasis(B, p)), i = 0; + } + + return e; + } + + function extendBasis(B, p) { + var i, j; + + if (enclosesWeakAll(p, B)) + return [p]; + + // If we get here then B must have at least one element. + for (i = 0; i < B.length; ++i) { + if (enclosesNot(p, B[i]) + && enclosesWeakAll(encloseBasis2(B[i], p), B)) { + return [B[i], p]; + } + } + + // If we get here then B must have at least two elements. + for (i = 0; i < B.length - 1; ++i) { + for (j = i + 1; j < B.length; ++j) { + if (enclosesNot(encloseBasis2(B[i], B[j]), p) + && enclosesNot(encloseBasis2(B[i], p), B[j]) + && enclosesNot(encloseBasis2(B[j], p), B[i]) + && enclosesWeakAll(encloseBasis3(B[i], B[j], p), B)) { + return [B[i], B[j], p]; + } + } + } + + // If we get here then something is very wrong. + throw new Error; + } + + function enclosesNot(a, b) { + var dr = a.r - b.r, dx = b.x - a.x, dy = b.y - a.y; + return dr < 0 || dr * dr < dx * dx + dy * dy; + } + + function enclosesWeak(a, b) { + var dr = a.r - b.r + 1e-6, dx = b.x - a.x, dy = b.y - a.y; + return dr > 0 && dr * dr > dx * dx + dy * dy; + } + + function enclosesWeakAll(a, B) { + for (var i = 0; i < B.length; ++i) { + if (!enclosesWeak(a, B[i])) { + return false; + } + } + return true; + } + + function encloseBasis(B) { + switch (B.length) { + case 1: + return encloseBasis1(B[0]); + case 2: + return encloseBasis2(B[0], B[1]); + case 3: + return encloseBasis3(B[0], B[1], B[2]); + } + } + + function encloseBasis1(a) { + return { + x: a.x, + y: a.y, + r: a.r + }; + } + + function encloseBasis2(a, b) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1, + l = Math.sqrt(x21 * x21 + y21 * y21); + return { + x: (x1 + x2 + x21 / l * r21) / 2, + y: (y1 + y2 + y21 / l * r21) / 2, + r: (l + r1 + r2) / 2 + }; + } + + function encloseBasis3(a, b, c) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x3 = c.x, y3 = c.y, r3 = c.r, + a2 = x1 - x2, + a3 = x1 - x3, + b2 = y1 - y2, + b3 = y1 - y3, + c2 = r2 - r1, + c3 = r3 - r1, + d1 = x1 * x1 + y1 * y1 - r1 * r1, + d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2, + d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3, + ab = a3 * b2 - a2 * b3, + xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1, + xb = (b3 * c2 - b2 * c3) / ab, + ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1, + yb = (a2 * c3 - a3 * c2) / ab, + A = xb * xb + yb * yb - 1, + B = 2 * (r1 + xa * xb + ya * yb), + C = xa * xa + ya * ya - r1 * r1, + r = -(A ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B); + return { + x: x1 + xa + xb * r, + y: y1 + ya + yb * r, + r: r + }; + } + + function place(b, a, c) { + var dx = b.x - a.x, x, a2, + dy = b.y - a.y, y, b2, + d2 = dx * dx + dy * dy; + if (d2) { + a2 = a.r + c.r, a2 *= a2; + b2 = b.r + c.r, b2 *= b2; + if (a2 > b2) { + x = (d2 + b2 - a2) / (2 * d2); + y = Math.sqrt(Math.max(0, b2 / d2 - x * x)); + c.x = b.x - x * dx - y * dy; + c.y = b.y - x * dy + y * dx; + } else { + x = (d2 + a2 - b2) / (2 * d2); + y = Math.sqrt(Math.max(0, a2 / d2 - x * x)); + c.x = a.x + x * dx - y * dy; + c.y = a.y + x * dy + y * dx; + } + } else { + c.x = a.x + c.r; + c.y = a.y; + } + } + + function intersects(a, b) { + var dr = a.r + b.r - 1e-6, dx = b.x - a.x, dy = b.y - a.y; + return dr > 0 && dr * dr > dx * dx + dy * dy; + } + + function score(node) { + var a = node._, + b = node.next._, + ab = a.r + b.r, + dx = (a.x * b.r + b.x * a.r) / ab, + dy = (a.y * b.r + b.y * a.r) / ab; + return dx * dx + dy * dy; + } + + function Node$1(circle) { + this._ = circle; + this.next = null; + this.previous = null; + } + + function packEnclose(circles) { + if (!(n = circles.length)) + return 0; + + var a, b, c, n, aa, ca, i, j, k, sj, sk; + + // Place the first circle. + a = circles[0], a.x = 0, a.y = 0; + if (!(n > 1)) + return a.r; + + // Place the second circle. + b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0; + if (!(n > 2)) + return a.r + b.r; + + // Place the third circle. + place(b, a, c = circles[2]); + + // Initialize the front-chain using the first three circles a, b and c. + a = new Node$1(a), b = new Node$1(b), c = new Node$1(c); + a.next = c.previous = b; + b.next = a.previous = c; + c.next = b.previous = a; + + // Attempt to place each remaining circle… + pack: for (i = 3; i < n; ++i) { + place(a._, b._, c = circles[i]), c = new Node$1(c); + + // Find the closest intersecting circle on the front-chain, if any. + // “Closeness” is determined by linear distance along the front-chain. + // “Ahead” or “behind” is likewise determined by linear distance. + j = b.next, k = a.previous, sj = b._.r, sk = a._.r; + do { + if (sj <= sk) { + if (intersects(j._, c._)) { + b = j, a.next = b, b.previous = a, --i; + continue pack; + } + sj += j._.r, j = j.next; + } else { + if (intersects(k._, c._)) { + a = k, a.next = b, b.previous = a, --i; + continue pack; + } + sk += k._.r, k = k.previous; + } + } while (j !== k.next); + + // Success! Insert the new circle c between a and b. + c.previous = a, c.next = b, a.next = b.previous = b = c; + + // Compute the new closest circle pair to the centroid. + aa = score(a); + while ((c = c.next) !== b) { + if ((ca = score(c)) < aa) { + a = c, aa = ca; + } + } + b = a.next; + } + + // Compute the enclosing circle of the front chain. + a = [b._], c = b; + while ((c = c.next) !== b) + a.push(c._); + c = enclose(a); + + // Translate the circles to put the enclosing circle around the origin. + for (i = 0; i < n; ++i) + a = circles[i], a.x -= c.x, a.y -= c.y; + + return c.r; + } + + function siblings(circles) { + packEnclose(circles); + return circles; + } + + function optional(f) { + return f == null ? null : required(f); + } + + function required(f) { + if (typeof f !== "function") + throw new Error; + return f; + } + + function constantZero() { + return 0; + } + + function constant$9(x) { + return function () { + return x; + }; + } + + function defaultRadius$1(d) { + return Math.sqrt(d.value); + } + + function index$2() { + var radius = null, + dx = 1, + dy = 1, + padding = constantZero; + + function pack(root) { + root.x = dx / 2, root.y = dy / 2; + if (radius) { + root.eachBefore(radiusLeaf(radius)) + .eachAfter(packChildren(padding, 0.5)) + .eachBefore(translateChild(1)); + } else { + root.eachBefore(radiusLeaf(defaultRadius$1)) + .eachAfter(packChildren(constantZero, 1)) + .eachAfter(packChildren(padding, root.r / Math.min(dx, dy))) + .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r))); + } + return root; + } + + pack.radius = function (x) { + return arguments.length ? (radius = optional(x), pack) : radius; + }; + + pack.size = function (x) { + return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy]; + }; + + pack.padding = function (x) { + return arguments.length ? (padding = typeof x === "function" ? x : constant$9(+x), pack) : padding; + }; + + return pack; + } + + function radiusLeaf(radius) { + return function (node) { + if (!node.children) { + node.r = Math.max(0, +radius(node) || 0); + } + }; + } + + function packChildren(padding, k) { + return function (node) { + if (children = node.children) { + var children, + i, + n = children.length, + r = padding(node) * k || 0, + e; + + if (r) + for (i = 0; i < n; ++i) + children[i].r += r; + e = packEnclose(children); + if (r) + for (i = 0; i < n; ++i) + children[i].r -= r; + node.r = e + r; + } + }; + } + + function translateChild(k) { + return function (node) { + var parent = node.parent; + node.r *= k; + if (parent) { + node.x = parent.x + k * node.x; + node.y = parent.y + k * node.y; + } + }; + } + + function roundNode(node) { + node.x0 = Math.round(node.x0); + node.y0 = Math.round(node.y0); + node.x1 = Math.round(node.x1); + node.y1 = Math.round(node.y1); + } + + function treemapDice(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (x1 - x0) / parent.value; + + while (++i < n) { + node = nodes[i], node.y0 = y0, node.y1 = y1; + node.x0 = x0, node.x1 = x0 += node.value * k; + } + } + + function partition() { + var dx = 1, + dy = 1, + padding = 0, + round = false; + + function partition(root) { + var n = root.height + 1; + root.x0 = + root.y0 = padding; + root.x1 = dx; + root.y1 = dy / n; + root.eachBefore(positionNode(dy, n)); + if (round) + root.eachBefore(roundNode); + return root; + } + + function positionNode(dy, n) { + return function (node) { + if (node.children) { + treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n); + } + var x0 = node.x0, + y0 = node.y0, + x1 = node.x1 - padding, + y1 = node.y1 - padding; + if (x1 < x0) + x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) + y0 = y1 = (y0 + y1) / 2; + node.x0 = x0; + node.y0 = y0; + node.x1 = x1; + node.y1 = y1; + }; + } + + partition.round = function (x) { + return arguments.length ? (round = !!x, partition) : round; + }; + + partition.size = function (x) { + return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy]; + }; + + partition.padding = function (x) { + return arguments.length ? (padding = +x, partition) : padding; + }; + + return partition; + } + + var keyPrefix$1 = "$", // Protect against keys like “__proto__”. + preroot = {depth: -1}, + ambiguous = {}; + + function defaultId(d) { + return d.id; + } + + function defaultParentId(d) { + return d.parentId; + } + + function stratify() { + var id = defaultId, + parentId = defaultParentId; + + function stratify(data) { + var d, + i, + n = data.length, + root, + parent, + node, + nodes = new Array(n), + nodeId, + nodeKey, + nodeByKey = {}; + + for (i = 0; i < n; ++i) { + d = data[i], node = nodes[i] = new Node(d); + if ((nodeId = id(d, i, data)) != null && (nodeId += "")) { + nodeKey = keyPrefix$1 + (node.id = nodeId); + nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node; + } + } + + for (i = 0; i < n; ++i) { + node = nodes[i], nodeId = parentId(data[i], i, data); + if (nodeId == null || !(nodeId += "")) { + if (root) + throw new Error("multiple roots"); + root = node; + } else { + parent = nodeByKey[keyPrefix$1 + nodeId]; + if (!parent) + throw new Error("missing: " + nodeId); + if (parent === ambiguous) + throw new Error("ambiguous: " + nodeId); + if (parent.children) + parent.children.push(node); + else + parent.children = [node]; + node.parent = parent; + } + } + + if (!root) + throw new Error("no root"); + root.parent = preroot; + root.eachBefore(function (node) { + node.depth = node.parent.depth + 1; + --n; + }).eachBefore(computeHeight); + root.parent = null; + if (n > 0) + throw new Error("cycle"); + + return root; + } + + stratify.id = function (x) { + return arguments.length ? (id = required(x), stratify) : id; + }; + + stratify.parentId = function (x) { + return arguments.length ? (parentId = required(x), stratify) : parentId; + }; + + return stratify; + } + + function defaultSeparation$1(a, b) { + return a.parent === b.parent ? 1 : 2; + } + +// function radialSeparation(a, b) { +// return (a.parent === b.parent ? 1 : 2) / a.depth; +// } + +// This function is used to traverse the left contour of a subtree (or +// subforest). It returns the successor of v on this contour. This successor is +// either given by the leftmost child of v or by the thread of v. The function +// returns null if and only if v is on the highest level of its subtree. + function nextLeft(v) { + var children = v.children; + return children ? children[0] : v.t; + } + +// This function works analogously to nextLeft. + function nextRight(v) { + var children = v.children; + return children ? children[children.length - 1] : v.t; + } + +// Shifts the current subtree rooted at w+. This is done by increasing +// prelim(w+) and mod(w+) by shift. + function moveSubtree(wm, wp, shift) { + var change = shift / (wp.i - wm.i); + wp.c -= change; + wp.s += shift; + wm.c += change; + wp.z += shift; + wp.m += shift; + } + +// All other shifts, applied to the smaller subtrees between w- and w+, are +// performed by this function. To prepare the shifts, we have to adjust +// change(w+), shift(w+), and change(w-). + function executeShifts(v) { + var shift = 0, + change = 0, + children = v.children, + i = children.length, + w; + while (--i >= 0) { + w = children[i]; + w.z += shift; + w.m += shift; + shift += w.s + (change += w.c); + } + } + +// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise, +// returns the specified (default) ancestor. + function nextAncestor(vim, v, ancestor) { + return vim.a.parent === v.parent ? vim.a : ancestor; + } + + function TreeNode(node, i) { + this._ = node; + this.parent = null; + this.children = null; + this.A = null; // default ancestor + this.a = this; // ancestor + this.z = 0; // prelim + this.m = 0; // mod + this.c = 0; // change + this.s = 0; // shift + this.t = null; // thread + this.i = i; // number + } + + TreeNode.prototype = Object.create(Node.prototype); + + function treeRoot(root) { + var tree = new TreeNode(root, 0), + node, + nodes = [tree], + child, + children, + i, + n; + + while (node = nodes.pop()) { + if (children = node._.children) { + node.children = new Array(n = children.length); + for (i = n - 1; i >= 0; --i) { + nodes.push(child = node.children[i] = new TreeNode(children[i], i)); + child.parent = node; + } + } + } + + (tree.parent = new TreeNode(null, 0)).children = [tree]; + return tree; + } + +// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm + function tree() { + var separation = defaultSeparation$1, + dx = 1, + dy = 1, + nodeSize = null; + + function tree(root) { + var t = treeRoot(root); + + // Compute the layout using Buchheim et al.’s algorithm. + t.eachAfter(firstWalk), t.parent.m = -t.z; + t.eachBefore(secondWalk); + + // If a fixed node size is specified, scale x and y. + if (nodeSize) + root.eachBefore(sizeNode); + + // If a fixed tree size is specified, scale x and y based on the extent. + // Compute the left-most, right-most, and depth-most nodes for extents. + else { + var left = root, + right = root, + bottom = root; + root.eachBefore(function (node) { + if (node.x < left.x) + left = node; + if (node.x > right.x) + right = node; + if (node.depth > bottom.depth) + bottom = node; + }); + var s = left === right ? 1 : separation(left, right) / 2, + tx = s - left.x, + kx = dx / (right.x + s + tx), + ky = dy / (bottom.depth || 1); + root.eachBefore(function (node) { + node.x = (node.x + tx) * kx; + node.y = node.depth * ky; + }); + } + + return root; + } + + // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is + // applied recursively to the children of v, as well as the function + // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the + // node v is placed to the midpoint of its outermost children. + function firstWalk(v) { + var children = v.children, + siblings = v.parent.children, + w = v.i ? siblings[v.i - 1] : null; + if (children) { + executeShifts(v); + var midpoint = (children[0].z + children[children.length - 1].z) / 2; + if (w) { + v.z = w.z + separation(v._, w._); + v.m = v.z - midpoint; + } else { + v.z = midpoint; + } + } else if (w) { + v.z = w.z + separation(v._, w._); + } + v.parent.A = apportion(v, w, v.parent.A || siblings[0]); + } + + // Computes all real x-coordinates by summing up the modifiers recursively. + function secondWalk(v) { + v._.x = v.z + v.parent.m; + v.m += v.parent.m; + } + + // The core of the algorithm. Here, a new subtree is combined with the + // previous subtrees. Threads are used to traverse the inside and outside + // contours of the left and right subtree up to the highest common level. The + // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the + // superscript o means outside and i means inside, the subscript - means left + // subtree and + means right subtree. For summing up the modifiers along the + // contour, we use respective variables si+, si-, so-, and so+. Whenever two + // nodes of the inside contours conflict, we compute the left one of the + // greatest uncommon ancestors using the function ANCESTOR and call MOVE + // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees. + // Finally, we add a new thread (if necessary). + function apportion(v, w, ancestor) { + if (w) { + var vip = v, + vop = v, + vim = w, + vom = vip.parent.children[0], + sip = vip.m, + sop = vop.m, + sim = vim.m, + som = vom.m, + shift; + while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) { + vom = nextLeft(vom); + vop = nextRight(vop); + vop.a = v; + shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); + if (shift > 0) { + moveSubtree(nextAncestor(vim, v, ancestor), v, shift); + sip += shift; + sop += shift; + } + sim += vim.m; + sip += vip.m; + som += vom.m; + sop += vop.m; + } + if (vim && !nextRight(vop)) { + vop.t = vim; + vop.m += sim - sop; + } + if (vip && !nextLeft(vom)) { + vom.t = vip; + vom.m += sip - som; + ancestor = v; + } + } + return ancestor; + } + + function sizeNode(node) { + node.x *= dx; + node.y = node.depth * dy; + } + + tree.separation = function (x) { + return arguments.length ? (separation = x, tree) : separation; + }; + + tree.size = function (x) { + return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]); + }; + + tree.nodeSize = function (x) { + return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null); + }; + + return tree; + } + + function treemapSlice(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (y1 - y0) / parent.value; + + while (++i < n) { + node = nodes[i], node.x0 = x0, node.x1 = x1; + node.y0 = y0, node.y1 = y0 += node.value * k; + } + } + + var phi = (1 + Math.sqrt(5)) / 2; + + function squarifyRatio(ratio, parent, x0, y0, x1, y1) { + var rows = [], + nodes = parent.children, + row, + nodeValue, + i0 = 0, + i1 = 0, + n = nodes.length, + dx, dy, + value = parent.value, + sumValue, + minValue, + maxValue, + newRatio, + minRatio, + alpha, + beta; + + while (i0 < n) { + dx = x1 - x0, dy = y1 - y0; + + // Find the next non-empty node. + do + sumValue = nodes[i1++].value; + while (!sumValue && i1 < n); + minValue = maxValue = sumValue; + alpha = Math.max(dy / dx, dx / dy) / (value * ratio); + beta = sumValue * sumValue * alpha; + minRatio = Math.max(maxValue / beta, beta / minValue); + + // Keep adding nodes while the aspect ratio maintains or improves. + for (; i1 < n; ++i1) { + sumValue += nodeValue = nodes[i1].value; + if (nodeValue < minValue) + minValue = nodeValue; + if (nodeValue > maxValue) + maxValue = nodeValue; + beta = sumValue * sumValue * alpha; + newRatio = Math.max(maxValue / beta, beta / minValue); + if (newRatio > minRatio) { + sumValue -= nodeValue; + break; + } + minRatio = newRatio; + } + + // Position and record the row orientation. + rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)}); + if (row.dice) + treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1); + else + treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1); + value -= sumValue, i0 = i1; + } + + return rows; + } + + var squarify = (function custom(ratio) { + + function squarify(parent, x0, y0, x1, y1) { + squarifyRatio(ratio, parent, x0, y0, x1, y1); + } + + squarify.ratio = function (x) { + return custom((x = +x) > 1 ? x : 1); + }; + + return squarify; + })(phi); + + function index$3() { + var tile = squarify, + round = false, + dx = 1, + dy = 1, + paddingStack = [0], + paddingInner = constantZero, + paddingTop = constantZero, + paddingRight = constantZero, + paddingBottom = constantZero, + paddingLeft = constantZero; + + function treemap(root) { + root.x0 = + root.y0 = 0; + root.x1 = dx; + root.y1 = dy; + root.eachBefore(positionNode); + paddingStack = [0]; + if (round) + root.eachBefore(roundNode); + return root; + } + + function positionNode(node) { + var p = paddingStack[node.depth], + x0 = node.x0 + p, + y0 = node.y0 + p, + x1 = node.x1 - p, + y1 = node.y1 - p; + if (x1 < x0) + x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) + y0 = y1 = (y0 + y1) / 2; + node.x0 = x0; + node.y0 = y0; + node.x1 = x1; + node.y1 = y1; + if (node.children) { + p = paddingStack[node.depth + 1] = paddingInner(node) / 2; + x0 += paddingLeft(node) - p; + y0 += paddingTop(node) - p; + x1 -= paddingRight(node) - p; + y1 -= paddingBottom(node) - p; + if (x1 < x0) + x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) + y0 = y1 = (y0 + y1) / 2; + tile(node, x0, y0, x1, y1); + } + } + + treemap.round = function (x) { + return arguments.length ? (round = !!x, treemap) : round; + }; + + treemap.size = function (x) { + return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy]; + }; + + treemap.tile = function (x) { + return arguments.length ? (tile = required(x), treemap) : tile; + }; + + treemap.padding = function (x) { + return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner(); + }; + + treemap.paddingInner = function (x) { + return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$9(+x), treemap) : paddingInner; + }; + + treemap.paddingOuter = function (x) { + return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop(); + }; + + treemap.paddingTop = function (x) { + return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$9(+x), treemap) : paddingTop; + }; + + treemap.paddingRight = function (x) { + return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$9(+x), treemap) : paddingRight; + }; + + treemap.paddingBottom = function (x) { + return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$9(+x), treemap) : paddingBottom; + }; + + treemap.paddingLeft = function (x) { + return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$9(+x), treemap) : paddingLeft; + }; + + return treemap; + } + + function binary(parent, x0, y0, x1, y1) { + var nodes = parent.children, + i, n = nodes.length, + sum, sums = new Array(n + 1); + + for (sums[0] = sum = i = 0; i < n; ++i) { + sums[i + 1] = sum += nodes[i].value; + } + + partition(0, n, parent.value, x0, y0, x1, y1); + + function partition(i, j, value, x0, y0, x1, y1) { + if (i >= j - 1) { + var node = nodes[i]; + node.x0 = x0, node.y0 = y0; + node.x1 = x1, node.y1 = y1; + return; + } + + var valueOffset = sums[i], + valueTarget = (value / 2) + valueOffset, + k = i + 1, + hi = j - 1; + + while (k < hi) { + var mid = k + hi >>> 1; + if (sums[mid] < valueTarget) + k = mid + 1; + else + hi = mid; + } + + if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) + --k; + + var valueLeft = sums[k] - valueOffset, + valueRight = value - valueLeft; + + if ((x1 - x0) > (y1 - y0)) { + var xk = (x0 * valueRight + x1 * valueLeft) / value; + partition(i, k, valueLeft, x0, y0, xk, y1); + partition(k, j, valueRight, xk, y0, x1, y1); + } else { + var yk = (y0 * valueRight + y1 * valueLeft) / value; + partition(i, k, valueLeft, x0, y0, x1, yk); + partition(k, j, valueRight, x0, yk, x1, y1); + } + } + } + + function sliceDice(parent, x0, y0, x1, y1) { + (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1); + } + + var resquarify = (function custom(ratio) { + + function resquarify(parent, x0, y0, x1, y1) { + if ((rows = parent._squarify) && (rows.ratio === ratio)) { + var rows, + row, + nodes, + i, + j = -1, + n, + m = rows.length, + value = parent.value; + + while (++j < m) { + row = rows[j], nodes = row.children; + for (i = row.value = 0, n = nodes.length; i < n; ++i) + row.value += nodes[i].value; + if (row.dice) + treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value); + else + treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1); + value -= row.value; + } + } else { + parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1); + rows.ratio = ratio; + } + } + + resquarify.ratio = function (x) { + return custom((x = +x) > 1 ? x : 1); + }; + + return resquarify; + })(phi); + + function area$2(polygon) { + var i = -1, + n = polygon.length, + a, + b = polygon[n - 1], + area = 0; + + while (++i < n) { + a = b; + b = polygon[i]; + area += a[1] * b[0] - a[0] * b[1]; + } + + return area / 2; + } + + function centroid$1(polygon) { + var i = -1, + n = polygon.length, + x = 0, + y = 0, + a, + b = polygon[n - 1], + c, + k = 0; + + while (++i < n) { + a = b; + b = polygon[i]; + k += c = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * c; + y += (a[1] + b[1]) * c; + } + + return k *= 3, [x / k, y / k]; + } + +// Returns the 2D cross product of AB and AC vectors, i.e., the z-component of +// the 3D cross product in a quadrant I Cartesian coordinate system (+x is +// right, +y is up). Returns a positive value if ABC is counter-clockwise, +// negative if clockwise, and zero if the points are collinear. + function cross$1(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); + } + + function lexicographicOrder(a, b) { + return a[0] - b[0] || a[1] - b[1]; + } + +// Computes the upper convex hull per the monotone chain algorithm. +// Assumes points.length >= 3, is sorted by x, unique in y. +// Returns an array of indices into points in left-to-right order. + function computeUpperHullIndexes(points) { + var n = points.length, + indexes = [0, 1], + size = 2; + + for (var i = 2; i < n; ++i) { + while (size > 1 && cross$1(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) + --size; + indexes[size++] = i; + } + + return indexes.slice(0, size); // remove popped points + } + + function hull(points) { + if ((n = points.length) < 3) + return null; + + var i, + n, + sortedPoints = new Array(n), + flippedPoints = new Array(n); + + for (i = 0; i < n; ++i) + sortedPoints[i] = [+points[i][0], +points[i][1], i]; + sortedPoints.sort(lexicographicOrder); + for (i = 0; i < n; ++i) + flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]]; + + var upperIndexes = computeUpperHullIndexes(sortedPoints), + lowerIndexes = computeUpperHullIndexes(flippedPoints); + + // Construct the hull polygon, removing possible duplicate endpoints. + var skipLeft = lowerIndexes[0] === upperIndexes[0], + skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1], + hull = []; + + // Add upper hull in right-to-l order. + // Then add lower hull in left-to-right order. + for (i = upperIndexes.length - 1; i >= 0; --i) + hull.push(points[sortedPoints[upperIndexes[i]][2]]); + for (i = + skipLeft; i < lowerIndexes.length - skipRight; ++i) + hull.push(points[sortedPoints[lowerIndexes[i]][2]]); + + return hull; + } + + function contains$2(polygon, point) { + var n = polygon.length, + p = polygon[n - 1], + x = point[0], y = point[1], + x0 = p[0], y0 = p[1], + x1, y1, + inside = false; + + for (var i = 0; i < n; ++i) { + p = polygon[i], x1 = p[0], y1 = p[1]; + if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) + inside = !inside; + x0 = x1, y0 = y1; + } + + return inside; + } + + function length$2(polygon) { + var i = -1, + n = polygon.length, + b = polygon[n - 1], + xa, + ya, + xb = b[0], + yb = b[1], + perimeter = 0; + + while (++i < n) { + xa = xb; + ya = yb; + b = polygon[i]; + xb = b[0]; + yb = b[1]; + xa -= xb; + ya -= yb; + perimeter += Math.sqrt(xa * xa + ya * ya); + } + + return perimeter; + } + + function defaultSource$1() { + return Math.random(); + } + + var uniform = (function sourceRandomUniform(source) { + function randomUniform(min, max) { + min = min == null ? 0 : +min; + max = max == null ? 1 : +max; + if (arguments.length === 1) + max = min, min = 0; + else + max -= min; + return function () { + return source() * max + min; + }; + } + + randomUniform.source = sourceRandomUniform; + + return randomUniform; + })(defaultSource$1); + + var normal = (function sourceRandomNormal(source) { + function randomNormal(mu, sigma) { + var x, r; + mu = mu == null ? 0 : +mu; + sigma = sigma == null ? 1 : +sigma; + return function () { + var y; + + // If available, use the second previously-generated uniform random. + if (x != null) + y = x, x = null; + + // Otherwise, generate a new x and y. + else + do { + x = source() * 2 - 1; + y = source() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); + + return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r); + }; + } + + randomNormal.source = sourceRandomNormal; + + return randomNormal; + })(defaultSource$1); + + var logNormal = (function sourceRandomLogNormal(source) { + function randomLogNormal() { + var randomNormal = normal.source(source).apply(this, arguments); + return function () { + return Math.exp(randomNormal()); + }; + } + + randomLogNormal.source = sourceRandomLogNormal; + + return randomLogNormal; + })(defaultSource$1); + + var irwinHall = (function sourceRandomIrwinHall(source) { + function randomIrwinHall(n) { + return function () { + for (var sum = 0, i = 0; i < n; ++i) + sum += source(); + return sum; + }; + } + + randomIrwinHall.source = sourceRandomIrwinHall; + + return randomIrwinHall; + })(defaultSource$1); + + var bates = (function sourceRandomBates(source) { + function randomBates(n) { + var randomIrwinHall = irwinHall.source(source)(n); + return function () { + return randomIrwinHall() / n; + }; + } + + randomBates.source = sourceRandomBates; + + return randomBates; + })(defaultSource$1); + + var exponential$1 = (function sourceRandomExponential(source) { + function randomExponential(lambda) { + return function () { + return -Math.log(1 - source()) / lambda; + }; + } + + randomExponential.source = sourceRandomExponential; + + return randomExponential; + })(defaultSource$1); + + function initRange(domain, range) { + switch (arguments.length) { + case 0: + break; + case 1: + this.range(domain); + break; + default: + this.range(range).domain(domain); + break; + } + return this; + } + + function initInterpolator(domain, interpolator) { + switch (arguments.length) { + case 0: + break; + case 1: + this.interpolator(domain); + break; + default: + this.interpolator(interpolator).domain(domain); + break; + } + return this; + } + + var array$3 = Array.prototype; + + var map$3 = array$3.map; + var slice$5 = array$3.slice; + + var implicit = {name: "implicit"}; + + function ordinal() { + var index = map$1(), + domain = [], + range = [], + unknown = implicit; + + function scale(d) { + var key = d + "", i = index.get(key); + if (!i) { + if (unknown !== implicit) + return unknown; + index.set(key, i = domain.push(d)); + } + return range[(i - 1) % range.length]; + } + + scale.domain = function (_) { + if (!arguments.length) + return domain.slice(); + domain = [], index = map$1(); + var i = -1, n = _.length, d, key; + while (++i < n) + if (!index.has(key = (d = _[i]) + "")) + index.set(key, domain.push(d)); + return scale; + }; + + scale.range = function (_) { + return arguments.length ? (range = slice$5.call(_), scale) : range.slice(); + }; + + scale.unknown = function (_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + scale.copy = function () { + return ordinal(domain, range).unknown(unknown); + }; + + initRange.apply(scale, arguments); + + return scale; + } + + function band() { + var scale = ordinal().unknown(undefined), + domain = scale.domain, + ordinalRange = scale.range, + range = [0, 1], + step, + bandwidth, + round = false, + paddingInner = 0, + paddingOuter = 0, + align = 0.5; + + delete scale.unknown; + + function rescale() { + var n = domain().length, + reverse = range[1] < range[0], + start = range[reverse - 0], + stop = range[1 - reverse]; + step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2); + if (round) + step = Math.floor(step); + start += (stop - start - step * (n - paddingInner)) * align; + bandwidth = step * (1 - paddingInner); + if (round) + start = Math.round(start), bandwidth = Math.round(bandwidth); + var values = sequence(n).map(function (i) { + return start + step * i; + }); + return ordinalRange(reverse ? values.reverse() : values); + } + + scale.domain = function (_) { + return arguments.length ? (domain(_), rescale()) : domain(); + }; + + scale.range = function (_) { + return arguments.length ? (range = [+_[0], +_[1]], rescale()) : range.slice(); + }; + + scale.rangeRound = function (_) { + return range = [+_[0], +_[1]], round = true, rescale(); + }; + + scale.bandwidth = function () { + return bandwidth; + }; + + scale.step = function () { + return step; + }; + + scale.round = function (_) { + return arguments.length ? (round = !!_, rescale()) : round; + }; + + scale.padding = function (_) { + return arguments.length ? (paddingInner = Math.min(1, paddingOuter = +_), rescale()) : paddingInner; + }; + + scale.paddingInner = function (_) { + return arguments.length ? (paddingInner = Math.min(1, _), rescale()) : paddingInner; + }; + + scale.paddingOuter = function (_) { + return arguments.length ? (paddingOuter = +_, rescale()) : paddingOuter; + }; + + scale.align = function (_) { + return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align; + }; + + scale.copy = function () { + return band(domain(), range) + .round(round) + .paddingInner(paddingInner) + .paddingOuter(paddingOuter) + .align(align); + }; + + return initRange.apply(rescale(), arguments); + } + + function pointish(scale) { + var copy = scale.copy; + + scale.padding = scale.paddingOuter; + delete scale.paddingInner; + delete scale.paddingOuter; + + scale.copy = function () { + return pointish(copy()); + }; + + return scale; + } + + function point$1() { + return pointish(band.apply(null, arguments).paddingInner(1)); + } + + function constant$a(x) { + return function () { + return x; + }; + } + + function number$2(x) { + return +x; + } + + var unit = [0, 1]; + + function identity$6(x) { + return x; + } + + function normalize(a, b) { + return (b -= (a = +a)) + ? function (x) { + return (x - a) / b; + } + : constant$a(isNaN(b) ? NaN : 0.5); + } + + function clamper(domain) { + var a = domain[0], b = domain[domain.length - 1], t; + if (a > b) + t = a, a = b, b = t; + return function (x) { + return Math.max(a, Math.min(b, x)); + }; + } + +// normalize(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. +// interpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding range value x in [a,b]. + function bimap(domain, range, interpolate) { + var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1]; + if (d1 < d0) + d0 = normalize(d1, d0), r0 = interpolate(r1, r0); + else + d0 = normalize(d0, d1), r0 = interpolate(r0, r1); + return function (x) { + return r0(d0(x)); + }; + } + + function polymap(domain, range, interpolate) { + var j = Math.min(domain.length, range.length) - 1, + d = new Array(j), + r = new Array(j), + i = -1; + + // Reverse descending domains. + if (domain[j] < domain[0]) { + domain = domain.slice().reverse(); + range = range.slice().reverse(); + } + + while (++i < j) { + d[i] = normalize(domain[i], domain[i + 1]); + r[i] = interpolate(range[i], range[i + 1]); + } + + return function (x) { + var i = bisectRight(domain, x, 1, j) - 1; + return r[i](d[i](x)); + }; + } + + function copy(source, target) { + return target + .domain(source.domain()) + .range(source.range()) + .interpolate(source.interpolate()) + .clamp(source.clamp()) + .unknown(source.unknown()); + } + + function transformer$1() { + var domain = unit, + range = unit, + interpolate = interpolateValue, + transform, + untransform, + unknown, + clamp = identity$6, + piecewise, + output, + input; + + function rescale() { + piecewise = Math.min(domain.length, range.length) > 2 ? polymap : bimap; + output = input = null; + return scale; + } + + function scale(x) { + return isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate)))(transform(clamp(x))); + } + + scale.invert = function (y) { + return clamp(untransform((input || (input = piecewise(range, domain.map(transform), interpolateNumber)))(y))); + }; + + scale.domain = function (_) { + return arguments.length ? (domain = map$3.call(_, number$2), clamp === identity$6 || (clamp = clamper(domain)), rescale()) : domain.slice(); + }; + + scale.range = function (_) { + return arguments.length ? (range = slice$5.call(_), rescale()) : range.slice(); + }; + + scale.rangeRound = function (_) { + return range = slice$5.call(_), interpolate = interpolateRound, rescale(); + }; + + scale.clamp = function (_) { + return arguments.length ? (clamp = _ ? clamper(domain) : identity$6, scale) : clamp !== identity$6; + }; + + scale.interpolate = function (_) { + return arguments.length ? (interpolate = _, rescale()) : interpolate; + }; + + scale.unknown = function (_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + return function (t, u) { + transform = t, untransform = u; + return rescale(); + }; + } + + function continuous(transform, untransform) { + return transformer$1()(transform, untransform); + } + + function tickFormat(start, stop, count, specifier) { + var step = tickStep(start, stop, count), + precision; + specifier = formatSpecifier(specifier == null ? ",f" : specifier); + switch (specifier.type) { + case "s": + { + var value = Math.max(Math.abs(start), Math.abs(stop)); + if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) + specifier.precision = precision; + return exports.formatPrefix(specifier, value); + } + case "": + case "e": + case "g": + case "p": + case "r": + { + if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) + specifier.precision = precision - (specifier.type === "e"); + break; + } + case "f": + case "%": + { + if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) + specifier.precision = precision - (specifier.type === "%") * 2; + break; + } + } + return exports.format(specifier); + } + + function linearish(scale) { + var domain = scale.domain; + + scale.ticks = function (count) { + var d = domain(); + return ticks(d[0], d[d.length - 1], count == null ? 10 : count); + }; + + scale.tickFormat = function (count, specifier) { + var d = domain(); + return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier); + }; + + scale.nice = function (count) { + if (count == null) + count = 10; + + var d = domain(), + i0 = 0, + i1 = d.length - 1, + start = d[i0], + stop = d[i1], + step; + + if (stop < start) { + step = start, start = stop, stop = step; + step = i0, i0 = i1, i1 = step; + } + + step = tickIncrement(start, stop, count); + + if (step > 0) { + start = Math.floor(start / step) * step; + stop = Math.ceil(stop / step) * step; + step = tickIncrement(start, stop, count); + } else if (step < 0) { + start = Math.ceil(start * step) / step; + stop = Math.floor(stop * step) / step; + step = tickIncrement(start, stop, count); + } + + if (step > 0) { + d[i0] = Math.floor(start / step) * step; + d[i1] = Math.ceil(stop / step) * step; + domain(d); + } else if (step < 0) { + d[i0] = Math.ceil(start * step) / step; + d[i1] = Math.floor(stop * step) / step; + domain(d); + } + + return scale; + }; + + return scale; + } + + function linear$2() { + var scale = continuous(identity$6, identity$6); + + scale.copy = function () { + return copy(scale, linear$2()); + }; + + initRange.apply(scale, arguments); + + return linearish(scale); + } + + function identity$7(domain) { + var unknown; + + function scale(x) { + return isNaN(x = +x) ? unknown : x; + } + + scale.invert = scale; + + scale.domain = scale.range = function (_) { + return arguments.length ? (domain = map$3.call(_, number$2), scale) : domain.slice(); + }; + + scale.unknown = function (_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + scale.copy = function () { + return identity$7(domain).unknown(unknown); + }; + + domain = arguments.length ? map$3.call(domain, number$2) : [0, 1]; + + return linearish(scale); + } + + function nice(domain, interval) { + domain = domain.slice(); + + var i0 = 0, + i1 = domain.length - 1, + x0 = domain[i0], + x1 = domain[i1], + t; + + if (x1 < x0) { + t = i0, i0 = i1, i1 = t; + t = x0, x0 = x1, x1 = t; + } + + domain[i0] = interval.floor(x0); + domain[i1] = interval.ceil(x1); + return domain; + } + + function transformLog(x) { + return Math.log(x); + } + + function transformExp(x) { + return Math.exp(x); + } + + function transformLogn(x) { + return -Math.log(-x); + } + + function transformExpn(x) { + return -Math.exp(-x); + } + + function pow10(x) { + return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x; + } + + function powp(base) { + return base === 10 ? pow10 + : base === Math.E ? Math.exp + : function (x) { + return Math.pow(base, x); + }; + } + + function logp(base) { + return base === Math.E ? Math.log + : base === 10 && Math.log10 + || base === 2 && Math.log2 + || (base = Math.log(base), function (x) { + return Math.log(x) / base; + }); + } + + function reflect(f) { + return function (x) { + return -f(-x); + }; + } + + function loggish(transform) { + var scale = transform(transformLog, transformExp), + domain = scale.domain, + base = 10, + logs, + pows; + + function rescale() { + logs = logp(base), pows = powp(base); + if (domain()[0] < 0) { + logs = reflect(logs), pows = reflect(pows); + transform(transformLogn, transformExpn); + } else { + transform(transformLog, transformExp); + } + return scale; + } + + scale.base = function (_) { + return arguments.length ? (base = +_, rescale()) : base; + }; + + scale.domain = function (_) { + return arguments.length ? (domain(_), rescale()) : domain(); + }; + + scale.ticks = function (count) { + var d = domain(), + u = d[0], + v = d[d.length - 1], + r; + + if (r = v < u) + i = u, u = v, v = i; + + var i = logs(u), + j = logs(v), + p, + k, + t, + n = count == null ? 10 : +count, + z = []; + + if (!(base % 1) && j - i < n) { + i = Math.round(i) - 1, j = Math.round(j) + 1; + if (u > 0) + for (; i < j; ++i) { + for (k = 1, p = pows(i); k < base; ++k) { + t = p * k; + if (t < u) + continue; + if (t > v) + break; + z.push(t); + } + } + else + for (; i < j; ++i) { + for (k = base - 1, p = pows(i); k >= 1; --k) { + t = p * k; + if (t < u) + continue; + if (t > v) + break; + z.push(t); + } + } + } else { + z = ticks(i, j, Math.min(j - i, n)).map(pows); + } + + return r ? z.reverse() : z; + }; + + scale.tickFormat = function (count, specifier) { + if (specifier == null) + specifier = base === 10 ? ".0e" : ","; + if (typeof specifier !== "function") + specifier = exports.format(specifier); + if (count === Infinity) + return specifier; + if (count == null) + count = 10; + var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate? + return function (d) { + var i = d / pows(Math.round(logs(d))); + if (i * base < base - 0.5) + i *= base; + return i <= k ? specifier(d) : ""; + }; + }; + + scale.nice = function () { + return domain(nice(domain(), { + floor: function (x) { + return pows(Math.floor(logs(x))); + }, + ceil: function (x) { + return pows(Math.ceil(logs(x))); + } + })); + }; + + return scale; + } + + function log$1() { + var scale = loggish(transformer$1()).domain([1, 10]); + + scale.copy = function () { + return copy(scale, log$1()).base(scale.base()); + }; + + initRange.apply(scale, arguments); + + return scale; + } + + function transformSymlog(c) { + return function (x) { + return Math.sign(x) * Math.log1p(Math.abs(x / c)); + }; + } + + function transformSymexp(c) { + return function (x) { + return Math.sign(x) * Math.expm1(Math.abs(x)) * c; + }; + } + + function symlogish(transform) { + var c = 1, scale = transform(transformSymlog(c), transformSymexp(c)); + + scale.constant = function (_) { + return arguments.length ? transform(transformSymlog(c = +_), transformSymexp(c)) : c; + }; + + return linearish(scale); + } + + function symlog() { + var scale = symlogish(transformer$1()); + + scale.copy = function () { + return copy(scale, symlog()).constant(scale.constant()); + }; + + return initRange.apply(scale, arguments); + } + + function transformPow(exponent) { + return function (x) { + return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent); + }; + } + + function transformSqrt(x) { + return x < 0 ? -Math.sqrt(-x) : Math.sqrt(x); + } + + function transformSquare(x) { + return x < 0 ? -x * x : x * x; + } + + function powish(transform) { + var scale = transform(identity$6, identity$6), + exponent = 1; + + function rescale() { + return exponent === 1 ? transform(identity$6, identity$6) + : exponent === 0.5 ? transform(transformSqrt, transformSquare) + : transform(transformPow(exponent), transformPow(1 / exponent)); + } + + scale.exponent = function (_) { + return arguments.length ? (exponent = +_, rescale()) : exponent; + }; + + return linearish(scale); + } + + function pow$1() { + var scale = powish(transformer$1()); + + scale.copy = function () { + return copy(scale, pow$1()).exponent(scale.exponent()); + }; + + initRange.apply(scale, arguments); + + return scale; + } + + function sqrt$1() { + return pow$1.apply(null, arguments).exponent(0.5); + } + + function quantile() { + var domain = [], + range = [], + thresholds = [], + unknown; + + function rescale() { + var i = 0, n = Math.max(1, range.length); + thresholds = new Array(n - 1); + while (++i < n) + thresholds[i - 1] = threshold(domain, i / n); + return scale; + } + + function scale(x) { + return isNaN(x = +x) ? unknown : range[bisectRight(thresholds, x)]; + } + + scale.invertExtent = function (y) { + var i = range.indexOf(y); + return i < 0 ? [NaN, NaN] : [ + i > 0 ? thresholds[i - 1] : domain[0], + i < thresholds.length ? thresholds[i] : domain[domain.length - 1] + ]; + }; + + scale.domain = function (_) { + if (!arguments.length) + return domain.slice(); + domain = []; + for (var i = 0, n = _.length, d; i < n; ++i) + if (d = _[i], d != null && !isNaN(d = +d)) + domain.push(d); + domain.sort(ascending); + return rescale(); + }; + + scale.range = function (_) { + return arguments.length ? (range = slice$5.call(_), rescale()) : range.slice(); + }; + + scale.unknown = function (_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + scale.quantiles = function () { + return thresholds.slice(); + }; + + scale.copy = function () { + return quantile() + .domain(domain) + .range(range) + .unknown(unknown); + }; + + return initRange.apply(scale, arguments); + } + + function quantize$1() { + var x0 = 0, + x1 = 1, + n = 1, + domain = [0.5], + range = [0, 1], + unknown; + + function scale(x) { + return x <= x ? range[bisectRight(domain, x, 0, n)] : unknown; + } + + function rescale() { + var i = -1; + domain = new Array(n); + while (++i < n) + domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1); + return scale; + } + + scale.domain = function (_) { + return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1]; + }; + + scale.range = function (_) { + return arguments.length ? (n = (range = slice$5.call(_)).length - 1, rescale()) : range.slice(); + }; + + scale.invertExtent = function (y) { + var i = range.indexOf(y); + return i < 0 ? [NaN, NaN] + : i < 1 ? [x0, domain[0]] + : i >= n ? [domain[n - 1], x1] + : [domain[i - 1], domain[i]]; + }; + + scale.unknown = function (_) { + return arguments.length ? (unknown = _, scale) : scale; + }; + + scale.thresholds = function () { + return domain.slice(); + }; + + scale.copy = function () { + return quantize$1() + .domain([x0, x1]) + .range(range) + .unknown(unknown); + }; + + return initRange.apply(linearish(scale), arguments); + } + + function threshold$1() { + var domain = [0.5], + range = [0, 1], + unknown, + n = 1; + + function scale(x) { + return x <= x ? range[bisectRight(domain, x, 0, n)] : unknown; + } + + scale.domain = function (_) { + return arguments.length ? (domain = slice$5.call(_), n = Math.min(domain.length, range.length - 1), scale) : domain.slice(); + }; + + scale.range = function (_) { + return arguments.length ? (range = slice$5.call(_), n = Math.min(domain.length, range.length - 1), scale) : range.slice(); + }; + + scale.invertExtent = function (y) { + var i = range.indexOf(y); + return [domain[i - 1], domain[i]]; + }; + + scale.unknown = function (_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + scale.copy = function () { + return threshold$1() + .domain(domain) + .range(range) + .unknown(unknown); + }; + + return initRange.apply(scale, arguments); + } + + var t0$1 = new Date, + t1$1 = new Date; + + function newInterval(floori, offseti, count, field) { + + function interval(date) { + return floori(date = arguments.length === 0 ? new Date : new Date(+date)), date; + } + + interval.floor = function (date) { + return floori(date = new Date(+date)), date; + }; + + interval.ceil = function (date) { + return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date; + }; + + interval.round = function (date) { + var d0 = interval(date), + d1 = interval.ceil(date); + return date - d0 < d1 - date ? d0 : d1; + }; + + interval.offset = function (date, step) { + return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; + }; + + interval.range = function (start, stop, step) { + var range = [], previous; + start = interval.ceil(start); + step = step == null ? 1 : Math.floor(step); + if (!(start < stop) || !(step > 0)) + return range; // also handles Invalid Date + do + range.push(previous = new Date(+start)), offseti(start, step), floori(start); + while (previous < start && start < stop); + return range; + }; + + interval.filter = function (test) { + return newInterval(function (date) { + if (date >= date) + while (floori(date), !test(date)) + date.setTime(date - 1); + }, function (date, step) { + if (date >= date) { + if (step < 0) + while (++step <= 0) { + while (offseti(date, -1), !test(date)) { + } // eslint-disable-line no-empty + } + else + while (--step >= 0) { + while (offseti(date, +1), !test(date)) { + } // eslint-disable-line no-empty + } + } + }); + }; + + if (count) { + interval.count = function (start, end) { + t0$1.setTime(+start), t1$1.setTime(+end); + floori(t0$1), floori(t1$1); + return Math.floor(count(t0$1, t1$1)); + }; + + interval.every = function (step) { + step = Math.floor(step); + return !isFinite(step) || !(step > 0) ? null + : !(step > 1) ? interval + : interval.filter(field + ? function (d) { + return field(d) % step === 0; + } + : function (d) { + return interval.count(0, d) % step === 0; + }); + }; + } + + return interval; + } + + var millisecond = newInterval(function () { + // noop + }, function (date, step) { + date.setTime(+date + step); + }, function (start, end) { + return end - start; + }); + +// An optimized implementation for this simple case. + millisecond.every = function (k) { + k = Math.floor(k); + if (!isFinite(k) || !(k > 0)) + return null; + if (!(k > 1)) + return millisecond; + return newInterval(function (date) { + date.setTime(Math.floor(date / k) * k); + }, function (date, step) { + date.setTime(+date + step * k); + }, function (start, end) { + return (end - start) / k; + }); + }; + var milliseconds = millisecond.range; + + var durationSecond = 1e3; + var durationMinute = 6e4; + var durationHour = 36e5; + var durationDay = 864e5; + var durationWeek = 6048e5; + + var second = newInterval(function (date) { + date.setTime(date - date.getMilliseconds()); + }, function (date, step) { + date.setTime(+date + step * durationSecond); + }, function (start, end) { + return (end - start) / durationSecond; + }, function (date) { + return date.getUTCSeconds(); + }); + var seconds = second.range; + + var minute = newInterval(function (date) { + date.setTime(date - date.getMilliseconds() - date.getSeconds() * durationSecond); + }, function (date, step) { + date.setTime(+date + step * durationMinute); + }, function (start, end) { + return (end - start) / durationMinute; + }, function (date) { + return date.getMinutes(); + }); + var minutes = minute.range; + + var hour = newInterval(function (date) { + date.setTime(date - date.getMilliseconds() - date.getSeconds() * durationSecond - date.getMinutes() * durationMinute); + }, function (date, step) { + date.setTime(+date + step * durationHour); + }, function (start, end) { + return (end - start) / durationHour; + }, function (date) { + return date.getHours(); + }); + var hours = hour.range; + + var day = newInterval(function (date) { + date.setHours(0, 0, 0, 0); + }, function (date, step) { + date.setDate(date.getDate() + step); + }, function (start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay; + }, function (date) { + return date.getDate() - 1; + }); + var days = day.range; + + function weekday(i) { + return newInterval(function (date) { + date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); + date.setHours(0, 0, 0, 0); + }, function (date, step) { + date.setDate(date.getDate() + step * 7); + }, function (start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek; + }); + } + + var sunday = weekday(0); + var monday = weekday(1); + var tuesday = weekday(2); + var wednesday = weekday(3); + var thursday = weekday(4); + var friday = weekday(5); + var saturday = weekday(6); + + var sundays = sunday.range; + var mondays = monday.range; + var tuesdays = tuesday.range; + var wednesdays = wednesday.range; + var thursdays = thursday.range; + var fridays = friday.range; + var saturdays = saturday.range; + + var month = newInterval(function (date) { + date.setDate(1); + date.setHours(0, 0, 0, 0); + }, function (date, step) { + date.setMonth(date.getMonth() + step); + }, function (start, end) { + return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; + }, function (date) { + return date.getMonth(); + }); + var months = month.range; + + var year = newInterval(function (date) { + date.setMonth(0, 1); + date.setHours(0, 0, 0, 0); + }, function (date, step) { + date.setFullYear(date.getFullYear() + step); + }, function (start, end) { + return end.getFullYear() - start.getFullYear(); + }, function (date) { + return date.getFullYear(); + }); + +// An optimized implementation for this simple case. + year.every = function (k) { + return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function (date) { + date.setFullYear(Math.floor(date.getFullYear() / k) * k); + date.setMonth(0, 1); + date.setHours(0, 0, 0, 0); + }, function (date, step) { + date.setFullYear(date.getFullYear() + step * k); + }); + }; + var years = year.range; + + var utcMinute = newInterval(function (date) { + date.setUTCSeconds(0, 0); + }, function (date, step) { + date.setTime(+date + step * durationMinute); + }, function (start, end) { + return (end - start) / durationMinute; + }, function (date) { + return date.getUTCMinutes(); + }); + var utcMinutes = utcMinute.range; + + var utcHour = newInterval(function (date) { + date.setUTCMinutes(0, 0, 0); + }, function (date, step) { + date.setTime(+date + step * durationHour); + }, function (start, end) { + return (end - start) / durationHour; + }, function (date) { + return date.getUTCHours(); + }); + var utcHours = utcHour.range; + + var utcDay = newInterval(function (date) { + date.setUTCHours(0, 0, 0, 0); + }, function (date, step) { + date.setUTCDate(date.getUTCDate() + step); + }, function (start, end) { + return (end - start) / durationDay; + }, function (date) { + return date.getUTCDate() - 1; + }); + var utcDays = utcDay.range; + + function utcWeekday(i) { + return newInterval(function (date) { + date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); + date.setUTCHours(0, 0, 0, 0); + }, function (date, step) { + date.setUTCDate(date.getUTCDate() + step * 7); + }, function (start, end) { + return (end - start) / durationWeek; + }); + } + + var utcSunday = utcWeekday(0); + var utcMonday = utcWeekday(1); + var utcTuesday = utcWeekday(2); + var utcWednesday = utcWeekday(3); + var utcThursday = utcWeekday(4); + var utcFriday = utcWeekday(5); + var utcSaturday = utcWeekday(6); + + var utcSundays = utcSunday.range; + var utcMondays = utcMonday.range; + var utcTuesdays = utcTuesday.range; + var utcWednesdays = utcWednesday.range; + var utcThursdays = utcThursday.range; + var utcFridays = utcFriday.range; + var utcSaturdays = utcSaturday.range; + + var utcMonth = newInterval(function (date) { + date.setUTCDate(1); + date.setUTCHours(0, 0, 0, 0); + }, function (date, step) { + date.setUTCMonth(date.getUTCMonth() + step); + }, function (start, end) { + return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; + }, function (date) { + return date.getUTCMonth(); + }); + var utcMonths = utcMonth.range; + + var utcYear = newInterval(function (date) { + date.setUTCMonth(0, 1); + date.setUTCHours(0, 0, 0, 0); + }, function (date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step); + }, function (start, end) { + return end.getUTCFullYear() - start.getUTCFullYear(); + }, function (date) { + return date.getUTCFullYear(); + }); + +// An optimized implementation for this simple case. + utcYear.every = function (k) { + return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function (date) { + date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k); + date.setUTCMonth(0, 1); + date.setUTCHours(0, 0, 0, 0); + }, function (date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step * k); + }); + }; + var utcYears = utcYear.range; + + function localDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); + date.setFullYear(d.y); + return date; + } + return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); + } + + function utcDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); + date.setUTCFullYear(d.y); + return date; + } + return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); + } + + function newDate(y, m, d) { + return {y: y, m: m, d: d, H: 0, M: 0, S: 0, L: 0}; + } + + function formatLocale$1(locale) { + var locale_dateTime = locale.dateTime, + locale_date = locale.date, + locale_time = locale.time, + locale_periods = locale.periods, + locale_weekdays = locale.days, + locale_shortWeekdays = locale.shortDays, + locale_months = locale.months, + locale_shortMonths = locale.shortMonths; + + var periodRe = formatRe(locale_periods), + periodLookup = formatLookup(locale_periods), + weekdayRe = formatRe(locale_weekdays), + weekdayLookup = formatLookup(locale_weekdays), + shortWeekdayRe = formatRe(locale_shortWeekdays), + shortWeekdayLookup = formatLookup(locale_shortWeekdays), + monthRe = formatRe(locale_months), + monthLookup = formatLookup(locale_months), + shortMonthRe = formatRe(locale_shortMonths), + shortMonthLookup = formatLookup(locale_shortMonths); + + var formats = { + "a": formatShortWeekday, + "A": formatWeekday, + "b": formatShortMonth, + "B": formatMonth, + "c": null, + "d": formatDayOfMonth, + "e": formatDayOfMonth, + "f": formatMicroseconds, + "H": formatHour24, + "I": formatHour12, + "j": formatDayOfYear, + "L": formatMilliseconds, + "m": formatMonthNumber, + "M": formatMinutes, + "p": formatPeriod, + "q": formatQuarter, + "Q": formatUnixTimestamp, + "s": formatUnixTimestampSeconds, + "S": formatSeconds, + "u": formatWeekdayNumberMonday, + "U": formatWeekNumberSunday, + "V": formatWeekNumberISO, + "w": formatWeekdayNumberSunday, + "W": formatWeekNumberMonday, + "x": null, + "X": null, + "y": formatYear$1, + "Y": formatFullYear, + "Z": formatZone, + "%": formatLiteralPercent + }; + + var utcFormats = { + "a": formatUTCShortWeekday, + "A": formatUTCWeekday, + "b": formatUTCShortMonth, + "B": formatUTCMonth, + "c": null, + "d": formatUTCDayOfMonth, + "e": formatUTCDayOfMonth, + "f": formatUTCMicroseconds, + "H": formatUTCHour24, + "I": formatUTCHour12, + "j": formatUTCDayOfYear, + "L": formatUTCMilliseconds, + "m": formatUTCMonthNumber, + "M": formatUTCMinutes, + "p": formatUTCPeriod, + "q": formatUTCQuarter, + "Q": formatUnixTimestamp, + "s": formatUnixTimestampSeconds, + "S": formatUTCSeconds, + "u": formatUTCWeekdayNumberMonday, + "U": formatUTCWeekNumberSunday, + "V": formatUTCWeekNumberISO, + "w": formatUTCWeekdayNumberSunday, + "W": formatUTCWeekNumberMonday, + "x": null, + "X": null, + "y": formatUTCYear, + "Y": formatUTCFullYear, + "Z": formatUTCZone, + "%": formatLiteralPercent + }; + + var parses = { + "a": parseShortWeekday, + "A": parseWeekday, + "b": parseShortMonth, + "B": parseMonth, + "c": parseLocaleDateTime, + "d": parseDayOfMonth, + "e": parseDayOfMonth, + "f": parseMicroseconds, + "H": parseHour24, + "I": parseHour24, + "j": parseDayOfYear, + "L": parseMilliseconds, + "m": parseMonthNumber, + "M": parseMinutes, + "p": parsePeriod, + "q": parseQuarter, + "Q": parseUnixTimestamp, + "s": parseUnixTimestampSeconds, + "S": parseSeconds, + "u": parseWeekdayNumberMonday, + "U": parseWeekNumberSunday, + "V": parseWeekNumberISO, + "w": parseWeekdayNumberSunday, + "W": parseWeekNumberMonday, + "x": parseLocaleDate, + "X": parseLocaleTime, + "y": parseYear, + "Y": parseFullYear, + "Z": parseZone, + "%": parseLiteralPercent + }; + + // These recursive directive definitions must be deferred. + formats.x = newFormat(locale_date, formats); + formats.X = newFormat(locale_time, formats); + formats.c = newFormat(locale_dateTime, formats); + utcFormats.x = newFormat(locale_date, utcFormats); + utcFormats.X = newFormat(locale_time, utcFormats); + utcFormats.c = newFormat(locale_dateTime, utcFormats); + + function newFormat(specifier, formats) { + return function (date) { + var string = [], + i = -1, + j = 0, + n = specifier.length, + c, + pad, + format; + + if (!(date instanceof Date)) + date = new Date(+date); + + while (++i < n) { + if (specifier.charCodeAt(i) === 37) { + string.push(specifier.slice(j, i)); + if ((pad = pads[c = specifier.charAt(++i)]) != null) + c = specifier.charAt(++i); + else + pad = c === "e" ? " " : "0"; + if (format = formats[c]) + c = format(date, pad); + string.push(c); + j = i + 1; + } + } + + string.push(specifier.slice(j, i)); + return string.join(""); + }; + } + + function newParse(specifier, Z) { + return function (string) { + var d = newDate(1900, undefined, 1), + i = parseSpecifier(d, specifier, string += "", 0), + week, day$1; + if (i != string.length) + return null; + + // If a UNIX timestamp is specified, return it. + if ("Q" in d) + return new Date(d.Q); + if ("s" in d) + return new Date(d.s * 1000 + ("L" in d ? d.L : 0)); + + // If this is utcParse, never use the local timezone. + if (Z && !("Z" in d)) + d.Z = 0; + + // The am-pm flag is 0 for AM, and 1 for PM. + if ("p" in d) + d.H = d.H % 12 + d.p * 12; + + // If the month was not specified, inherit from the quarter. + if (d.m === undefined) + d.m = "q" in d ? d.q : 0; + + // Convert day-of-week and week-of-year to day-of-year. + if ("V" in d) { + if (d.V < 1 || d.V > 53) + return null; + if (!("w" in d)) + d.w = 1; + if ("Z" in d) { + week = utcDate(newDate(d.y, 0, 1)), day$1 = week.getUTCDay(); + week = day$1 > 4 || day$1 === 0 ? utcMonday.ceil(week) : utcMonday(week); + week = utcDay.offset(week, (d.V - 1) * 7); + d.y = week.getUTCFullYear(); + d.m = week.getUTCMonth(); + d.d = week.getUTCDate() + (d.w + 6) % 7; + } else { + week = localDate(newDate(d.y, 0, 1)), day$1 = week.getDay(); + week = day$1 > 4 || day$1 === 0 ? monday.ceil(week) : monday(week); + week = day.offset(week, (d.V - 1) * 7); + d.y = week.getFullYear(); + d.m = week.getMonth(); + d.d = week.getDate() + (d.w + 6) % 7; + } + } else if ("W" in d || "U" in d) { + if (!("w" in d)) + d.w = "u" in d ? d.u % 7 : "W" in d ? 1 : 0; + day$1 = "Z" in d ? utcDate(newDate(d.y, 0, 1)).getUTCDay() : localDate(newDate(d.y, 0, 1)).getDay(); + d.m = 0; + d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day$1 + 5) % 7 : d.w + d.U * 7 - (day$1 + 6) % 7; + } + + // If a time zone is specified, all fields are interpreted as UTC and then + // offset according to the specified time zone. + if ("Z" in d) { + d.H += d.Z / 100 | 0; + d.M += d.Z % 100; + return utcDate(d); + } + + // Otherwise, all fields are in local time. + return localDate(d); + }; + } + + function parseSpecifier(d, specifier, string, j) { + var i = 0, + n = specifier.length, + m = string.length, + c, + parse; + + while (i < n) { + if (j >= m) + return -1; + c = specifier.charCodeAt(i++); + if (c === 37) { + c = specifier.charAt(i++); + parse = parses[c in pads ? specifier.charAt(i++) : c]; + if (!parse || ((j = parse(d, string, j)) < 0)) + return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } + + return j; + } + + function parsePeriod(d, string, i) { + var n = periodRe.exec(string.slice(i)); + return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseShortWeekday(d, string, i) { + var n = shortWeekdayRe.exec(string.slice(i)); + return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseWeekday(d, string, i) { + var n = weekdayRe.exec(string.slice(i)); + return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseShortMonth(d, string, i) { + var n = shortMonthRe.exec(string.slice(i)); + return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseMonth(d, string, i) { + var n = monthRe.exec(string.slice(i)); + return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseLocaleDateTime(d, string, i) { + return parseSpecifier(d, locale_dateTime, string, i); + } + + function parseLocaleDate(d, string, i) { + return parseSpecifier(d, locale_date, string, i); + } + + function parseLocaleTime(d, string, i) { + return parseSpecifier(d, locale_time, string, i); + } + + function formatShortWeekday(d) { + return locale_shortWeekdays[d.getDay()]; + } + + function formatWeekday(d) { + return locale_weekdays[d.getDay()]; + } + + function formatShortMonth(d) { + return locale_shortMonths[d.getMonth()]; + } + + function formatMonth(d) { + return locale_months[d.getMonth()]; + } + + function formatPeriod(d) { + return locale_periods[+(d.getHours() >= 12)]; + } + + function formatQuarter(d) { + return 1 + ~~(d.getMonth() / 3); + } + + function formatUTCShortWeekday(d) { + return locale_shortWeekdays[d.getUTCDay()]; + } + + function formatUTCWeekday(d) { + return locale_weekdays[d.getUTCDay()]; + } + + function formatUTCShortMonth(d) { + return locale_shortMonths[d.getUTCMonth()]; + } + + function formatUTCMonth(d) { + return locale_months[d.getUTCMonth()]; + } + + function formatUTCPeriod(d) { + return locale_periods[+(d.getUTCHours() >= 12)]; + } + + function formatUTCQuarter(d) { + return 1 + ~~(d.getUTCMonth() / 3); + } + + return { + format: function (specifier) { + var f = newFormat(specifier += "", formats); + f.toString = function () { + return specifier; + }; + return f; + }, + parse: function (specifier) { + var p = newParse(specifier += "", false); + p.toString = function () { + return specifier; + }; + return p; + }, + utcFormat: function (specifier) { + var f = newFormat(specifier += "", utcFormats); + f.toString = function () { + return specifier; + }; + return f; + }, + utcParse: function (specifier) { + var p = newParse(specifier += "", true); + p.toString = function () { + return specifier; + }; + return p; + } + }; + } + + var pads = {"-": "", "_": " ", "0": "0"}, + numberRe = /^\s*\d+/, // note: ignores next directive + percentRe = /^%/, + requoteRe = /[\\^$*+?|[\]().{}]/g; + + function pad$1(value, fill, width) { + var sign = value < 0 ? "-" : "", + string = (sign ? -value : value) + "", + length = string.length; + return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); + } + + function requote(s) { + return s.replace(requoteRe, "\\$&"); + } + + function formatRe(names) { + return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); + } + + function formatLookup(names) { + var map = {}, i = -1, n = names.length; + while (++i < n) + map[names[i].toLowerCase()] = i; + return map; + } + + function parseWeekdayNumberSunday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + return n ? (d.w = +n[0], i + n[0].length) : -1; + } + + function parseWeekdayNumberMonday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + return n ? (d.u = +n[0], i + n[0].length) : -1; + } + + function parseWeekNumberSunday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.U = +n[0], i + n[0].length) : -1; + } + + function parseWeekNumberISO(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.V = +n[0], i + n[0].length) : -1; + } + + function parseWeekNumberMonday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.W = +n[0], i + n[0].length) : -1; + } + + function parseFullYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 4)); + return n ? (d.y = +n[0], i + n[0].length) : -1; + } + + function parseYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; + } + + function parseZone(d, string, i) { + var n = /^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(string.slice(i, i + 6)); + return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1; + } + + function parseQuarter(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + return n ? (d.q = n[0] * 3 - 3, i + n[0].length) : -1; + } + + function parseMonthNumber(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.m = n[0] - 1, i + n[0].length) : -1; + } + + function parseDayOfMonth(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.d = +n[0], i + n[0].length) : -1; + } + + function parseDayOfYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; + } + + function parseHour24(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.H = +n[0], i + n[0].length) : -1; + } + + function parseMinutes(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.M = +n[0], i + n[0].length) : -1; + } + + function parseSeconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.S = +n[0], i + n[0].length) : -1; + } + + function parseMilliseconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.L = +n[0], i + n[0].length) : -1; + } + + function parseMicroseconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 6)); + return n ? (d.L = Math.floor(n[0] / 1000), i + n[0].length) : -1; + } + + function parseLiteralPercent(d, string, i) { + var n = percentRe.exec(string.slice(i, i + 1)); + return n ? i + n[0].length : -1; + } + + function parseUnixTimestamp(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.Q = +n[0], i + n[0].length) : -1; + } + + function parseUnixTimestampSeconds(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.s = +n[0], i + n[0].length) : -1; + } + + function formatDayOfMonth(d, p) { + return pad$1(d.getDate(), p, 2); + } + + function formatHour24(d, p) { + return pad$1(d.getHours(), p, 2); + } + + function formatHour12(d, p) { + return pad$1(d.getHours() % 12 || 12, p, 2); + } + + function formatDayOfYear(d, p) { + return pad$1(1 + day.count(year(d), d), p, 3); + } + + function formatMilliseconds(d, p) { + return pad$1(d.getMilliseconds(), p, 3); + } + + function formatMicroseconds(d, p) { + return formatMilliseconds(d, p) + "000"; + } + + function formatMonthNumber(d, p) { + return pad$1(d.getMonth() + 1, p, 2); + } + + function formatMinutes(d, p) { + return pad$1(d.getMinutes(), p, 2); + } + + function formatSeconds(d, p) { + return pad$1(d.getSeconds(), p, 2); + } + + function formatWeekdayNumberMonday(d) { + var day = d.getDay(); + return day === 0 ? 7 : day; + } + + function formatWeekNumberSunday(d, p) { + return pad$1(sunday.count(year(d) - 1, d), p, 2); + } + + function formatWeekNumberISO(d, p) { + var day = d.getDay(); + d = (day >= 4 || day === 0) ? thursday(d) : thursday.ceil(d); + return pad$1(thursday.count(year(d), d) + (year(d).getDay() === 4), p, 2); + } + + function formatWeekdayNumberSunday(d) { + return d.getDay(); + } + + function formatWeekNumberMonday(d, p) { + return pad$1(monday.count(year(d) - 1, d), p, 2); + } + + function formatYear$1(d, p) { + return pad$1(d.getFullYear() % 100, p, 2); + } + + function formatFullYear(d, p) { + return pad$1(d.getFullYear() % 10000, p, 4); + } + + function formatZone(d) { + var z = d.getTimezoneOffset(); + return (z > 0 ? "-" : (z *= -1, "+")) + + pad$1(z / 60 | 0, "0", 2) + + pad$1(z % 60, "0", 2); + } + + function formatUTCDayOfMonth(d, p) { + return pad$1(d.getUTCDate(), p, 2); + } + + function formatUTCHour24(d, p) { + return pad$1(d.getUTCHours(), p, 2); + } + + function formatUTCHour12(d, p) { + return pad$1(d.getUTCHours() % 12 || 12, p, 2); + } + + function formatUTCDayOfYear(d, p) { + return pad$1(1 + utcDay.count(utcYear(d), d), p, 3); + } + + function formatUTCMilliseconds(d, p) { + return pad$1(d.getUTCMilliseconds(), p, 3); + } + + function formatUTCMicroseconds(d, p) { + return formatUTCMilliseconds(d, p) + "000"; + } + + function formatUTCMonthNumber(d, p) { + return pad$1(d.getUTCMonth() + 1, p, 2); + } + + function formatUTCMinutes(d, p) { + return pad$1(d.getUTCMinutes(), p, 2); + } + + function formatUTCSeconds(d, p) { + return pad$1(d.getUTCSeconds(), p, 2); + } + + function formatUTCWeekdayNumberMonday(d) { + var dow = d.getUTCDay(); + return dow === 0 ? 7 : dow; + } + + function formatUTCWeekNumberSunday(d, p) { + return pad$1(utcSunday.count(utcYear(d) - 1, d), p, 2); + } + + function formatUTCWeekNumberISO(d, p) { + var day = d.getUTCDay(); + d = (day >= 4 || day === 0) ? utcThursday(d) : utcThursday.ceil(d); + return pad$1(utcThursday.count(utcYear(d), d) + (utcYear(d).getUTCDay() === 4), p, 2); + } + + function formatUTCWeekdayNumberSunday(d) { + return d.getUTCDay(); + } + + function formatUTCWeekNumberMonday(d, p) { + return pad$1(utcMonday.count(utcYear(d) - 1, d), p, 2); + } + + function formatUTCYear(d, p) { + return pad$1(d.getUTCFullYear() % 100, p, 2); + } + + function formatUTCFullYear(d, p) { + return pad$1(d.getUTCFullYear() % 10000, p, 4); + } + + function formatUTCZone() { + return "+0000"; + } + + function formatLiteralPercent() { + return "%"; + } + + function formatUnixTimestamp(d) { + return +d; + } + + function formatUnixTimestampSeconds(d) { + return Math.floor(+d / 1000); + } + + var locale$1; + + defaultLocale$1({ + dateTime: "%x, %X", + date: "%-m/%-d/%Y", + time: "%-I:%M:%S %p", + periods: ["AM", "PM"], + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + }); + + function defaultLocale$1(definition) { + locale$1 = formatLocale$1(definition); + exports.timeFormat = locale$1.format; + exports.timeParse = locale$1.parse; + exports.utcFormat = locale$1.utcFormat; + exports.utcParse = locale$1.utcParse; + return locale$1; + } + + var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; + + function formatIsoNative(date) { + return date.toISOString(); + } + + var formatIso = Date.prototype.toISOString + ? formatIsoNative + : exports.utcFormat(isoSpecifier); + + function parseIsoNative(string) { + var date = new Date(string); + return isNaN(date) ? null : date; + } + + var parseIso = +new Date("2000-01-01T00:00:00.000Z") + ? parseIsoNative + : exports.utcParse(isoSpecifier); + + var durationSecond$1 = 1000, + durationMinute$1 = durationSecond$1 * 60, + durationHour$1 = durationMinute$1 * 60, + durationDay$1 = durationHour$1 * 24, + durationWeek$1 = durationDay$1 * 7, + durationMonth = durationDay$1 * 30, + durationYear = durationDay$1 * 365; + + function date$1(t) { + return new Date(t); + } + + function number$3(t) { + return t instanceof Date ? +t : +new Date(+t); + } + + function calendar(year, month, week, day, hour, minute, second, millisecond, format) { + var scale = continuous(identity$6, identity$6), + invert = scale.invert, + domain = scale.domain; + + var formatMillisecond = format(".%L"), + formatSecond = format(":%S"), + formatMinute = format("%I:%M"), + formatHour = format("%I %p"), + formatDay = format("%a %d"), + formatWeek = format("%b %d"), + formatMonth = format("%B"), + formatYear = format("%Y"); + + var tickIntervals = [ + [second, 1, durationSecond$1], + [second, 5, 5 * durationSecond$1], + [second, 15, 15 * durationSecond$1], + [second, 30, 30 * durationSecond$1], + [minute, 1, durationMinute$1], + [minute, 5, 5 * durationMinute$1], + [minute, 15, 15 * durationMinute$1], + [minute, 30, 30 * durationMinute$1], + [hour, 1, durationHour$1], + [hour, 3, 3 * durationHour$1], + [hour, 6, 6 * durationHour$1], + [hour, 12, 12 * durationHour$1], + [day, 1, durationDay$1], + [day, 2, 2 * durationDay$1], + [week, 1, durationWeek$1], + [month, 1, durationMonth], + [month, 3, 3 * durationMonth], + [year, 1, durationYear] + ]; + + function tickFormat(date) { + return (second(date) < date ? formatMillisecond + : minute(date) < date ? formatSecond + : hour(date) < date ? formatMinute + : day(date) < date ? formatHour + : month(date) < date ? (week(date) < date ? formatDay : formatWeek) + : year(date) < date ? formatMonth + : formatYear)(date); + } + + function tickInterval(interval, start, stop, step) { + if (interval == null) + interval = 10; + + // If a desired tick count is specified, pick a reasonable tick interval + // based on the extent of the domain and a rough estimate of tick size. + // Otherwise, assume interval is already a time interval and use it. + if (typeof interval === "number") { + var target = Math.abs(stop - start) / interval, + i = bisector(function (i) { + return i[2]; + }).right(tickIntervals, target); + if (i === tickIntervals.length) { + step = tickStep(start / durationYear, stop / durationYear, interval); + interval = year; + } else if (i) { + i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i]; + step = i[1]; + interval = i[0]; + } else { + step = Math.max(tickStep(start, stop, interval), 1); + interval = millisecond; + } + } + + return step == null ? interval : interval.every(step); + } + + scale.invert = function (y) { + return new Date(invert(y)); + }; + + scale.domain = function (_) { + return arguments.length ? domain(map$3.call(_, number$3)) : domain().map(date$1); + }; + + scale.ticks = function (interval, step) { + var d = domain(), + t0 = d[0], + t1 = d[d.length - 1], + r = t1 < t0, + t; + if (r) + t = t0, t0 = t1, t1 = t; + t = tickInterval(interval, t0, t1, step); + t = t ? t.range(t0, t1 + 1) : []; // inclusive stop + return r ? t.reverse() : t; + }; + + scale.tickFormat = function (count, specifier) { + return specifier == null ? tickFormat : format(specifier); + }; + + scale.nice = function (interval, step) { + var d = domain(); + return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) + ? domain(nice(d, interval)) + : scale; + }; + + scale.copy = function () { + return copy(scale, calendar(year, month, week, day, hour, minute, second, millisecond, format)); + }; + + return scale; + } + + function time() { + return initRange.apply(calendar(year, month, sunday, day, hour, minute, second, millisecond, exports.timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]), arguments); + } + + function utcTime() { + return initRange.apply(calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, exports.utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]), arguments); + } + + function transformer$2() { + var x0 = 0, + x1 = 1, + t0, + t1, + k10, + transform, + interpolator = identity$6, + clamp = false, + unknown; + + function scale(x) { + return isNaN(x = +x) ? unknown : interpolator(k10 === 0 ? 0.5 : (x = (transform(x) - t0) * k10, clamp ? Math.max(0, Math.min(1, x)) : x)); + } + + scale.domain = function (_) { + return arguments.length ? (t0 = transform(x0 = +_[0]), t1 = transform(x1 = +_[1]), k10 = t0 === t1 ? 0 : 1 / (t1 - t0), scale) : [x0, x1]; + }; + + scale.clamp = function (_) { + return arguments.length ? (clamp = !!_, scale) : clamp; + }; + + scale.interpolator = function (_) { + return arguments.length ? (interpolator = _, scale) : interpolator; + }; + + scale.unknown = function (_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + return function (t) { + transform = t, t0 = t(x0), t1 = t(x1), k10 = t0 === t1 ? 0 : 1 / (t1 - t0); + return scale; + }; + } + + function copy$1(source, target) { + return target + .domain(source.domain()) + .interpolator(source.interpolator()) + .clamp(source.clamp()) + .unknown(source.unknown()); + } + + function sequential() { + var scale = linearish(transformer$2()(identity$6)); + + scale.copy = function () { + return copy$1(scale, sequential()); + }; + + return initInterpolator.apply(scale, arguments); + } + + function sequentialLog() { + var scale = loggish(transformer$2()).domain([1, 10]); + + scale.copy = function () { + return copy$1(scale, sequentialLog()).base(scale.base()); + }; + + return initInterpolator.apply(scale, arguments); + } + + function sequentialSymlog() { + var scale = symlogish(transformer$2()); + + scale.copy = function () { + return copy$1(scale, sequentialSymlog()).constant(scale.constant()); + }; + + return initInterpolator.apply(scale, arguments); + } + + function sequentialPow() { + var scale = powish(transformer$2()); + + scale.copy = function () { + return copy$1(scale, sequentialPow()).exponent(scale.exponent()); + }; + + return initInterpolator.apply(scale, arguments); + } + + function sequentialSqrt() { + return sequentialPow.apply(null, arguments).exponent(0.5); + } + + function sequentialQuantile() { + var domain = [], + interpolator = identity$6; + + function scale(x) { + if (!isNaN(x = +x)) + return interpolator((bisectRight(domain, x) - 1) / (domain.length - 1)); + } + + scale.domain = function (_) { + if (!arguments.length) + return domain.slice(); + domain = []; + for (var i = 0, n = _.length, d; i < n; ++i) + if (d = _[i], d != null && !isNaN(d = +d)) + domain.push(d); + domain.sort(ascending); + return scale; + }; + + scale.interpolator = function (_) { + return arguments.length ? (interpolator = _, scale) : interpolator; + }; + + scale.copy = function () { + return sequentialQuantile(interpolator).domain(domain); + }; + + return initInterpolator.apply(scale, arguments); + } + + function transformer$3() { + var x0 = 0, + x1 = 0.5, + x2 = 1, + t0, + t1, + t2, + k10, + k21, + interpolator = identity$6, + transform, + clamp = false, + unknown; + + function scale(x) { + return isNaN(x = +x) ? unknown : (x = 0.5 + ((x = +transform(x)) - t1) * (x < t1 ? k10 : k21), interpolator(clamp ? Math.max(0, Math.min(1, x)) : x)); + } + + scale.domain = function (_) { + return arguments.length ? (t0 = transform(x0 = +_[0]), t1 = transform(x1 = +_[1]), t2 = transform(x2 = +_[2]), k10 = t0 === t1 ? 0 : 0.5 / (t1 - t0), k21 = t1 === t2 ? 0 : 0.5 / (t2 - t1), scale) : [x0, x1, x2]; + }; + + scale.clamp = function (_) { + return arguments.length ? (clamp = !!_, scale) : clamp; + }; + + scale.interpolator = function (_) { + return arguments.length ? (interpolator = _, scale) : interpolator; + }; + + scale.unknown = function (_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + return function (t) { + transform = t, t0 = t(x0), t1 = t(x1), t2 = t(x2), k10 = t0 === t1 ? 0 : 0.5 / (t1 - t0), k21 = t1 === t2 ? 0 : 0.5 / (t2 - t1); + return scale; + }; + } + + function diverging() { + var scale = linearish(transformer$3()(identity$6)); + + scale.copy = function () { + return copy$1(scale, diverging()); + }; + + return initInterpolator.apply(scale, arguments); + } + + function divergingLog() { + var scale = loggish(transformer$3()).domain([0.1, 1, 10]); + + scale.copy = function () { + return copy$1(scale, divergingLog()).base(scale.base()); + }; + + return initInterpolator.apply(scale, arguments); + } + + function divergingSymlog() { + var scale = symlogish(transformer$3()); + + scale.copy = function () { + return copy$1(scale, divergingSymlog()).constant(scale.constant()); + }; + + return initInterpolator.apply(scale, arguments); + } + + function divergingPow() { + var scale = powish(transformer$3()); + + scale.copy = function () { + return copy$1(scale, divergingPow()).exponent(scale.exponent()); + }; + + return initInterpolator.apply(scale, arguments); + } + + function divergingSqrt() { + return divergingPow.apply(null, arguments).exponent(0.5); + } + + function colors(specifier) { + var n = specifier.length / 6 | 0, colors = new Array(n), i = 0; + while (i < n) + colors[i] = "#" + specifier.slice(i * 6, ++i * 6); + return colors; + } + + var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"); + + var Accent = colors("7fc97fbeaed4fdc086ffff99386cb0f0027fbf5b17666666"); + + var Dark2 = colors("1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666"); + + var Paired = colors("a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928"); + + var Pastel1 = colors("fbb4aeb3cde3ccebc5decbe4fed9a6ffffcce5d8bdfddaecf2f2f2"); + + var Pastel2 = colors("b3e2cdfdcdaccbd5e8f4cae4e6f5c9fff2aef1e2cccccccc"); + + var Set1 = colors("e41a1c377eb84daf4a984ea3ff7f00ffff33a65628f781bf999999"); + + var Set2 = colors("66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3"); + + var Set3 = colors("8dd3c7ffffb3bebadafb807280b1d3fdb462b3de69fccde5d9d9d9bc80bdccebc5ffed6f"); + + var Tableau10 = colors("4e79a7f28e2ce1575976b7b259a14fedc949af7aa1ff9da79c755fbab0ab"); + + function ramp(scheme) { + return rgbBasis(scheme[scheme.length - 1]); + } + + var scheme = new Array(3).concat( + "d8b365f5f5f55ab4ac", + "a6611adfc27d80cdc1018571", + "a6611adfc27df5f5f580cdc1018571", + "8c510ad8b365f6e8c3c7eae55ab4ac01665e", + "8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e", + "8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e", + "8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e", + "5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30", + "5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30" + ).map(colors); + + var BrBG = ramp(scheme); + + var scheme$1 = new Array(3).concat( + "af8dc3f7f7f77fbf7b", + "7b3294c2a5cfa6dba0008837", + "7b3294c2a5cff7f7f7a6dba0008837", + "762a83af8dc3e7d4e8d9f0d37fbf7b1b7837", + "762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837", + "762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837", + "762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837", + "40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b", + "40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b" + ).map(colors); + + var PRGn = ramp(scheme$1); + + var scheme$2 = new Array(3).concat( + "e9a3c9f7f7f7a1d76a", + "d01c8bf1b6dab8e1864dac26", + "d01c8bf1b6daf7f7f7b8e1864dac26", + "c51b7de9a3c9fde0efe6f5d0a1d76a4d9221", + "c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221", + "c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221", + "c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221", + "8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419", + "8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419" + ).map(colors); + + var PiYG = ramp(scheme$2); + + var scheme$3 = new Array(3).concat( + "998ec3f7f7f7f1a340", + "5e3c99b2abd2fdb863e66101", + "5e3c99b2abd2f7f7f7fdb863e66101", + "542788998ec3d8daebfee0b6f1a340b35806", + "542788998ec3d8daebf7f7f7fee0b6f1a340b35806", + "5427888073acb2abd2d8daebfee0b6fdb863e08214b35806", + "5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806", + "2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08", + "2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08" + ).map(colors); + + var PuOr = ramp(scheme$3); + + var scheme$4 = new Array(3).concat( + "ef8a62f7f7f767a9cf", + "ca0020f4a58292c5de0571b0", + "ca0020f4a582f7f7f792c5de0571b0", + "b2182bef8a62fddbc7d1e5f067a9cf2166ac", + "b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac", + "b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac", + "b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac", + "67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061", + "67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061" + ).map(colors); + + var RdBu = ramp(scheme$4); + + var scheme$5 = new Array(3).concat( + "ef8a62ffffff999999", + "ca0020f4a582bababa404040", + "ca0020f4a582ffffffbababa404040", + "b2182bef8a62fddbc7e0e0e09999994d4d4d", + "b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d", + "b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d", + "b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d", + "67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a", + "67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a" + ).map(colors); + + var RdGy = ramp(scheme$5); + + var scheme$6 = new Array(3).concat( + "fc8d59ffffbf91bfdb", + "d7191cfdae61abd9e92c7bb6", + "d7191cfdae61ffffbfabd9e92c7bb6", + "d73027fc8d59fee090e0f3f891bfdb4575b4", + "d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4", + "d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4", + "d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4", + "a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695", + "a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695" + ).map(colors); + + var RdYlBu = ramp(scheme$6); + + var scheme$7 = new Array(3).concat( + "fc8d59ffffbf91cf60", + "d7191cfdae61a6d96a1a9641", + "d7191cfdae61ffffbfa6d96a1a9641", + "d73027fc8d59fee08bd9ef8b91cf601a9850", + "d73027fc8d59fee08bffffbfd9ef8b91cf601a9850", + "d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850", + "d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850", + "a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837", + "a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837" + ).map(colors); + + var RdYlGn = ramp(scheme$7); + + var scheme$8 = new Array(3).concat( + "fc8d59ffffbf99d594", + "d7191cfdae61abdda42b83ba", + "d7191cfdae61ffffbfabdda42b83ba", + "d53e4ffc8d59fee08be6f59899d5943288bd", + "d53e4ffc8d59fee08bffffbfe6f59899d5943288bd", + "d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd", + "d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd", + "9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2", + "9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2" + ).map(colors); + + var Spectral = ramp(scheme$8); + + var scheme$9 = new Array(3).concat( + "e5f5f999d8c92ca25f", + "edf8fbb2e2e266c2a4238b45", + "edf8fbb2e2e266c2a42ca25f006d2c", + "edf8fbccece699d8c966c2a42ca25f006d2c", + "edf8fbccece699d8c966c2a441ae76238b45005824", + "f7fcfde5f5f9ccece699d8c966c2a441ae76238b45005824", + "f7fcfde5f5f9ccece699d8c966c2a441ae76238b45006d2c00441b" + ).map(colors); + + var BuGn = ramp(scheme$9); + + var scheme$a = new Array(3).concat( + "e0ecf49ebcda8856a7", + "edf8fbb3cde38c96c688419d", + "edf8fbb3cde38c96c68856a7810f7c", + "edf8fbbfd3e69ebcda8c96c68856a7810f7c", + "edf8fbbfd3e69ebcda8c96c68c6bb188419d6e016b", + "f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d6e016b", + "f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d810f7c4d004b" + ).map(colors); + + var BuPu = ramp(scheme$a); + + var scheme$b = new Array(3).concat( + "e0f3dba8ddb543a2ca", + "f0f9e8bae4bc7bccc42b8cbe", + "f0f9e8bae4bc7bccc443a2ca0868ac", + "f0f9e8ccebc5a8ddb57bccc443a2ca0868ac", + "f0f9e8ccebc5a8ddb57bccc44eb3d32b8cbe08589e", + "f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe08589e", + "f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe0868ac084081" + ).map(colors); + + var GnBu = ramp(scheme$b); + + var scheme$c = new Array(3).concat( + "fee8c8fdbb84e34a33", + "fef0d9fdcc8afc8d59d7301f", + "fef0d9fdcc8afc8d59e34a33b30000", + "fef0d9fdd49efdbb84fc8d59e34a33b30000", + "fef0d9fdd49efdbb84fc8d59ef6548d7301f990000", + "fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301f990000", + "fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301fb300007f0000" + ).map(colors); + + var OrRd = ramp(scheme$c); + + var scheme$d = new Array(3).concat( + "ece2f0a6bddb1c9099", + "f6eff7bdc9e167a9cf02818a", + "f6eff7bdc9e167a9cf1c9099016c59", + "f6eff7d0d1e6a6bddb67a9cf1c9099016c59", + "f6eff7d0d1e6a6bddb67a9cf3690c002818a016450", + "fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016450", + "fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016c59014636" + ).map(colors); + + var PuBuGn = ramp(scheme$d); + + var scheme$e = new Array(3).concat( + "ece7f2a6bddb2b8cbe", + "f1eef6bdc9e174a9cf0570b0", + "f1eef6bdc9e174a9cf2b8cbe045a8d", + "f1eef6d0d1e6a6bddb74a9cf2b8cbe045a8d", + "f1eef6d0d1e6a6bddb74a9cf3690c00570b0034e7b", + "fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0034e7b", + "fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0045a8d023858" + ).map(colors); + + var PuBu = ramp(scheme$e); + + var scheme$f = new Array(3).concat( + "e7e1efc994c7dd1c77", + "f1eef6d7b5d8df65b0ce1256", + "f1eef6d7b5d8df65b0dd1c77980043", + "f1eef6d4b9dac994c7df65b0dd1c77980043", + "f1eef6d4b9dac994c7df65b0e7298ace125691003f", + "f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125691003f", + "f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125698004367001f" + ).map(colors); + + var PuRd = ramp(scheme$f); + + var scheme$g = new Array(3).concat( + "fde0ddfa9fb5c51b8a", + "feebe2fbb4b9f768a1ae017e", + "feebe2fbb4b9f768a1c51b8a7a0177", + "feebe2fcc5c0fa9fb5f768a1c51b8a7a0177", + "feebe2fcc5c0fa9fb5f768a1dd3497ae017e7a0177", + "fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a0177", + "fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a017749006a" + ).map(colors); + + var RdPu = ramp(scheme$g); + + var scheme$h = new Array(3).concat( + "edf8b17fcdbb2c7fb8", + "ffffcca1dab441b6c4225ea8", + "ffffcca1dab441b6c42c7fb8253494", + "ffffccc7e9b47fcdbb41b6c42c7fb8253494", + "ffffccc7e9b47fcdbb41b6c41d91c0225ea80c2c84", + "ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea80c2c84", + "ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea8253494081d58" + ).map(colors); + + var YlGnBu = ramp(scheme$h); + + var scheme$i = new Array(3).concat( + "f7fcb9addd8e31a354", + "ffffccc2e69978c679238443", + "ffffccc2e69978c67931a354006837", + "ffffccd9f0a3addd8e78c67931a354006837", + "ffffccd9f0a3addd8e78c67941ab5d238443005a32", + "ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443005a32", + "ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443006837004529" + ).map(colors); + + var YlGn = ramp(scheme$i); + + var scheme$j = new Array(3).concat( + "fff7bcfec44fd95f0e", + "ffffd4fed98efe9929cc4c02", + "ffffd4fed98efe9929d95f0e993404", + "ffffd4fee391fec44ffe9929d95f0e993404", + "ffffd4fee391fec44ffe9929ec7014cc4c028c2d04", + "ffffe5fff7bcfee391fec44ffe9929ec7014cc4c028c2d04", + "ffffe5fff7bcfee391fec44ffe9929ec7014cc4c02993404662506" + ).map(colors); + + var YlOrBr = ramp(scheme$j); + + var scheme$k = new Array(3).concat( + "ffeda0feb24cf03b20", + "ffffb2fecc5cfd8d3ce31a1c", + "ffffb2fecc5cfd8d3cf03b20bd0026", + "ffffb2fed976feb24cfd8d3cf03b20bd0026", + "ffffb2fed976feb24cfd8d3cfc4e2ae31a1cb10026", + "ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cb10026", + "ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cbd0026800026" + ).map(colors); + + var YlOrRd = ramp(scheme$k); + + var scheme$l = new Array(3).concat( + "deebf79ecae13182bd", + "eff3ffbdd7e76baed62171b5", + "eff3ffbdd7e76baed63182bd08519c", + "eff3ffc6dbef9ecae16baed63182bd08519c", + "eff3ffc6dbef9ecae16baed64292c62171b5084594", + "f7fbffdeebf7c6dbef9ecae16baed64292c62171b5084594", + "f7fbffdeebf7c6dbef9ecae16baed64292c62171b508519c08306b" + ).map(colors); + + var Blues = ramp(scheme$l); + + var scheme$m = new Array(3).concat( + "e5f5e0a1d99b31a354", + "edf8e9bae4b374c476238b45", + "edf8e9bae4b374c47631a354006d2c", + "edf8e9c7e9c0a1d99b74c47631a354006d2c", + "edf8e9c7e9c0a1d99b74c47641ab5d238b45005a32", + "f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45005a32", + "f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45006d2c00441b" + ).map(colors); + + var Greens = ramp(scheme$m); + + var scheme$n = new Array(3).concat( + "f0f0f0bdbdbd636363", + "f7f7f7cccccc969696525252", + "f7f7f7cccccc969696636363252525", + "f7f7f7d9d9d9bdbdbd969696636363252525", + "f7f7f7d9d9d9bdbdbd969696737373525252252525", + "fffffff0f0f0d9d9d9bdbdbd969696737373525252252525", + "fffffff0f0f0d9d9d9bdbdbd969696737373525252252525000000" + ).map(colors); + + var Greys = ramp(scheme$n); + + var scheme$o = new Array(3).concat( + "efedf5bcbddc756bb1", + "f2f0f7cbc9e29e9ac86a51a3", + "f2f0f7cbc9e29e9ac8756bb154278f", + "f2f0f7dadaebbcbddc9e9ac8756bb154278f", + "f2f0f7dadaebbcbddc9e9ac8807dba6a51a34a1486", + "fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a34a1486", + "fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a354278f3f007d" + ).map(colors); + + var Purples = ramp(scheme$o); + + var scheme$p = new Array(3).concat( + "fee0d2fc9272de2d26", + "fee5d9fcae91fb6a4acb181d", + "fee5d9fcae91fb6a4ade2d26a50f15", + "fee5d9fcbba1fc9272fb6a4ade2d26a50f15", + "fee5d9fcbba1fc9272fb6a4aef3b2ccb181d99000d", + "fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181d99000d", + "fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181da50f1567000d" + ).map(colors); + + var Reds = ramp(scheme$p); + + var scheme$q = new Array(3).concat( + "fee6cefdae6be6550d", + "feeddefdbe85fd8d3cd94701", + "feeddefdbe85fd8d3ce6550da63603", + "feeddefdd0a2fdae6bfd8d3ce6550da63603", + "feeddefdd0a2fdae6bfd8d3cf16913d948018c2d04", + "fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d948018c2d04", + "fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d94801a636037f2704" + ).map(colors); + + var Oranges = ramp(scheme$q); + + function cividis(t) { + t = Math.max(0, Math.min(1, t)); + return "rgb(" + + Math.max(0, Math.min(255, Math.round(-4.54 - t * (35.34 - t * (2381.73 - t * (6402.7 - t * (7024.72 - t * 2710.57))))))) + ", " + + Math.max(0, Math.min(255, Math.round(32.49 + t * (170.73 + t * (52.82 - t * (131.46 - t * (176.58 - t * 67.37))))))) + ", " + + Math.max(0, Math.min(255, Math.round(81.24 + t * (442.36 - t * (2482.43 - t * (6167.24 - t * (6614.94 - t * 2475.67))))))) + + ")"; + } + + var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0)); + + var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); + + var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8)); + + var c = cubehelix(); + + function rainbow(t) { + if (t < 0 || t > 1) + t -= Math.floor(t); + var ts = Math.abs(t - 0.5); + c.h = 360 * t - 100; + c.s = 1.5 - 1.5 * ts; + c.l = 0.8 - 0.9 * ts; + return c + ""; + } + + var c$1 = rgb(), + pi_1_3 = Math.PI / 3, + pi_2_3 = Math.PI * 2 / 3; + + function sinebow(t) { + var x; + t = (0.5 - t) * Math.PI; + c$1.r = 255 * (x = Math.sin(t)) * x; + c$1.g = 255 * (x = Math.sin(t + pi_1_3)) * x; + c$1.b = 255 * (x = Math.sin(t + pi_2_3)) * x; + return c$1 + ""; + } + + function turbo(t) { + t = Math.max(0, Math.min(1, t)); + return "rgb(" + + Math.max(0, Math.min(255, Math.round(34.61 + t * (1172.33 - t * (10793.56 - t * (33300.12 - t * (38394.49 - t * 14825.05))))))) + ", " + + Math.max(0, Math.min(255, Math.round(23.31 + t * (557.33 + t * (1225.33 - t * (3574.96 - t * (1073.77 + t * 707.56))))))) + ", " + + Math.max(0, Math.min(255, Math.round(27.2 + t * (3211.1 - t * (15327.97 - t * (27814 - t * (22569.18 - t * 6838.66))))))) + + ")"; + } + + function ramp$1(range) { + var n = range.length; + return function (t) { + return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; + }; + } + + var viridis = ramp$1(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")); + + var magma = ramp$1(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")); + + var inferno = ramp$1(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")); + + var plasma = ramp$1(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")); + + function constant$b(x) { + return function constant() { + return x; + }; + } + + var abs$1 = Math.abs; + var atan2$1 = Math.atan2; + var cos$2 = Math.cos; + var max$2 = Math.max; + var min$1 = Math.min; + var sin$2 = Math.sin; + var sqrt$2 = Math.sqrt; + + var epsilon$3 = 1e-12; + var pi$4 = Math.PI; + var halfPi$3 = pi$4 / 2; + var tau$4 = 2 * pi$4; + + function acos$1(x) { + return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x); + } + + function asin$1(x) { + return x >= 1 ? halfPi$3 : x <= -1 ? -halfPi$3 : Math.asin(x); + } + + function arcInnerRadius(d) { + return d.innerRadius; + } + + function arcOuterRadius(d) { + return d.outerRadius; + } + + function arcStartAngle(d) { + return d.startAngle; + } + + function arcEndAngle(d) { + return d.endAngle; + } + + function arcPadAngle(d) { + return d && d.padAngle; // Note: optional! + } + + function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { + var x10 = x1 - x0, y10 = y1 - y0, + x32 = x3 - x2, y32 = y3 - y2, + t = y32 * x10 - x32 * y10; + if (t * t < epsilon$3) + return; + t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t; + return [x0 + t * x10, y0 + t * y10]; + } + +// Compute perpendicular offset line of length rc. +// http://mathworld.wolfram.com/Circle-LineIntersection.html + function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { + var x01 = x0 - x1, + y01 = y0 - y1, + lo = (cw ? rc : -rc) / sqrt$2(x01 * x01 + y01 * y01), + ox = lo * y01, + oy = -lo * x01, + x11 = x0 + ox, + y11 = y0 + oy, + x10 = x1 + ox, + y10 = y1 + oy, + x00 = (x11 + x10) / 2, + y00 = (y11 + y10) / 2, + dx = x10 - x11, + dy = y10 - y11, + d2 = dx * dx + dy * dy, + r = r1 - rc, + D = x11 * y10 - x10 * y11, + d = (dy < 0 ? -1 : 1) * sqrt$2(max$2(0, r * r * d2 - D * D)), + cx0 = (D * dy - dx * d) / d2, + cy0 = (-D * dx - dy * d) / d2, + cx1 = (D * dy + dx * d) / d2, + cy1 = (-D * dx + dy * d) / d2, + dx0 = cx0 - x00, + dy0 = cy0 - y00, + dx1 = cx1 - x00, + dy1 = cy1 - y00; + + // Pick the closer of the two intersection points. + // TODO Is there a faster way to determine which intersection to use? + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) + cx0 = cx1, cy0 = cy1; + + return { + cx: cx0, + cy: cy0, + x01: -ox, + y01: -oy, + x11: cx0 * (r1 / r - 1), + y11: cy0 * (r1 / r - 1) + }; + } + + function arc() { + var innerRadius = arcInnerRadius, + outerRadius = arcOuterRadius, + cornerRadius = constant$b(0), + padRadius = null, + startAngle = arcStartAngle, + endAngle = arcEndAngle, + padAngle = arcPadAngle, + context = null; + + function arc() { + var buffer, + r, + r0 = +innerRadius.apply(this, arguments), + r1 = +outerRadius.apply(this, arguments), + a0 = startAngle.apply(this, arguments) - halfPi$3, + a1 = endAngle.apply(this, arguments) - halfPi$3, + da = abs$1(a1 - a0), + cw = a1 > a0; + + if (!context) + context = buffer = path(); + + // Ensure that the outer radius is always larger than the inner radius. + if (r1 < r0) + r = r1, r1 = r0, r0 = r; + + // Is it a point? + if (!(r1 > epsilon$3)) + context.moveTo(0, 0); + + // Or is it a circle or annulus? + else if (da > tau$4 - epsilon$3) { + context.moveTo(r1 * cos$2(a0), r1 * sin$2(a0)); + context.arc(0, 0, r1, a0, a1, !cw); + if (r0 > epsilon$3) { + context.moveTo(r0 * cos$2(a1), r0 * sin$2(a1)); + context.arc(0, 0, r0, a1, a0, cw); + } + } + + // Or is it a circular or annular sector? + else { + var a01 = a0, + a11 = a1, + a00 = a0, + a10 = a1, + da0 = da, + da1 = da, + ap = padAngle.apply(this, arguments) / 2, + rp = (ap > epsilon$3) && (padRadius ? +padRadius.apply(this, arguments) : sqrt$2(r0 * r0 + r1 * r1)), + rc = min$1(abs$1(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), + rc0 = rc, + rc1 = rc, + t0, + t1; + + // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0. + if (rp > epsilon$3) { + var p0 = asin$1(rp / r0 * sin$2(ap)), + p1 = asin$1(rp / r1 * sin$2(ap)); + if ((da0 -= p0 * 2) > epsilon$3) + p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; + else + da0 = 0, a00 = a10 = (a0 + a1) / 2; + if ((da1 -= p1 * 2) > epsilon$3) + p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; + else + da1 = 0, a01 = a11 = (a0 + a1) / 2; + } + + var x01 = r1 * cos$2(a01), + y01 = r1 * sin$2(a01), + x10 = r0 * cos$2(a10), + y10 = r0 * sin$2(a10); + + // Apply rounded corners? + if (rc > epsilon$3) { + var x11 = r1 * cos$2(a11), + y11 = r1 * sin$2(a11), + x00 = r0 * cos$2(a00), + y00 = r0 * sin$2(a00), + oc; + + // Restrict the corner radius according to the sector angle. + if (da < pi$4 && (oc = intersect(x01, y01, x00, y00, x11, y11, x10, y10))) { + var ax = x01 - oc[0], + ay = y01 - oc[1], + bx = x11 - oc[0], + by = y11 - oc[1], + kc = 1 / sin$2(acos$1((ax * bx + ay * by) / (sqrt$2(ax * ax + ay * ay) * sqrt$2(bx * bx + by * by))) / 2), + lc = sqrt$2(oc[0] * oc[0] + oc[1] * oc[1]); + rc0 = min$1(rc, (r0 - lc) / (kc - 1)); + rc1 = min$1(rc, (r1 - lc) / (kc + 1)); + } + } + + // Is the sector collapsed to a line? + if (!(da1 > epsilon$3)) + context.moveTo(x01, y01); + + // Does the sector’s outer ring have rounded corners? + else if (rc1 > epsilon$3) { + t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw); + t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); + + context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); + + // Have the corners merged? + if (rc1 < rc) + context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw); + + // Otherwise, draw the two corners and the ring. + else { + context.arc(t0.cx, t0.cy, rc1, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw); + context.arc(0, 0, r1, atan2$1(t0.cy + t0.y11, t0.cx + t0.x11), atan2$1(t1.cy + t1.y11, t1.cx + t1.x11), !cw); + context.arc(t1.cx, t1.cy, rc1, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw); + } + } + + // Or is the outer ring just a circular arc? + else + context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); + + // Is there no inner ring, and it’s a circular sector? + // Or perhaps it’s an annular sector collapsed due to padding? + if (!(r0 > epsilon$3) || !(da0 > epsilon$3)) + context.lineTo(x10, y10); + + // Does the sector’s inner ring (or point) have rounded corners? + else if (rc0 > epsilon$3) { + t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw); + t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); + + context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); + + // Have the corners merged? + if (rc0 < rc) + context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t1.y01, t1.x01), !cw); + + // Otherwise, draw the two corners and the ring. + else { + context.arc(t0.cx, t0.cy, rc0, atan2$1(t0.y01, t0.x01), atan2$1(t0.y11, t0.x11), !cw); + context.arc(0, 0, r0, atan2$1(t0.cy + t0.y11, t0.cx + t0.x11), atan2$1(t1.cy + t1.y11, t1.cx + t1.x11), cw); + context.arc(t1.cx, t1.cy, rc0, atan2$1(t1.y11, t1.x11), atan2$1(t1.y01, t1.x01), !cw); + } + } + + // Or is the inner ring just a circular arc? + else + context.arc(0, 0, r0, a10, a00, cw); + } + + context.closePath(); + + if (buffer) + return context = null, buffer + "" || null; + } + + arc.centroid = function () { + var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, + a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$4 / 2; + return [cos$2(a) * r, sin$2(a) * r]; + }; + + arc.innerRadius = function (_) { + return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$b(+_), arc) : innerRadius; + }; + + arc.outerRadius = function (_) { + return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$b(+_), arc) : outerRadius; + }; + + arc.cornerRadius = function (_) { + return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$b(+_), arc) : cornerRadius; + }; + + arc.padRadius = function (_) { + return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$b(+_), arc) : padRadius; + }; + + arc.startAngle = function (_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$b(+_), arc) : startAngle; + }; + + arc.endAngle = function (_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$b(+_), arc) : endAngle; + }; + + arc.padAngle = function (_) { + return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$b(+_), arc) : padAngle; + }; + + arc.context = function (_) { + return arguments.length ? ((context = _ == null ? null : _), arc) : context; + }; + + return arc; + } + + function Linear(context) { + this._context = context; + } + + Linear.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._point = 0; + }, + lineEnd: function () { + if (this._line || (this._line !== 0 && this._point === 1)) + this._context.closePath(); + this._line = 1 - this._line; + }, + point: function (x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: + this._point = 1; + this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); + break; + case 1: + this._point = 2; // proceed + default: + this._context.lineTo(x, y); + break; + } + } + }; + + function curveLinear(context) { + return new Linear(context); + } + + function x$3(p) { + return p[0]; + } + + function y$3(p) { + return p[1]; + } + + function line() { + var x = x$3, + y = y$3, + defined = constant$b(true), + context = null, + curve = curveLinear, + output = null; + + function line(data) { + var i, + n = data.length, + d, + defined0 = false, + buffer; + + if (context == null) + output = curve(buffer = path()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) + output.lineStart(); + else + output.lineEnd(); + } + if (defined0) + output.point(+x(d, i, data), +y(d, i, data)); + } + + if (buffer) + return output = null, buffer + "" || null; + } + + line.x = function (_) { + return arguments.length ? (x = typeof _ === "function" ? _ : constant$b(+_), line) : x; + }; + + line.y = function (_) { + return arguments.length ? (y = typeof _ === "function" ? _ : constant$b(+_), line) : y; + }; + + line.defined = function (_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : constant$b(!!_), line) : defined; + }; + + line.curve = function (_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; + }; + + line.context = function (_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; + }; + + return line; + } + + function area$3() { + var x0 = x$3, + x1 = null, + y0 = constant$b(0), + y1 = y$3, + defined = constant$b(true), + context = null, + curve = curveLinear, + output = null; + + function area(data) { + var i, + j, + k, + n = data.length, + d, + defined0 = false, + buffer, + x0z = new Array(n), + y0z = new Array(n); + + if (context == null) + output = curve(buffer = path()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) { + j = i; + output.areaStart(); + output.lineStart(); + } else { + output.lineEnd(); + output.lineStart(); + for (k = i - 1; k >= j; --k) { + output.point(x0z[k], y0z[k]); + } + output.lineEnd(); + output.areaEnd(); + } + } + if (defined0) { + x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); + output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); + } + } + + if (buffer) + return output = null, buffer + "" || null; + } + + function arealine() { + return line().defined(defined).curve(curve).context(context); + } + + area.x = function (_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$b(+_), x1 = null, area) : x0; + }; + + area.x0 = function (_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$b(+_), area) : x0; + }; + + area.x1 = function (_) { + return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$b(+_), area) : x1; + }; + + area.y = function (_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$b(+_), y1 = null, area) : y0; + }; + + area.y0 = function (_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$b(+_), area) : y0; + }; + + area.y1 = function (_) { + return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$b(+_), area) : y1; + }; + + area.lineX0 = + area.lineY0 = function () { + return arealine().x(x0).y(y0); + }; + + area.lineY1 = function () { + return arealine().x(x0).y(y1); + }; + + area.lineX1 = function () { + return arealine().x(x1).y(y0); + }; + + area.defined = function (_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : constant$b(!!_), area) : defined; + }; + + area.curve = function (_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; + }; + + area.context = function (_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; + }; + + return area; + } + + function descending$1(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; + } + + function identity$8(d) { + return d; + } + + function pie() { + var value = identity$8, + sortValues = descending$1, + sort = null, + startAngle = constant$b(0), + endAngle = constant$b(tau$4), + padAngle = constant$b(0); + + function pie(data) { + var i, + n = data.length, + j, + k, + sum = 0, + index = new Array(n), + arcs = new Array(n), + a0 = +startAngle.apply(this, arguments), + da = Math.min(tau$4, Math.max(-tau$4, endAngle.apply(this, arguments) - a0)), + a1, + p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), + pa = p * (da < 0 ? -1 : 1), + v; + + for (i = 0; i < n; ++i) { + if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { + sum += v; + } + } + + // Optionally sort the arcs by previously-computed values or by data. + if (sortValues != null) + index.sort(function (i, j) { + return sortValues(arcs[i], arcs[j]); + }); + else if (sort != null) + index.sort(function (i, j) { + return sort(data[i], data[j]); + }); + + // Compute the arcs! They are stored in the original data's order. + for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { + j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { + data: data[j], + index: i, + value: v, + startAngle: a0, + endAngle: a1, + padAngle: p + }; + } + + return arcs; + } + + pie.value = function (_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant$b(+_), pie) : value; + }; + + pie.sortValues = function (_) { + return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; + }; + + pie.sort = function (_) { + return arguments.length ? (sort = _, sortValues = null, pie) : sort; + }; + + pie.startAngle = function (_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$b(+_), pie) : startAngle; + }; + + pie.endAngle = function (_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$b(+_), pie) : endAngle; + }; + + pie.padAngle = function (_) { + return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$b(+_), pie) : padAngle; + }; + + return pie; + } + + var curveRadialLinear = curveRadial(curveLinear); + + function Radial(curve) { + this._curve = curve; + } + + Radial.prototype = { + areaStart: function () { + this._curve.areaStart(); + }, + areaEnd: function () { + this._curve.areaEnd(); + }, + lineStart: function () { + this._curve.lineStart(); + }, + lineEnd: function () { + this._curve.lineEnd(); + }, + point: function (a, r) { + this._curve.point(r * Math.sin(a), r * -Math.cos(a)); + } + }; + + function curveRadial(curve) { + + function radial(context) { + return new Radial(curve(context)); + } + + radial._curve = curve; + + return radial; + } + + function lineRadial(l) { + var c = l.curve; + + l.angle = l.x, delete l.x; + l.radius = l.y, delete l.y; + + l.curve = function (_) { + return arguments.length ? c(curveRadial(_)) : c()._curve; + }; + + return l; + } + + function lineRadial$1() { + return lineRadial(line().curve(curveRadialLinear)); + } + + function areaRadial() { + var a = area$3().curve(curveRadialLinear), + c = a.curve, + x0 = a.lineX0, + x1 = a.lineX1, + y0 = a.lineY0, + y1 = a.lineY1; + + a.angle = a.x, delete a.x; + a.startAngle = a.x0, delete a.x0; + a.endAngle = a.x1, delete a.x1; + a.radius = a.y, delete a.y; + a.innerRadius = a.y0, delete a.y0; + a.outerRadius = a.y1, delete a.y1; + a.lineStartAngle = function () { + return lineRadial(x0()); + }, delete a.lineX0; + a.lineEndAngle = function () { + return lineRadial(x1()); + }, delete a.lineX1; + a.lineInnerRadius = function () { + return lineRadial(y0()); + }, delete a.lineY0; + a.lineOuterRadius = function () { + return lineRadial(y1()); + }, delete a.lineY1; + + a.curve = function (_) { + return arguments.length ? c(curveRadial(_)) : c()._curve; + }; + + return a; + } + + function pointRadial(x, y) { + return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)]; + } + + var slice$6 = Array.prototype.slice; + + function linkSource(d) { + return d.source; + } + + function linkTarget(d) { + return d.target; + } + + function link$2(curve) { + var source = linkSource, + target = linkTarget, + x = x$3, + y = y$3, + context = null; + + function link() { + var buffer, argv = slice$6.call(arguments), s = source.apply(this, argv), t = target.apply(this, argv); + if (!context) + context = buffer = path(); + curve(context, +x.apply(this, (argv[0] = s, argv)), +y.apply(this, argv), +x.apply(this, (argv[0] = t, argv)), +y.apply(this, argv)); + if (buffer) + return context = null, buffer + "" || null; + } + + link.source = function (_) { + return arguments.length ? (source = _, link) : source; + }; + + link.target = function (_) { + return arguments.length ? (target = _, link) : target; + }; + + link.x = function (_) { + return arguments.length ? (x = typeof _ === "function" ? _ : constant$b(+_), link) : x; + }; + + link.y = function (_) { + return arguments.length ? (y = typeof _ === "function" ? _ : constant$b(+_), link) : y; + }; + + link.context = function (_) { + return arguments.length ? ((context = _ == null ? null : _), link) : context; + }; + + return link; + } + + function curveHorizontal(context, x0, y0, x1, y1) { + context.moveTo(x0, y0); + context.bezierCurveTo(x0 = (x0 + x1) / 2, y0, x0, y1, x1, y1); + } + + function curveVertical(context, x0, y0, x1, y1) { + context.moveTo(x0, y0); + context.bezierCurveTo(x0, y0 = (y0 + y1) / 2, x1, y0, x1, y1); + } + + function curveRadial$1(context, x0, y0, x1, y1) { + var p0 = pointRadial(x0, y0), + p1 = pointRadial(x0, y0 = (y0 + y1) / 2), + p2 = pointRadial(x1, y0), + p3 = pointRadial(x1, y1); + context.moveTo(p0[0], p0[1]); + context.bezierCurveTo(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]); + } + + function linkHorizontal() { + return link$2(curveHorizontal); + } + + function linkVertical() { + return link$2(curveVertical); + } + + function linkRadial() { + var l = link$2(curveRadial$1); + l.angle = l.x, delete l.x; + l.radius = l.y, delete l.y; + return l; + } + + var circle$2 = { + draw: function (context, size) { + var r = Math.sqrt(size / pi$4); + context.moveTo(r, 0); + context.arc(0, 0, r, 0, tau$4); + } + }; + + var cross$2 = { + draw: function (context, size) { + var r = Math.sqrt(size / 5) / 2; + context.moveTo(-3 * r, -r); + context.lineTo(-r, -r); + context.lineTo(-r, -3 * r); + context.lineTo(r, -3 * r); + context.lineTo(r, -r); + context.lineTo(3 * r, -r); + context.lineTo(3 * r, r); + context.lineTo(r, r); + context.lineTo(r, 3 * r); + context.lineTo(-r, 3 * r); + context.lineTo(-r, r); + context.lineTo(-3 * r, r); + context.closePath(); + } + }; + + var tan30 = Math.sqrt(1 / 3), + tan30_2 = tan30 * 2; + + var diamond = { + draw: function (context, size) { + var y = Math.sqrt(size / tan30_2), + x = y * tan30; + context.moveTo(0, -y); + context.lineTo(x, 0); + context.lineTo(0, y); + context.lineTo(-x, 0); + context.closePath(); + } + }; + + var ka = 0.89081309152928522810, + kr = Math.sin(pi$4 / 10) / Math.sin(7 * pi$4 / 10), + kx = Math.sin(tau$4 / 10) * kr, + ky = -Math.cos(tau$4 / 10) * kr; + + var star = { + draw: function (context, size) { + var r = Math.sqrt(size * ka), + x = kx * r, + y = ky * r; + context.moveTo(0, -r); + context.lineTo(x, y); + for (var i = 1; i < 5; ++i) { + var a = tau$4 * i / 5, + c = Math.cos(a), + s = Math.sin(a); + context.lineTo(s * r, -c * r); + context.lineTo(c * x - s * y, s * x + c * y); + } + context.closePath(); + } + }; + + var square = { + draw: function (context, size) { + var w = Math.sqrt(size), + x = -w / 2; + context.rect(x, x, w, w); + } + }; + + var sqrt3 = Math.sqrt(3); + + var triangle = { + draw: function (context, size) { + var y = -Math.sqrt(size / (sqrt3 * 3)); + context.moveTo(0, y * 2); + context.lineTo(-sqrt3 * y, -y); + context.lineTo(sqrt3 * y, -y); + context.closePath(); + } + }; + + var c$2 = -0.5, + s = Math.sqrt(3) / 2, + k = 1 / Math.sqrt(12), + a = (k / 2 + 1) * 3; + + var wye = { + draw: function (context, size) { + var r = Math.sqrt(size / a), + x0 = r / 2, + y0 = r * k, + x1 = x0, + y1 = r * k + r, + x2 = -x1, + y2 = y1; + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + context.lineTo(c$2 * x0 - s * y0, s * x0 + c$2 * y0); + context.lineTo(c$2 * x1 - s * y1, s * x1 + c$2 * y1); + context.lineTo(c$2 * x2 - s * y2, s * x2 + c$2 * y2); + context.lineTo(c$2 * x0 + s * y0, c$2 * y0 - s * x0); + context.lineTo(c$2 * x1 + s * y1, c$2 * y1 - s * x1); + context.lineTo(c$2 * x2 + s * y2, c$2 * y2 - s * x2); + context.closePath(); + } + }; + + var symbols = [ + circle$2, + cross$2, + diamond, + square, + star, + triangle, + wye + ]; + + function symbol() { + var type = constant$b(circle$2), + size = constant$b(64), + context = null; + + function symbol() { + var buffer; + if (!context) + context = buffer = path(); + type.apply(this, arguments).draw(context, +size.apply(this, arguments)); + if (buffer) + return context = null, buffer + "" || null; + } + + symbol.type = function (_) { + return arguments.length ? (type = typeof _ === "function" ? _ : constant$b(_), symbol) : type; + }; + + symbol.size = function (_) { + return arguments.length ? (size = typeof _ === "function" ? _ : constant$b(+_), symbol) : size; + }; + + symbol.context = function (_) { + return arguments.length ? (context = _ == null ? null : _, symbol) : context; + }; + + return symbol; + } + + function noop$3() {} + + function point$2(that, x, y) { + that._context.bezierCurveTo( + (2 * that._x0 + that._x1) / 3, + (2 * that._y0 + that._y1) / 3, + (that._x0 + 2 * that._x1) / 3, + (that._y0 + 2 * that._y1) / 3, + (that._x0 + 4 * that._x1 + x) / 6, + (that._y0 + 4 * that._y1 + y) / 6 + ); + } + + function Basis(context) { + this._context = context; + } + + Basis.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function () { + switch (this._point) { + case 3: + point$2(this, this._x1, this._y1); // proceed + case 2: + this._context.lineTo(this._x1, this._y1); + break; + } + if (this._line || (this._line !== 0 && this._point === 1)) + this._context.closePath(); + this._line = 1 - this._line; + }, + point: function (x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: + this._point = 1; + this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); + break; + case 1: + this._point = 2; + break; + case 2: + this._point = 3; + this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed + default: + point$2(this, x, y); + break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } + }; + + function basis$2(context) { + return new Basis(context); + } + + function BasisClosed(context) { + this._context = context; + } + + BasisClosed.prototype = { + areaStart: noop$3, + areaEnd: noop$3, + lineStart: function () { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; + this._point = 0; + }, + lineEnd: function () { + switch (this._point) { + case 1: + { + this._context.moveTo(this._x2, this._y2); + this._context.closePath(); + break; + } + case 2: + { + this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); + this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); + this._context.closePath(); + break; + } + case 3: + { + this.point(this._x2, this._y2); + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + break; + } + } + }, + point: function (x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: + this._point = 1; + this._x2 = x, this._y2 = y; + break; + case 1: + this._point = 2; + this._x3 = x, this._y3 = y; + break; + case 2: + this._point = 3; + this._x4 = x, this._y4 = y; + this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); + break; + default: + point$2(this, x, y); + break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } + }; + + function basisClosed$1(context) { + return new BasisClosed(context); + } + + function BasisOpen(context) { + this._context = context; + } + + BasisOpen.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function () { + if (this._line || (this._line !== 0 && this._point === 3)) + this._context.closePath(); + this._line = 1 - this._line; + }, + point: function (x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: + this._point = 1; + break; + case 1: + this._point = 2; + break; + case 2: + this._point = 3; + var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; + this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); + break; + case 3: + this._point = 4; // proceed + default: + point$2(this, x, y); + break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } + }; + + function basisOpen(context) { + return new BasisOpen(context); + } + + function Bundle(context, beta) { + this._basis = new Basis(context); + this._beta = beta; + } + + Bundle.prototype = { + lineStart: function () { + this._x = []; + this._y = []; + this._basis.lineStart(); + }, + lineEnd: function () { + var x = this._x, + y = this._y, + j = x.length - 1; + + if (j > 0) { + var x0 = x[0], + y0 = y[0], + dx = x[j] - x0, + dy = y[j] - y0, + i = -1, + t; + + while (++i <= j) { + t = i / j; + this._basis.point( + this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), + this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) + ); + } + } + + this._x = this._y = null; + this._basis.lineEnd(); + }, + point: function (x, y) { + this._x.push(+x); + this._y.push(+y); + } + }; + + var bundle = (function custom(beta) { + + function bundle(context) { + return beta === 1 ? new Basis(context) : new Bundle(context, beta); + } + + bundle.beta = function (beta) { + return custom(+beta); + }; + + return bundle; + })(0.85); + + function point$3(that, x, y) { + that._context.bezierCurveTo( + that._x1 + that._k * (that._x2 - that._x0), + that._y1 + that._k * (that._y2 - that._y0), + that._x2 + that._k * (that._x1 - x), + that._y2 + that._k * (that._y1 - y), + that._x2, + that._y2 + ); + } + + function Cardinal(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; + } + + Cardinal.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function () { + switch (this._point) { + case 2: + this._context.lineTo(this._x2, this._y2); + break; + case 3: + point$3(this, this._x1, this._y1); + break; + } + if (this._line || (this._line !== 0 && this._point === 1)) + this._context.closePath(); + this._line = 1 - this._line; + }, + point: function (x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: + this._point = 1; + this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); + break; + case 1: + this._point = 2; + this._x1 = x, this._y1 = y; + break; + case 2: + this._point = 3; // proceed + default: + point$3(this, x, y); + break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } + }; + + var cardinal = (function custom(tension) { + + function cardinal(context) { + return new Cardinal(context, tension); + } + + cardinal.tension = function (tension) { + return custom(+tension); + }; + + return cardinal; + })(0); + + function CardinalClosed(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; + } + + CardinalClosed.prototype = { + areaStart: noop$3, + areaEnd: noop$3, + lineStart: function () { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._point = 0; + }, + lineEnd: function () { + switch (this._point) { + case 1: + { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: + { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: + { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function (x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: + this._point = 1; + this._x3 = x, this._y3 = y; + break; + case 1: + this._point = 2; + this._context.moveTo(this._x4 = x, this._y4 = y); + break; + case 2: + this._point = 3; + this._x5 = x, this._y5 = y; + break; + default: + point$3(this, x, y); + break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } + }; + + var cardinalClosed = (function custom(tension) { + + function cardinal(context) { + return new CardinalClosed(context, tension); + } + + cardinal.tension = function (tension) { + return custom(+tension); + }; + + return cardinal; + })(0); + + function CardinalOpen(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; + } + + CardinalOpen.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function () { + if (this._line || (this._line !== 0 && this._point === 3)) + this._context.closePath(); + this._line = 1 - this._line; + }, + point: function (x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: + this._point = 1; + break; + case 1: + this._point = 2; + break; + case 2: + this._point = 3; + this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); + break; + case 3: + this._point = 4; // proceed + default: + point$3(this, x, y); + break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } + }; + + var cardinalOpen = (function custom(tension) { + + function cardinal(context) { + return new CardinalOpen(context, tension); + } + + cardinal.tension = function (tension) { + return custom(+tension); + }; + + return cardinal; + })(0); + + function point$4(that, x, y) { + var x1 = that._x1, + y1 = that._y1, + x2 = that._x2, + y2 = that._y2; + + if (that._l01_a > epsilon$3) { + var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, + n = 3 * that._l01_a * (that._l01_a + that._l12_a); + x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; + y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; + } + + if (that._l23_a > epsilon$3) { + var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, + m = 3 * that._l23_a * (that._l23_a + that._l12_a); + x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; + y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; + } + + that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); + } + + function CatmullRom(context, alpha) { + this._context = context; + this._alpha = alpha; + } + + CatmullRom.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function () { + switch (this._point) { + case 2: + this._context.lineTo(this._x2, this._y2); + break; + case 3: + this.point(this._x2, this._y2); + break; + } + if (this._line || (this._line !== 0 && this._point === 1)) + this._context.closePath(); + this._line = 1 - this._line; + }, + point: function (x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: + this._point = 1; + this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); + break; + case 1: + this._point = 2; + break; + case 2: + this._point = 3; // proceed + default: + point$4(this, x, y); + break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } + }; + + var catmullRom = (function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0); + } + + catmullRom.alpha = function (alpha) { + return custom(+alpha); + }; + + return catmullRom; + })(0.5); + + function CatmullRomClosed(context, alpha) { + this._context = context; + this._alpha = alpha; + } + + CatmullRomClosed.prototype = { + areaStart: noop$3, + areaEnd: noop$3, + lineStart: function () { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function () { + switch (this._point) { + case 1: + { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: + { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: + { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function (x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: + this._point = 1; + this._x3 = x, this._y3 = y; + break; + case 1: + this._point = 2; + this._context.moveTo(this._x4 = x, this._y4 = y); + break; + case 2: + this._point = 3; + this._x5 = x, this._y5 = y; + break; + default: + point$4(this, x, y); + break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } + }; + + var catmullRomClosed = (function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0); + } + + catmullRom.alpha = function (alpha) { + return custom(+alpha); + }; + + return catmullRom; + })(0.5); + + function CatmullRomOpen(context, alpha) { + this._context = context; + this._alpha = alpha; + } + + CatmullRomOpen.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function () { + if (this._line || (this._line !== 0 && this._point === 3)) + this._context.closePath(); + this._line = 1 - this._line; + }, + point: function (x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: + this._point = 1; + break; + case 1: + this._point = 2; + break; + case 2: + this._point = 3; + this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); + break; + case 3: + this._point = 4; // proceed + default: + point$4(this, x, y); + break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } + }; + + var catmullRomOpen = (function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0); + } + + catmullRom.alpha = function (alpha) { + return custom(+alpha); + }; + + return catmullRom; + })(0.5); + + function LinearClosed(context) { + this._context = context; + } + + LinearClosed.prototype = { + areaStart: noop$3, + areaEnd: noop$3, + lineStart: function () { + this._point = 0; + }, + lineEnd: function () { + if (this._point) + this._context.closePath(); + }, + point: function (x, y) { + x = +x, y = +y; + if (this._point) + this._context.lineTo(x, y); + else + this._point = 1, this._context.moveTo(x, y); + } + }; + + function linearClosed(context) { + return new LinearClosed(context); + } + + function sign$1(x) { + return x < 0 ? -1 : 1; + } + +// Calculate the slopes of the tangents (Hermite-type interpolation) based on +// the following paper: Steffen, M. 1990. A Simple Method for Monotonic +// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. +// NOV(II), P. 443, 1990. + function slope3(that, x2, y2) { + var h0 = that._x1 - that._x0, + h1 = x2 - that._x1, + s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), + s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), + p = (s0 * h1 + s1 * h0) / (h0 + h1); + return (sign$1(s0) + sign$1(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; + } + +// Calculate a one-sided slope. + function slope2(that, t) { + var h = that._x1 - that._x0; + return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; + } + +// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations +// "you can express cubic Hermite interpolation in terms of cubic Bézier curves +// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". + function point$5(that, t0, t1) { + var x0 = that._x0, + y0 = that._y0, + x1 = that._x1, + y1 = that._y1, + dx = (x1 - x0) / 3; + that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); + } + + function MonotoneX(context) { + this._context = context; + } + + MonotoneX.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._x0 = this._x1 = + this._y0 = this._y1 = + this._t0 = NaN; + this._point = 0; + }, + lineEnd: function () { + switch (this._point) { + case 2: + this._context.lineTo(this._x1, this._y1); + break; + case 3: + point$5(this, this._t0, slope2(this, this._t0)); + break; + } + if (this._line || (this._line !== 0 && this._point === 1)) + this._context.closePath(); + this._line = 1 - this._line; + }, + point: function (x, y) { + var t1 = NaN; + + x = +x, y = +y; + if (x === this._x1 && y === this._y1) + return; // Ignore coincident points. + switch (this._point) { + case 0: + this._point = 1; + this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); + break; + case 1: + this._point = 2; + break; + case 2: + this._point = 3; + point$5(this, slope2(this, t1 = slope3(this, x, y)), t1); + break; + default: + point$5(this, this._t0, t1 = slope3(this, x, y)); + break; + } + + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + this._t0 = t1; + } + }; + + function MonotoneY(context) { + this._context = new ReflectContext(context); + } + + (MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function (x, y) { + MonotoneX.prototype.point.call(this, y, x); + }; + + function ReflectContext(context) { + this._context = context; + } + + ReflectContext.prototype = { + moveTo: function (x, y) { + this._context.moveTo(y, x); + }, + closePath: function () { + this._context.closePath(); + }, + lineTo: function (x, y) { + this._context.lineTo(y, x); + }, + bezierCurveTo: function (x1, y1, x2, y2, x, y) { + this._context.bezierCurveTo(y1, x1, y2, x2, y, x); + } + }; + + function monotoneX(context) { + return new MonotoneX(context); + } + + function monotoneY(context) { + return new MonotoneY(context); + } + + function Natural(context) { + this._context = context; + } + + Natural.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._x = []; + this._y = []; + }, + lineEnd: function () { + var x = this._x, + y = this._y, + n = x.length; + + if (n) { + this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); + if (n === 2) { + this._context.lineTo(x[1], y[1]); + } else { + var px = controlPoints(x), + py = controlPoints(y); + for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { + this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); + } + } + } + + if (this._line || (this._line !== 0 && n === 1)) + this._context.closePath(); + this._line = 1 - this._line; + this._x = this._y = null; + }, + point: function (x, y) { + this._x.push(+x); + this._y.push(+y); + } + }; + +// See https://www.particleincell.com/2012/bezier-splines/ for derivation. + function controlPoints(x) { + var i, + n = x.length - 1, + m, + a = new Array(n), + b = new Array(n), + r = new Array(n); + a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; + for (i = 1; i < n - 1; ++i) + a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; + a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; + for (i = 1; i < n; ++i) + m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; + a[n - 1] = r[n - 1] / b[n - 1]; + for (i = n - 2; i >= 0; --i) + a[i] = (r[i] - a[i + 1]) / b[i]; + b[n - 1] = (x[n] + a[n - 1]) / 2; + for (i = 0; i < n - 1; ++i) + b[i] = 2 * x[i + 1] - a[i + 1]; + return [a, b]; + } + + function natural(context) { + return new Natural(context); + } + + function Step(context, t) { + this._context = context; + this._t = t; + } + + Step.prototype = { + areaStart: function () { + this._line = 0; + }, + areaEnd: function () { + this._line = NaN; + }, + lineStart: function () { + this._x = this._y = NaN; + this._point = 0; + }, + lineEnd: function () { + if (0 < this._t && this._t < 1 && this._point === 2) + this._context.lineTo(this._x, this._y); + if (this._line || (this._line !== 0 && this._point === 1)) + this._context.closePath(); + if (this._line >= 0) + this._t = 1 - this._t, this._line = 1 - this._line; + }, + point: function (x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: + this._point = 1; + this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); + break; + case 1: + this._point = 2; // proceed + default: + { + if (this._t <= 0) { + this._context.lineTo(this._x, y); + this._context.lineTo(x, y); + } else { + var x1 = this._x * (1 - this._t) + x * this._t; + this._context.lineTo(x1, this._y); + this._context.lineTo(x1, y); + } + break; + } + } + this._x = x, this._y = y; + } + }; + + function step(context) { + return new Step(context, 0.5); + } + + function stepBefore(context) { + return new Step(context, 0); + } + + function stepAfter(context) { + return new Step(context, 1); + } + + function none$1(series, order) { + if (!((n = series.length) > 1)) + return; + for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { + s0 = s1, s1 = series[order[i]]; + for (j = 0; j < m; ++j) { + s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; + } + } + } + + function none$2(series) { + var n = series.length, o = new Array(n); + while (--n >= 0) + o[n] = n; + return o; + } + + function stackValue(d, key) { + return d[key]; + } + + function stack() { + var keys = constant$b([]), + order = none$2, + offset = none$1, + value = stackValue; + + function stack(data) { + var kz = keys.apply(this, arguments), + i, + m = data.length, + n = kz.length, + sz = new Array(n), + oz; + + for (i = 0; i < n; ++i) { + for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) { + si[j] = sij = [0, +value(data[j], ki, j, data)]; + sij.data = data[j]; + } + si.key = ki; + } + + for (i = 0, oz = order(sz); i < n; ++i) { + sz[oz[i]].index = i; + } + + offset(sz, oz); + return sz; + } + + stack.keys = function (_) { + return arguments.length ? (keys = typeof _ === "function" ? _ : constant$b(slice$6.call(_)), stack) : keys; + }; + + stack.value = function (_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant$b(+_), stack) : value; + }; + + stack.order = function (_) { + return arguments.length ? (order = _ == null ? none$2 : typeof _ === "function" ? _ : constant$b(slice$6.call(_)), stack) : order; + }; + + stack.offset = function (_) { + return arguments.length ? (offset = _ == null ? none$1 : _, stack) : offset; + }; + + return stack; + } + + function expand(series, order) { + if (!((n = series.length) > 0)) + return; + for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) { + for (y = i = 0; i < n; ++i) + y += series[i][j][1] || 0; + if (y) + for (i = 0; i < n; ++i) + series[i][j][1] /= y; + } + none$1(series, order); + } + + function diverging$1(series, order) { + if (!((n = series.length) > 0)) + return; + for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) { + for (yp = yn = 0, i = 0; i < n; ++i) { + if ((dy = (d = series[order[i]][j])[1] - d[0]) > 0) { + d[0] = yp, d[1] = yp += dy; + } else if (dy < 0) { + d[1] = yn, d[0] = yn += dy; + } else { + d[0] = 0, d[1] = dy; + } + } + } + } + + function silhouette(series, order) { + if (!((n = series.length) > 0)) + return; + for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) { + for (var i = 0, y = 0; i < n; ++i) + y += series[i][j][1] || 0; + s0[j][1] += s0[j][0] = -y / 2; + } + none$1(series, order); + } + + function wiggle(series, order) { + if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) + return; + for (var y = 0, j = 1, s0, m, n; j < m; ++j) { + for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) { + var si = series[order[i]], + sij0 = si[j][1] || 0, + sij1 = si[j - 1][1] || 0, + s3 = (sij0 - sij1) / 2; + for (var k = 0; k < i; ++k) { + var sk = series[order[k]], + skj0 = sk[j][1] || 0, + skj1 = sk[j - 1][1] || 0; + s3 += skj0 - skj1; + } + s1 += sij0, s2 += s3 * sij0; + } + s0[j - 1][1] += s0[j - 1][0] = y; + if (s1) + y -= s2 / s1; + } + s0[j - 1][1] += s0[j - 1][0] = y; + none$1(series, order); + } + + function appearance(series) { + var peaks = series.map(peak); + return none$2(series).sort(function (a, b) { + return peaks[a] - peaks[b]; + }); + } + + function peak(series) { + var i = -1, j = 0, n = series.length, vi, vj = -Infinity; + while (++i < n) + if ((vi = +series[i][1]) > vj) + vj = vi, j = i; + return j; + } + + function ascending$3(series) { + var sums = series.map(sum$2); + return none$2(series).sort(function (a, b) { + return sums[a] - sums[b]; + }); + } + + function sum$2(series) { + var s = 0, i = -1, n = series.length, v; + while (++i < n) + if (v = +series[i][1]) + s += v; + return s; + } + + function descending$2(series) { + return ascending$3(series).reverse(); + } + + function insideOut(series) { + var n = series.length, + i, + j, + sums = series.map(sum$2), + order = appearance(series), + top = 0, + bottom = 0, + tops = [], + bottoms = []; + + for (i = 0; i < n; ++i) { + j = order[i]; + if (top < bottom) { + top += sums[j]; + tops.push(j); + } else { + bottom += sums[j]; + bottoms.push(j); + } + } + + return bottoms.reverse().concat(tops); + } + + function reverse(series) { + return none$2(series).reverse(); + } + + function constant$c(x) { + return function () { + return x; + }; + } + + function x$4(d) { + return d[0]; + } + + function y$4(d) { + return d[1]; + } + + function RedBlackTree() { + this._ = null; // root node + } + + function RedBlackNode(node) { + node.U = // parent node + node.C = // color - true for red, false for black + node.L = // left node + node.R = // right node + node.P = // previous node + node.N = null; // next node + } + + RedBlackTree.prototype = { + constructor: RedBlackTree, + + insert: function (after, node) { + var parent, grandpa, uncle; + + if (after) { + node.P = after; + node.N = after.N; + if (after.N) + after.N.P = node; + after.N = node; + if (after.R) { + after = after.R; + while (after.L) + after = after.L; + after.L = node; + } else { + after.R = node; + } + parent = after; + } else if (this._) { + after = RedBlackFirst(this._); + node.P = null; + node.N = after; + after.P = after.L = node; + parent = after; + } else { + node.P = node.N = null; + this._ = node; + parent = null; + } + node.L = node.R = null; + node.U = parent; + node.C = true; + + after = node; + while (parent && parent.C) { + grandpa = parent.U; + if (parent === grandpa.L) { + uncle = grandpa.R; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.R) { + RedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateRight(this, grandpa); + } + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.L) { + RedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateLeft(this, grandpa); + } + } + parent = after.U; + } + this._.C = false; + }, + + remove: function (node) { + if (node.N) + node.N.P = node.P; + if (node.P) + node.P.N = node.N; + node.N = node.P = null; + + var parent = node.U, + sibling, + left = node.L, + right = node.R, + next, + red; + + if (!left) + next = right; + else if (!right) + next = left; + else + next = RedBlackFirst(right); + + if (parent) { + if (parent.L === node) + parent.L = next; + else + parent.R = next; + } else { + this._ = next; + } + + if (left && right) { + red = next.C; + next.C = node.C; + next.L = left; + left.U = next; + if (next !== right) { + parent = next.U; + next.U = node.U; + node = next.R; + parent.L = node; + next.R = right; + right.U = next; + } else { + next.U = parent; + parent = next; + node = next.R; + } + } else { + red = node.C; + node = next; + } + + if (node) + node.U = parent; + if (red) + return; + if (node && node.C) { + node.C = false; + return; + } + + do { + if (node === this._) + break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateLeft(this, parent); + sibling = parent.R; + } + if ((sibling.L && sibling.L.C) + || (sibling.R && sibling.R.C)) { + if (!sibling.R || !sibling.R.C) { + sibling.L.C = false; + sibling.C = true; + RedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + RedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateRight(this, parent); + sibling = parent.L; + } + if ((sibling.L && sibling.L.C) + || (sibling.R && sibling.R.C)) { + if (!sibling.L || !sibling.L.C) { + sibling.R.C = false; + sibling.C = true; + RedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + RedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); + + if (node) + node.C = false; + } + }; + + function RedBlackRotateLeft(tree, node) { + var p = node, + q = node.R, + parent = p.U; + + if (parent) { + if (parent.L === p) + parent.L = q; + else + parent.R = q; + } else { + tree._ = q; + } + + q.U = parent; + p.U = q; + p.R = q.L; + if (p.R) + p.R.U = p; + q.L = p; + } + + function RedBlackRotateRight(tree, node) { + var p = node, + q = node.L, + parent = p.U; + + if (parent) { + if (parent.L === p) + parent.L = q; + else + parent.R = q; + } else { + tree._ = q; + } + + q.U = parent; + p.U = q; + p.L = q.R; + if (p.L) + p.L.U = p; + q.R = p; + } + + function RedBlackFirst(node) { + while (node.L) + node = node.L; + return node; + } + + function createEdge(left, right, v0, v1) { + var edge = [null, null], + index = edges.push(edge) - 1; + edge.left = left; + edge.right = right; + if (v0) + setEdgeEnd(edge, left, right, v0); + if (v1) + setEdgeEnd(edge, right, left, v1); + cells[left.index].halfedges.push(index); + cells[right.index].halfedges.push(index); + return edge; + } + + function createBorderEdge(left, v0, v1) { + var edge = [v0, v1]; + edge.left = left; + return edge; + } + + function setEdgeEnd(edge, left, right, vertex) { + if (!edge[0] && !edge[1]) { + edge[0] = vertex; + edge.left = left; + edge.right = right; + } else if (edge.left === right) { + edge[1] = vertex; + } else { + edge[0] = vertex; + } + } + +// Liang–Barsky line clipping. + function clipEdge(edge, x0, y0, x1, y1) { + var a = edge[0], + b = edge[1], + ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + t0 = 0, + t1 = 1, + dx = bx - ax, + dy = by - ay, + r; + + r = x0 - ax; + if (!dx && r > 0) + return; + r /= dx; + if (dx < 0) { + if (r < t0) + return; + if (r < t1) + t1 = r; + } else if (dx > 0) { + if (r > t1) + return; + if (r > t0) + t0 = r; + } + + r = x1 - ax; + if (!dx && r < 0) + return; + r /= dx; + if (dx < 0) { + if (r > t1) + return; + if (r > t0) + t0 = r; + } else if (dx > 0) { + if (r < t0) + return; + if (r < t1) + t1 = r; + } + + r = y0 - ay; + if (!dy && r > 0) + return; + r /= dy; + if (dy < 0) { + if (r < t0) + return; + if (r < t1) + t1 = r; + } else if (dy > 0) { + if (r > t1) + return; + if (r > t0) + t0 = r; + } + + r = y1 - ay; + if (!dy && r < 0) + return; + r /= dy; + if (dy < 0) { + if (r > t1) + return; + if (r > t0) + t0 = r; + } else if (dy > 0) { + if (r < t0) + return; + if (r < t1) + t1 = r; + } + + if (!(t0 > 0) && !(t1 < 1)) + return true; // TODO Better check? + + if (t0 > 0) + edge[0] = [ax + t0 * dx, ay + t0 * dy]; + if (t1 < 1) + edge[1] = [ax + t1 * dx, ay + t1 * dy]; + return true; + } + + function connectEdge(edge, x0, y0, x1, y1) { + var v1 = edge[1]; + if (v1) + return true; + + var v0 = edge[0], + left = edge.left, + right = edge.right, + lx = left[0], + ly = left[1], + rx = right[0], + ry = right[1], + fx = (lx + rx) / 2, + fy = (ly + ry) / 2, + fm, + fb; + + if (ry === ly) { + if (fx < x0 || fx >= x1) + return; + if (lx > rx) { + if (!v0) + v0 = [fx, y0]; + else if (v0[1] >= y1) + return; + v1 = [fx, y1]; + } else { + if (!v0) + v0 = [fx, y1]; + else if (v0[1] < y0) + return; + v1 = [fx, y0]; + } + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!v0) + v0 = [(y0 - fb) / fm, y0]; + else if (v0[1] >= y1) + return; + v1 = [(y1 - fb) / fm, y1]; + } else { + if (!v0) + v0 = [(y1 - fb) / fm, y1]; + else if (v0[1] < y0) + return; + v1 = [(y0 - fb) / fm, y0]; + } + } else { + if (ly < ry) { + if (!v0) + v0 = [x0, fm * x0 + fb]; + else if (v0[0] >= x1) + return; + v1 = [x1, fm * x1 + fb]; + } else { + if (!v0) + v0 = [x1, fm * x1 + fb]; + else if (v0[0] < x0) + return; + v1 = [x0, fm * x0 + fb]; + } + } + } + + edge[0] = v0; + edge[1] = v1; + return true; + } + + function clipEdges(x0, y0, x1, y1) { + var i = edges.length, + edge; + + while (i--) { + if (!connectEdge(edge = edges[i], x0, y0, x1, y1) + || !clipEdge(edge, x0, y0, x1, y1) + || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$4 + || Math.abs(edge[0][1] - edge[1][1]) > epsilon$4)) { + delete edges[i]; + } + } + } + + function createCell(site) { + return cells[site.index] = { + site: site, + halfedges: [] + }; + } + + function cellHalfedgeAngle(cell, edge) { + var site = cell.site, + va = edge.left, + vb = edge.right; + if (site === vb) + vb = va, va = site; + if (vb) + return Math.atan2(vb[1] - va[1], vb[0] - va[0]); + if (site === va) + va = edge[1], vb = edge[0]; + else + va = edge[0], vb = edge[1]; + return Math.atan2(va[0] - vb[0], vb[1] - va[1]); + } + + function cellHalfedgeStart(cell, edge) { + return edge[+(edge.left !== cell.site)]; + } + + function cellHalfedgeEnd(cell, edge) { + return edge[+(edge.left === cell.site)]; + } + + function sortCellHalfedges() { + for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) { + if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) { + var index = new Array(m), + array = new Array(m); + for (j = 0; j < m; ++j) + index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]); + index.sort(function (i, j) { + return array[j] - array[i]; + }); + for (j = 0; j < m; ++j) + array[j] = halfedges[index[j]]; + for (j = 0; j < m; ++j) + halfedges[j] = array[j]; + } + } + } + + function clipCells(x0, y0, x1, y1) { + var nCells = cells.length, + iCell, + cell, + site, + iHalfedge, + halfedges, + nHalfedges, + start, + startX, + startY, + end, + endX, + endY, + cover = true; + + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + site = cell.site; + halfedges = cell.halfedges; + iHalfedge = halfedges.length; + + // Remove any dangling clipped edges. + while (iHalfedge--) { + if (!edges[halfedges[iHalfedge]]) { + halfedges.splice(iHalfedge, 1); + } + } + + // Insert any border edges as necessary. + iHalfedge = 0, nHalfedges = halfedges.length; + while (iHalfedge < nHalfedges) { + end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1]; + start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1]; + if (Math.abs(endX - startX) > epsilon$4 || Math.abs(endY - startY) > epsilon$4) { + halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end, + Math.abs(endX - x0) < epsilon$4 && y1 - endY > epsilon$4 ? [x0, Math.abs(startX - x0) < epsilon$4 ? startY : y1] + : Math.abs(endY - y1) < epsilon$4 && x1 - endX > epsilon$4 ? [Math.abs(startY - y1) < epsilon$4 ? startX : x1, y1] + : Math.abs(endX - x1) < epsilon$4 && endY - y0 > epsilon$4 ? [x1, Math.abs(startX - x1) < epsilon$4 ? startY : y0] + : Math.abs(endY - y0) < epsilon$4 && endX - x0 > epsilon$4 ? [Math.abs(startY - y0) < epsilon$4 ? startX : x0, y0] + : null)) - 1); + ++nHalfedges; + } + } + + if (nHalfedges) + cover = false; + } + } + + // If there weren’t any edges, have the closest site cover the extent. + // It doesn’t matter which corner of the extent we measure! + if (cover) { + var dx, dy, d2, dc = Infinity; + + for (iCell = 0, cover = null; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + site = cell.site; + dx = site[0] - x0; + dy = site[1] - y0; + d2 = dx * dx + dy * dy; + if (d2 < dc) + dc = d2, cover = cell; + } + } + + if (cover) { + var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0]; + cover.halfedges.push( + edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1, + edges.push(createBorderEdge(site, v01, v11)) - 1, + edges.push(createBorderEdge(site, v11, v10)) - 1, + edges.push(createBorderEdge(site, v10, v00)) - 1 + ); + } + } + + // Lastly delete any cells with no edges; these were entirely clipped. + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + if (!cell.halfedges.length) { + delete cells[iCell]; + } + } + } + } + + var circlePool = []; + + var firstCircle; + + function Circle() { + RedBlackNode(this); + this.x = + this.y = + this.arc = + this.site = + this.cy = null; + } + + function attachCircle(arc) { + var lArc = arc.P, + rArc = arc.N; + + if (!lArc || !rArc) + return; + + var lSite = lArc.site, + cSite = arc.site, + rSite = rArc.site; + + if (lSite === rSite) + return; + + var bx = cSite[0], + by = cSite[1], + ax = lSite[0] - bx, + ay = lSite[1] - by, + cx = rSite[0] - bx, + cy = rSite[1] - by; + + var d = 2 * (ax * cy - ay * cx); + if (d >= -epsilon2$2) + return; + + var ha = ax * ax + ay * ay, + hc = cx * cx + cy * cy, + x = (cy * ha - ay * hc) / d, + y = (ax * hc - cx * ha) / d; + + var circle = circlePool.pop() || new Circle; + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom + + arc.circle = circle; + + var before = null, + node = circles._; + + while (node) { + if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) { + if (node.L) + node = node.L; + else { + before = node.P; + break; + } + } else { + if (node.R) + node = node.R; + else { + before = node; + break; + } + } + } + + circles.insert(before, circle); + if (!before) + firstCircle = circle; + } + + function detachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) + firstCircle = circle.N; + circles.remove(circle); + circlePool.push(circle); + RedBlackNode(circle); + arc.circle = null; + } + } + + var beachPool = []; + + function Beach() { + RedBlackNode(this); + this.edge = + this.site = + this.circle = null; + } + + function createBeach(site) { + var beach = beachPool.pop() || new Beach; + beach.site = site; + return beach; + } + + function detachBeach(beach) { + detachCircle(beach); + beaches.remove(beach); + beachPool.push(beach); + RedBlackNode(beach); + } + + function removeBeach(beach) { + var circle = beach.circle, + x = circle.x, + y = circle.cy, + vertex = [x, y], + previous = beach.P, + next = beach.N, + disappearing = [beach]; + + detachBeach(beach); + + var lArc = previous; + while (lArc.circle + && Math.abs(x - lArc.circle.x) < epsilon$4 + && Math.abs(y - lArc.circle.cy) < epsilon$4) { + previous = lArc.P; + disappearing.unshift(lArc); + detachBeach(lArc); + lArc = previous; + } + + disappearing.unshift(lArc); + detachCircle(lArc); + + var rArc = next; + while (rArc.circle + && Math.abs(x - rArc.circle.x) < epsilon$4 + && Math.abs(y - rArc.circle.cy) < epsilon$4) { + next = rArc.N; + disappearing.push(rArc); + detachBeach(rArc); + rArc = next; + } + + disappearing.push(rArc); + detachCircle(rArc); + + var nArcs = disappearing.length, + iArc; + for (iArc = 1; iArc < nArcs; ++iArc) { + rArc = disappearing[iArc]; + lArc = disappearing[iArc - 1]; + setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } + + lArc = disappearing[0]; + rArc = disappearing[nArcs - 1]; + rArc.edge = createEdge(lArc.site, rArc.site, null, vertex); + + attachCircle(lArc); + attachCircle(rArc); + } + + function addBeach(site) { + var x = site[0], + directrix = site[1], + lArc, + rArc, + dxl, + dxr, + node = beaches._; + + while (node) { + dxl = leftBreakPoint(node, directrix) - x; + if (dxl > epsilon$4) + node = node.L; + else { + dxr = x - rightBreakPoint(node, directrix); + if (dxr > epsilon$4) { + if (!node.R) { + lArc = node; + break; + } + node = node.R; + } else { + if (dxl > -epsilon$4) { + lArc = node.P; + rArc = node; + } else if (dxr > -epsilon$4) { + lArc = node; + rArc = node.N; + } else { + lArc = rArc = node; + } + break; + } + } + } + + createCell(site); + var newArc = createBeach(site); + beaches.insert(lArc, newArc); + + if (!lArc && !rArc) + return; + + if (lArc === rArc) { + detachCircle(lArc); + rArc = createBeach(lArc.site); + beaches.insert(newArc, rArc); + newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site); + attachCircle(lArc); + attachCircle(rArc); + return; + } + + if (!rArc) { // && lArc + newArc.edge = createEdge(lArc.site, newArc.site); + return; + } + + // else lArc !== rArc + detachCircle(lArc); + detachCircle(rArc); + + var lSite = lArc.site, + ax = lSite[0], + ay = lSite[1], + bx = site[0] - ax, + by = site[1] - ay, + rSite = rArc.site, + cx = rSite[0] - ax, + cy = rSite[1] - ay, + d = 2 * (bx * cy - by * cx), + hb = bx * bx + by * by, + hc = cx * cx + cy * cy, + vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay]; + + setEdgeEnd(rArc.edge, lSite, rSite, vertex); + newArc.edge = createEdge(lSite, site, null, vertex); + rArc.edge = createEdge(site, rSite, null, vertex); + attachCircle(lArc); + attachCircle(rArc); + } + + function leftBreakPoint(arc, directrix) { + var site = arc.site, + rfocx = site[0], + rfocy = site[1], + pby2 = rfocy - directrix; + + if (!pby2) + return rfocx; + + var lArc = arc.P; + if (!lArc) + return -Infinity; + + site = lArc.site; + var lfocx = site[0], + lfocy = site[1], + plby2 = lfocy - directrix; + + if (!plby2) + return lfocx; + + var hl = lfocx - rfocx, + aby2 = 1 / pby2 - 1 / plby2, + b = hl / plby2; + + if (aby2) + return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; + + return (rfocx + lfocx) / 2; + } + + function rightBreakPoint(arc, directrix) { + var rArc = arc.N; + if (rArc) + return leftBreakPoint(rArc, directrix); + var site = arc.site; + return site[1] === directrix ? site[0] : Infinity; + } + + var epsilon$4 = 1e-6; + var epsilon2$2 = 1e-12; + var beaches; + var cells; + var circles; + var edges; + + function triangleArea(a, b, c) { + return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]); + } + + function lexicographic(a, b) { + return b[1] - a[1] + || b[0] - a[0]; + } + + function Diagram(sites, extent) { + var site = sites.sort(lexicographic).pop(), + x, + y, + circle; + + edges = []; + cells = new Array(sites.length); + beaches = new RedBlackTree; + circles = new RedBlackTree; + + while (true) { + circle = firstCircle; + if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) { + if (site[0] !== x || site[1] !== y) { + addBeach(site); + x = site[0], y = site[1]; + } + site = sites.pop(); + } else if (circle) { + removeBeach(circle.arc); + } else { + break; + } + } + + sortCellHalfedges(); + + if (extent) { + var x0 = +extent[0][0], + y0 = +extent[0][1], + x1 = +extent[1][0], + y1 = +extent[1][1]; + clipEdges(x0, y0, x1, y1); + clipCells(x0, y0, x1, y1); + } + + this.edges = edges; + this.cells = cells; + + beaches = + circles = + edges = + cells = null; + } + + Diagram.prototype = { + constructor: Diagram, + + polygons: function () { + var edges = this.edges; + + return this.cells.map(function (cell) { + var polygon = cell.halfedges.map(function (i) { + return cellHalfedgeStart(cell, edges[i]); + }); + polygon.data = cell.site.data; + return polygon; + }); + }, + + triangles: function () { + var triangles = [], + edges = this.edges; + + this.cells.forEach(function (cell, i) { + if (!(m = (halfedges = cell.halfedges).length)) + return; + var site = cell.site, + halfedges, + j = -1, + m, + s0, + e1 = edges[halfedges[m - 1]], + s1 = e1.left === site ? e1.right : e1.left; + + while (++j < m) { + s0 = s1; + e1 = edges[halfedges[j]]; + s1 = e1.left === site ? e1.right : e1.left; + if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) { + triangles.push([site.data, s0.data, s1.data]); + } + } + }); + + return triangles; + }, + + links: function () { + return this.edges.filter(function (edge) { + return edge.right; + }).map(function (edge) { + return { + source: edge.left.data, + target: edge.right.data + }; + }); + }, + + find: function (x, y, radius) { + var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell; + + // Use the previously-found cell, or start with an arbitrary one. + while (!(cell = that.cells[i1])) + if (++i1 >= n) + return null; + var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy; + + // Traverse the half-edges to find a closer cell, if any. + do { + cell = that.cells[i0 = i1], i1 = null; + cell.halfedges.forEach(function (e) { + var edge = that.edges[e], v = edge.left; + if ((v === cell.site || !v) && !(v = edge.right)) + return; + var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy; + if (v2 < d2) + d2 = v2, i1 = v.index; + }); + } while (i1 !== null); + + that._found = i0; + + return radius == null || d2 <= radius * radius ? cell.site : null; + } + }; + + function voronoi() { + var x = x$4, + y = y$4, + extent = null; + + function voronoi(data) { + return new Diagram(data.map(function (d, i) { + var s = [Math.round(x(d, i, data) / epsilon$4) * epsilon$4, Math.round(y(d, i, data) / epsilon$4) * epsilon$4]; + s.index = i; + s.data = d; + return s; + }), extent); + } + + voronoi.polygons = function (data) { + return voronoi(data).polygons(); + }; + + voronoi.links = function (data) { + return voronoi(data).links(); + }; + + voronoi.triangles = function (data) { + return voronoi(data).triangles(); + }; + + voronoi.x = function (_) { + return arguments.length ? (x = typeof _ === "function" ? _ : constant$c(+_), voronoi) : x; + }; + + voronoi.y = function (_) { + return arguments.length ? (y = typeof _ === "function" ? _ : constant$c(+_), voronoi) : y; + }; + + voronoi.extent = function (_) { + return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]]; + }; + + voronoi.size = function (_) { + return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]]; + }; + + return voronoi; + } + + function constant$d(x) { + return function () { + return x; + }; + } + + function ZoomEvent(target, type, transform) { + this.target = target; + this.type = type; + this.transform = transform; + } + + function Transform(k, x, y) { + this.k = k; + this.x = x; + this.y = y; + } + + Transform.prototype = { + constructor: Transform, + scale: function (k) { + return k === 1 ? this : new Transform(this.k * k, this.x, this.y); + }, + translate: function (x, y) { + return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); + }, + apply: function (point) { + return [point[0] * this.k + this.x, point[1] * this.k + this.y]; + }, + applyX: function (x) { + return x * this.k + this.x; + }, + applyY: function (y) { + return y * this.k + this.y; + }, + invert: function (location) { + return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; + }, + invertX: function (x) { + return (x - this.x) / this.k; + }, + invertY: function (y) { + return (y - this.y) / this.k; + }, + rescaleX: function (x) { + return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); + }, + rescaleY: function (y) { + return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); + }, + toString: function () { + return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + } + }; + + var identity$9 = new Transform(1, 0, 0); + + transform$1.prototype = Transform.prototype; + + function transform$1(node) { + while (!node.__zoom) + if (!(node = node.parentNode)) + return identity$9; + return node.__zoom; + } + + function nopropagation$2() { + exports.event.stopImmediatePropagation(); + } + + function noevent$2() { + exports.event.preventDefault(); + exports.event.stopImmediatePropagation(); + } + +// Ignore right-click, since that should open the context menu. + function defaultFilter$2() { + return !exports.event.ctrlKey && !exports.event.button; + } + + function defaultExtent$1() { + var e = this; + if (e instanceof SVGElement) { + e = e.ownerSVGElement || e; + if (e.hasAttribute("viewBox")) { + e = e.viewBox.baseVal; + return [[e.x, e.y], [e.x + e.width, e.y + e.height]]; + } + return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]]; + } + return [[0, 0], [e.clientWidth, e.clientHeight]]; + } + + function defaultTransform() { + return this.__zoom || identity$9; + } + + function defaultWheelDelta() { + return -exports.event.deltaY * (exports.event.deltaMode === 1 ? 0.05 : exports.event.deltaMode ? 1 : 0.002); + } + + function defaultTouchable$2() { + return navigator.maxTouchPoints || ("ontouchstart" in this); + } + + function defaultConstrain(transform, extent, translateExtent) { + var dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0], + dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0], + dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1], + dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1]; + return transform.translate( + dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), + dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1) + ); + } + + function zoom() { + var filter = defaultFilter$2, + extent = defaultExtent$1, + constrain = defaultConstrain, + wheelDelta = defaultWheelDelta, + touchable = defaultTouchable$2, + scaleExtent = [0, Infinity], + translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]], + duration = 250, + interpolate = interpolateZoom, + listeners = dispatch("start", "zoom", "end"), + touchstarting, + touchending, + touchDelay = 500, + wheelDelay = 150, + clickDistance2 = 0; + + function zoom(selection) { + selection + .property("__zoom", defaultTransform) + .on("wheel.zoom", wheeled) + .on("mousedown.zoom", mousedowned) + .on("dblclick.zoom", dblclicked) + .filter(touchable) + .on("touchstart.zoom", touchstarted) + .on("touchmove.zoom", touchmoved) + .on("touchend.zoom touchcancel.zoom", touchended) + .style("touch-action", "none") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + + zoom.transform = function (collection, transform, point) { + var selection = collection.selection ? collection.selection() : collection; + selection.property("__zoom", defaultTransform); + if (collection !== selection) { + schedule(collection, transform, point); + } else { + selection.interrupt().each(function () { + gesture(this, arguments) + .start() + .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform) + .end(); + }); + } + }; + + zoom.scaleBy = function (selection, k, p) { + zoom.scaleTo(selection, function () { + var k0 = this.__zoom.k, + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return k0 * k1; + }, p); + }; + + zoom.scaleTo = function (selection, k, p) { + zoom.transform(selection, function () { + var e = extent.apply(this, arguments), + t0 = this.__zoom, + p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p, + p1 = t0.invert(p0), + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent); + }, p); + }; + + zoom.translateBy = function (selection, x, y) { + zoom.transform(selection, function () { + return constrain(this.__zoom.translate( + typeof x === "function" ? x.apply(this, arguments) : x, + typeof y === "function" ? y.apply(this, arguments) : y + ), extent.apply(this, arguments), translateExtent); + }); + }; + + zoom.translateTo = function (selection, x, y, p) { + zoom.transform(selection, function () { + var e = extent.apply(this, arguments), + t = this.__zoom, + p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p; + return constrain(identity$9.translate(p0[0], p0[1]).scale(t.k).translate( + typeof x === "function" ? -x.apply(this, arguments) : -x, + typeof y === "function" ? -y.apply(this, arguments) : -y + ), e, translateExtent); + }, p); + }; + + function scale(transform, k) { + k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k)); + return k === transform.k ? transform : new Transform(k, transform.x, transform.y); + } + + function translate(transform, p0, p1) { + var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k; + return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y); + } + + function centroid(extent) { + return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2]; + } + + function schedule(transition, transform, point) { + transition + .on("start.zoom", function () { + gesture(this, arguments).start(); + }) + .on("interrupt.zoom end.zoom", function () { + gesture(this, arguments).end(); + }) + .tween("zoom", function () { + var that = this, + args = arguments, + g = gesture(that, args), + e = extent.apply(that, args), + p = point == null ? centroid(e) : typeof point === "function" ? point.apply(that, args) : point, + w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), + a = that.__zoom, + b = typeof transform === "function" ? transform.apply(that, args) : transform, + i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k)); + return function (t) { + if (t === 1) + t = b; // Avoid rounding error on end. + else { + var l = i(t), k = w / l[2]; + t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); + } + g.zoom(null, t); + }; + }); + } + + function gesture(that, args, clean) { + return (!clean && that.__zooming) || new Gesture(that, args); + } + + function Gesture(that, args) { + this.that = that; + this.args = args; + this.active = 0; + this.extent = extent.apply(that, args); + this.taps = 0; + } + + Gesture.prototype = { + start: function () { + if (++this.active === 1) { + this.that.__zooming = this; + this.emit("start"); + } + return this; + }, + zoom: function (key, transform) { + if (this.mouse && key !== "mouse") + this.mouse[1] = transform.invert(this.mouse[0]); + if (this.touch0 && key !== "touch") + this.touch0[1] = transform.invert(this.touch0[0]); + if (this.touch1 && key !== "touch") + this.touch1[1] = transform.invert(this.touch1[0]); + this.that.__zoom = transform; + this.emit("zoom"); + return this; + }, + end: function () { + if (--this.active === 0) { + delete this.that.__zooming; + this.emit("end"); + } + return this; + }, + emit: function (type) { + customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]); + } + }; + + function wheeled() { + if (!filter.apply(this, arguments)) + return; + var g = gesture(this, arguments), + t = this.__zoom, + k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))), + p = mouse(this); + + // If the mouse is in the same location as before, reuse it. + // If there were recent wheel events, reset the wheel idle timeout. + if (g.wheel) { + if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) { + g.mouse[1] = t.invert(g.mouse[0] = p); + } + clearTimeout(g.wheel); + } + + // If this wheel event won’t trigger a transform change, ignore it. + else if (t.k === k) + return; + + // Otherwise, capture the mouse point and location at the start. + else { + g.mouse = [p, t.invert(p)]; + interrupt(this); + g.start(); + } + + noevent$2(); + g.wheel = setTimeout(wheelidled, wheelDelay); + g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent)); + + function wheelidled() { + g.wheel = null; + g.end(); + } + } + + function mousedowned() { + if (touchending || !filter.apply(this, arguments)) + return; + var g = gesture(this, arguments, true), + v = select(exports.event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true), + p = mouse(this), + x0 = exports.event.clientX, + y0 = exports.event.clientY; + + dragDisable(exports.event.view); + nopropagation$2(); + g.mouse = [p, this.__zoom.invert(p)]; + interrupt(this); + g.start(); + + function mousemoved() { + noevent$2(); + if (!g.moved) { + var dx = exports.event.clientX - x0, dy = exports.event.clientY - y0; + g.moved = dx * dx + dy * dy > clickDistance2; + } + g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent, translateExtent)); + } + + function mouseupped() { + v.on("mousemove.zoom mouseup.zoom", null); + yesdrag(exports.event.view, g.moved); + noevent$2(); + g.end(); + } + } + + function dblclicked() { + if (!filter.apply(this, arguments)) + return; + var t0 = this.__zoom, + p0 = mouse(this), + p1 = t0.invert(p0), + k1 = t0.k * (exports.event.shiftKey ? 0.5 : 2), + t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments), translateExtent); + + noevent$2(); + if (duration > 0) + select(this).transition().duration(duration).call(schedule, t1, p0); + else + select(this).call(zoom.transform, t1); + } + + function touchstarted() { + if (!filter.apply(this, arguments)) + return; + var touches = exports.event.touches, + n = touches.length, + g = gesture(this, arguments, exports.event.changedTouches.length === n), + started, i, t, p; + + nopropagation$2(); + for (i = 0; i < n; ++i) { + t = touches[i], p = touch(this, touches, t.identifier); + p = [p, this.__zoom.invert(p), t.identifier]; + if (!g.touch0) + g.touch0 = p, started = true, g.taps = 1 + !!touchstarting; + else if (!g.touch1 && g.touch0[2] !== p[2]) + g.touch1 = p, g.taps = 0; + } + + if (touchstarting) + touchstarting = clearTimeout(touchstarting); + + if (started) { + if (g.taps < 2) + touchstarting = setTimeout(function () { + touchstarting = null; + }, touchDelay); + interrupt(this); + g.start(); + } + } + + function touchmoved() { + if (!this.__zooming) + return; + var g = gesture(this, arguments), + touches = exports.event.changedTouches, + n = touches.length, i, t, p, l; + + noevent$2(); + if (touchstarting) + touchstarting = clearTimeout(touchstarting); + g.taps = 0; + for (i = 0; i < n; ++i) { + t = touches[i], p = touch(this, touches, t.identifier); + if (g.touch0 && g.touch0[2] === t.identifier) + g.touch0[0] = p; + else if (g.touch1 && g.touch1[2] === t.identifier) + g.touch1[0] = p; + } + t = g.that.__zoom; + if (g.touch1) { + var p0 = g.touch0[0], l0 = g.touch0[1], + p1 = g.touch1[0], l1 = g.touch1[1], + dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, + dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl; + t = scale(t, Math.sqrt(dp / dl)); + p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]; + l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2]; + } else if (g.touch0) + p = g.touch0[0], l = g.touch0[1]; + else + return; + g.zoom("touch", constrain(translate(t, p, l), g.extent, translateExtent)); + } + + function touchended() { + if (!this.__zooming) + return; + var g = gesture(this, arguments), + touches = exports.event.changedTouches, + n = touches.length, i, t; + + nopropagation$2(); + if (touchending) + clearTimeout(touchending); + touchending = setTimeout(function () { + touchending = null; + }, touchDelay); + for (i = 0; i < n; ++i) { + t = touches[i]; + if (g.touch0 && g.touch0[2] === t.identifier) + delete g.touch0; + else if (g.touch1 && g.touch1[2] === t.identifier) + delete g.touch1; + } + if (g.touch1 && !g.touch0) + g.touch0 = g.touch1, delete g.touch1; + if (g.touch0) + g.touch0[1] = this.__zoom.invert(g.touch0[0]); + else { + g.end(); + // If this was a dbltap, reroute to the (optional) dblclick.zoom handler. + if (g.taps === 2) { + var p = select(this).on("dblclick.zoom"); + if (p) + p.apply(this, arguments); + } + } + } + + zoom.wheelDelta = function (_) { + return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant$d(+_), zoom) : wheelDelta; + }; + + zoom.filter = function (_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant$d(!!_), zoom) : filter; + }; + + zoom.touchable = function (_) { + return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$d(!!_), zoom) : touchable; + }; + + zoom.extent = function (_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant$d([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent; + }; + + zoom.scaleExtent = function (_) { + return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]]; + }; + + zoom.translateExtent = function (_) { + return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]]; + }; + + zoom.constrain = function (_) { + return arguments.length ? (constrain = _, zoom) : constrain; + }; + + zoom.duration = function (_) { + return arguments.length ? (duration = +_, zoom) : duration; + }; + + zoom.interpolate = function (_) { + return arguments.length ? (interpolate = _, zoom) : interpolate; + }; + + zoom.on = function () { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? zoom : value; + }; + + zoom.clickDistance = function (_) { + return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2); + }; + + return zoom; + } + + exports.FormatSpecifier = FormatSpecifier; + exports.active = active; + exports.arc = arc; + exports.area = area$3; + exports.areaRadial = areaRadial; + exports.ascending = ascending; + exports.autoType = autoType; + exports.axisBottom = axisBottom; + exports.axisLeft = axisLeft; + exports.axisRight = axisRight; + exports.axisTop = axisTop; + exports.bisect = bisectRight; + exports.bisectLeft = bisectLeft; + exports.bisectRight = bisectRight; + exports.bisector = bisector; + exports.blob = blob; + exports.brush = brush; + exports.brushSelection = brushSelection; + exports.brushX = brushX; + exports.brushY = brushY; + exports.buffer = buffer; + exports.chord = chord; + exports.clientPoint = point; + exports.cluster = cluster; + exports.color = color; + exports.contourDensity = density; + exports.contours = contours; + exports.create = create; + exports.creator = creator; + exports.cross = cross; + exports.csv = csv$1; + exports.csvFormat = csvFormat; + exports.csvFormatBody = csvFormatBody; + exports.csvFormatRow = csvFormatRow; + exports.csvFormatRows = csvFormatRows; + exports.csvFormatValue = csvFormatValue; + exports.csvParse = csvParse; + exports.csvParseRows = csvParseRows; + exports.cubehelix = cubehelix; + exports.curveBasis = basis$2; + exports.curveBasisClosed = basisClosed$1; + exports.curveBasisOpen = basisOpen; + exports.curveBundle = bundle; + exports.curveCardinal = cardinal; + exports.curveCardinalClosed = cardinalClosed; + exports.curveCardinalOpen = cardinalOpen; + exports.curveCatmullRom = catmullRom; + exports.curveCatmullRomClosed = catmullRomClosed; + exports.curveCatmullRomOpen = catmullRomOpen; + exports.curveLinear = curveLinear; + exports.curveLinearClosed = linearClosed; + exports.curveMonotoneX = monotoneX; + exports.curveMonotoneY = monotoneY; + exports.curveNatural = natural; + exports.curveStep = step; + exports.curveStepAfter = stepAfter; + exports.curveStepBefore = stepBefore; + exports.customEvent = customEvent; + exports.descending = descending; + exports.deviation = deviation; + exports.dispatch = dispatch; + exports.drag = drag; + exports.dragDisable = dragDisable; + exports.dragEnable = yesdrag; + exports.dsv = dsv; + exports.dsvFormat = dsvFormat; + exports.easeBack = backInOut; + exports.easeBackIn = backIn; + exports.easeBackInOut = backInOut; + exports.easeBackOut = backOut; + exports.easeBounce = bounceOut; + exports.easeBounceIn = bounceIn; + exports.easeBounceInOut = bounceInOut; + exports.easeBounceOut = bounceOut; + exports.easeCircle = circleInOut; + exports.easeCircleIn = circleIn; + exports.easeCircleInOut = circleInOut; + exports.easeCircleOut = circleOut; + exports.easeCubic = cubicInOut; + exports.easeCubicIn = cubicIn; + exports.easeCubicInOut = cubicInOut; + exports.easeCubicOut = cubicOut; + exports.easeElastic = elasticOut; + exports.easeElasticIn = elasticIn; + exports.easeElasticInOut = elasticInOut; + exports.easeElasticOut = elasticOut; + exports.easeExp = expInOut; + exports.easeExpIn = expIn; + exports.easeExpInOut = expInOut; + exports.easeExpOut = expOut; + exports.easeLinear = linear$1; + exports.easePoly = polyInOut; + exports.easePolyIn = polyIn; + exports.easePolyInOut = polyInOut; + exports.easePolyOut = polyOut; + exports.easeQuad = quadInOut; + exports.easeQuadIn = quadIn; + exports.easeQuadInOut = quadInOut; + exports.easeQuadOut = quadOut; + exports.easeSin = sinInOut; + exports.easeSinIn = sinIn; + exports.easeSinInOut = sinInOut; + exports.easeSinOut = sinOut; + exports.entries = entries; + exports.extent = extent; + exports.forceCenter = center$1; + exports.forceCollide = collide; + exports.forceLink = link; + exports.forceManyBody = manyBody; + exports.forceRadial = radial; + exports.forceSimulation = simulation; + exports.forceX = x$2; + exports.forceY = y$2; + exports.formatDefaultLocale = defaultLocale; + exports.formatLocale = formatLocale; + exports.formatSpecifier = formatSpecifier; + exports.geoAlbers = albers; + exports.geoAlbersUsa = albersUsa; + exports.geoArea = area$1; + exports.geoAzimuthalEqualArea = azimuthalEqualArea; + exports.geoAzimuthalEqualAreaRaw = azimuthalEqualAreaRaw; + exports.geoAzimuthalEquidistant = azimuthalEquidistant; + exports.geoAzimuthalEquidistantRaw = azimuthalEquidistantRaw; + exports.geoBounds = bounds; + exports.geoCentroid = centroid; + exports.geoCircle = circle; + exports.geoClipAntimeridian = clipAntimeridian; + exports.geoClipCircle = clipCircle; + exports.geoClipExtent = extent$1; + exports.geoClipRectangle = clipRectangle; + exports.geoConicConformal = conicConformal; + exports.geoConicConformalRaw = conicConformalRaw; + exports.geoConicEqualArea = conicEqualArea; + exports.geoConicEqualAreaRaw = conicEqualAreaRaw; + exports.geoConicEquidistant = conicEquidistant; + exports.geoConicEquidistantRaw = conicEquidistantRaw; + exports.geoContains = contains$1; + exports.geoDistance = distance; + exports.geoEqualEarth = equalEarth; + exports.geoEqualEarthRaw = equalEarthRaw; + exports.geoEquirectangular = equirectangular; + exports.geoEquirectangularRaw = equirectangularRaw; + exports.geoGnomonic = gnomonic; + exports.geoGnomonicRaw = gnomonicRaw; + exports.geoGraticule = graticule; + exports.geoGraticule10 = graticule10; + exports.geoIdentity = identity$5; + exports.geoInterpolate = interpolate$1; + exports.geoLength = length$1; + exports.geoMercator = mercator; + exports.geoMercatorRaw = mercatorRaw; + exports.geoNaturalEarth1 = naturalEarth1; + exports.geoNaturalEarth1Raw = naturalEarth1Raw; + exports.geoOrthographic = orthographic; + exports.geoOrthographicRaw = orthographicRaw; + exports.geoPath = index$1; + exports.geoProjection = projection; + exports.geoProjectionMutator = projectionMutator; + exports.geoRotation = rotation; + exports.geoStereographic = stereographic; + exports.geoStereographicRaw = stereographicRaw; + exports.geoStream = geoStream; + exports.geoTransform = transform; + exports.geoTransverseMercator = transverseMercator; + exports.geoTransverseMercatorRaw = transverseMercatorRaw; + exports.gray = gray; + exports.hcl = hcl; + exports.hierarchy = hierarchy; + exports.histogram = histogram; + exports.hsl = hsl; + exports.html = html; + exports.image = image; + exports.interpolate = interpolateValue; + exports.interpolateArray = array$1; + exports.interpolateBasis = basis$1; + exports.interpolateBasisClosed = basisClosed; + exports.interpolateBlues = Blues; + exports.interpolateBrBG = BrBG; + exports.interpolateBuGn = BuGn; + exports.interpolateBuPu = BuPu; + exports.interpolateCividis = cividis; + exports.interpolateCool = cool; + exports.interpolateCubehelix = cubehelix$2; + exports.interpolateCubehelixDefault = cubehelix$3; + exports.interpolateCubehelixLong = cubehelixLong; + exports.interpolateDate = date; + exports.interpolateDiscrete = discrete; + exports.interpolateGnBu = GnBu; + exports.interpolateGreens = Greens; + exports.interpolateGreys = Greys; + exports.interpolateHcl = hcl$2; + exports.interpolateHclLong = hclLong; + exports.interpolateHsl = hsl$2; + exports.interpolateHslLong = hslLong; + exports.interpolateHue = hue$1; + exports.interpolateInferno = inferno; + exports.interpolateLab = lab$1; + exports.interpolateMagma = magma; + exports.interpolateNumber = interpolateNumber; + exports.interpolateNumberArray = numberArray; + exports.interpolateObject = object; + exports.interpolateOrRd = OrRd; + exports.interpolateOranges = Oranges; + exports.interpolatePRGn = PRGn; + exports.interpolatePiYG = PiYG; + exports.interpolatePlasma = plasma; + exports.interpolatePuBu = PuBu; + exports.interpolatePuBuGn = PuBuGn; + exports.interpolatePuOr = PuOr; + exports.interpolatePuRd = PuRd; + exports.interpolatePurples = Purples; + exports.interpolateRainbow = rainbow; + exports.interpolateRdBu = RdBu; + exports.interpolateRdGy = RdGy; + exports.interpolateRdPu = RdPu; + exports.interpolateRdYlBu = RdYlBu; + exports.interpolateRdYlGn = RdYlGn; + exports.interpolateReds = Reds; + exports.interpolateRgb = interpolateRgb; + exports.interpolateRgbBasis = rgbBasis; + exports.interpolateRgbBasisClosed = rgbBasisClosed; + exports.interpolateRound = interpolateRound; + exports.interpolateSinebow = sinebow; + exports.interpolateSpectral = Spectral; + exports.interpolateString = interpolateString; + exports.interpolateTransformCss = interpolateTransformCss; + exports.interpolateTransformSvg = interpolateTransformSvg; + exports.interpolateTurbo = turbo; + exports.interpolateViridis = viridis; + exports.interpolateWarm = warm; + exports.interpolateYlGn = YlGn; + exports.interpolateYlGnBu = YlGnBu; + exports.interpolateYlOrBr = YlOrBr; + exports.interpolateYlOrRd = YlOrRd; + exports.interpolateZoom = interpolateZoom; + exports.interrupt = interrupt; + exports.interval = interval$1; + exports.isoFormat = formatIso; + exports.isoParse = parseIso; + exports.json = json; + exports.keys = keys; + exports.lab = lab; + exports.lch = lch; + exports.line = line; + exports.lineRadial = lineRadial$1; + exports.linkHorizontal = linkHorizontal; + exports.linkRadial = linkRadial; + exports.linkVertical = linkVertical; + exports.local = local; + exports.map = map$1; + exports.matcher = matcher; + exports.max = max; + exports.mean = mean; + exports.median = median; + exports.merge = merge; + exports.min = min; + exports.mouse = mouse; + exports.namespace = namespace; + exports.namespaces = namespaces; + exports.nest = nest; + exports.now = now; + exports.pack = index$2; + exports.packEnclose = enclose; + exports.packSiblings = siblings; + exports.pairs = pairs; + exports.partition = partition; + exports.path = path; + exports.permute = permute; + exports.pie = pie; + exports.piecewise = piecewise; + exports.pointRadial = pointRadial; + exports.polygonArea = area$2; + exports.polygonCentroid = centroid$1; + exports.polygonContains = contains$2; + exports.polygonHull = hull; + exports.polygonLength = length$2; + exports.precisionFixed = precisionFixed; + exports.precisionPrefix = precisionPrefix; + exports.precisionRound = precisionRound; + exports.quadtree = quadtree; + exports.quantile = threshold; + exports.quantize = quantize; + exports.radialArea = areaRadial; + exports.radialLine = lineRadial$1; + exports.randomBates = bates; + exports.randomExponential = exponential$1; + exports.randomIrwinHall = irwinHall; + exports.randomLogNormal = logNormal; + exports.randomNormal = normal; + exports.randomUniform = uniform; + exports.range = sequence; + exports.rgb = rgb; + exports.ribbon = ribbon; + exports.scaleBand = band; + exports.scaleDiverging = diverging; + exports.scaleDivergingLog = divergingLog; + exports.scaleDivergingPow = divergingPow; + exports.scaleDivergingSqrt = divergingSqrt; + exports.scaleDivergingSymlog = divergingSymlog; + exports.scaleIdentity = identity$7; + exports.scaleImplicit = implicit; + exports.scaleLinear = linear$2; + exports.scaleLog = log$1; + exports.scaleOrdinal = ordinal; + exports.scalePoint = point$1; + exports.scalePow = pow$1; + exports.scaleQuantile = quantile; + exports.scaleQuantize = quantize$1; + exports.scaleSequential = sequential; + exports.scaleSequentialLog = sequentialLog; + exports.scaleSequentialPow = sequentialPow; + exports.scaleSequentialQuantile = sequentialQuantile; + exports.scaleSequentialSqrt = sequentialSqrt; + exports.scaleSequentialSymlog = sequentialSymlog; + exports.scaleSqrt = sqrt$1; + exports.scaleSymlog = symlog; + exports.scaleThreshold = threshold$1; + exports.scaleTime = time; + exports.scaleUtc = utcTime; + exports.scan = scan; + exports.schemeAccent = Accent; + exports.schemeBlues = scheme$l; + exports.schemeBrBG = scheme; + exports.schemeBuGn = scheme$9; + exports.schemeBuPu = scheme$a; + exports.schemeCategory10 = category10; + exports.schemeDark2 = Dark2; + exports.schemeGnBu = scheme$b; + exports.schemeGreens = scheme$m; + exports.schemeGreys = scheme$n; + exports.schemeOrRd = scheme$c; + exports.schemeOranges = scheme$q; + exports.schemePRGn = scheme$1; + exports.schemePaired = Paired; + exports.schemePastel1 = Pastel1; + exports.schemePastel2 = Pastel2; + exports.schemePiYG = scheme$2; + exports.schemePuBu = scheme$e; + exports.schemePuBuGn = scheme$d; + exports.schemePuOr = scheme$3; + exports.schemePuRd = scheme$f; + exports.schemePurples = scheme$o; + exports.schemeRdBu = scheme$4; + exports.schemeRdGy = scheme$5; + exports.schemeRdPu = scheme$g; + exports.schemeRdYlBu = scheme$6; + exports.schemeRdYlGn = scheme$7; + exports.schemeReds = scheme$p; + exports.schemeSet1 = Set1; + exports.schemeSet2 = Set2; + exports.schemeSet3 = Set3; + exports.schemeSpectral = scheme$8; + exports.schemeTableau10 = Tableau10; + exports.schemeYlGn = scheme$i; + exports.schemeYlGnBu = scheme$h; + exports.schemeYlOrBr = scheme$j; + exports.schemeYlOrRd = scheme$k; + exports.select = select; + exports.selectAll = selectAll; + exports.selection = selection; + exports.selector = selector; + exports.selectorAll = selectorAll; + exports.set = set$2; + exports.shuffle = shuffle; + exports.stack = stack; + exports.stackOffsetDiverging = diverging$1; + exports.stackOffsetExpand = expand; + exports.stackOffsetNone = none$1; + exports.stackOffsetSilhouette = silhouette; + exports.stackOffsetWiggle = wiggle; + exports.stackOrderAppearance = appearance; + exports.stackOrderAscending = ascending$3; + exports.stackOrderDescending = descending$2; + exports.stackOrderInsideOut = insideOut; + exports.stackOrderNone = none$2; + exports.stackOrderReverse = reverse; + exports.stratify = stratify; + exports.style = styleValue; + exports.sum = sum; + exports.svg = svg; + exports.symbol = symbol; + exports.symbolCircle = circle$2; + exports.symbolCross = cross$2; + exports.symbolDiamond = diamond; + exports.symbolSquare = square; + exports.symbolStar = star; + exports.symbolTriangle = triangle; + exports.symbolWye = wye; + exports.symbols = symbols; + exports.text = text; + exports.thresholdFreedmanDiaconis = freedmanDiaconis; + exports.thresholdScott = scott; + exports.thresholdSturges = thresholdSturges; + exports.tickFormat = tickFormat; + exports.tickIncrement = tickIncrement; + exports.tickStep = tickStep; + exports.ticks = ticks; + exports.timeDay = day; + exports.timeDays = days; + exports.timeFormatDefaultLocale = defaultLocale$1; + exports.timeFormatLocale = formatLocale$1; + exports.timeFriday = friday; + exports.timeFridays = fridays; + exports.timeHour = hour; + exports.timeHours = hours; + exports.timeInterval = newInterval; + exports.timeMillisecond = millisecond; + exports.timeMilliseconds = milliseconds; + exports.timeMinute = minute; + exports.timeMinutes = minutes; + exports.timeMonday = monday; + exports.timeMondays = mondays; + exports.timeMonth = month; + exports.timeMonths = months; + exports.timeSaturday = saturday; + exports.timeSaturdays = saturdays; + exports.timeSecond = second; + exports.timeSeconds = seconds; + exports.timeSunday = sunday; + exports.timeSundays = sundays; + exports.timeThursday = thursday; + exports.timeThursdays = thursdays; + exports.timeTuesday = tuesday; + exports.timeTuesdays = tuesdays; + exports.timeWednesday = wednesday; + exports.timeWednesdays = wednesdays; + exports.timeWeek = sunday; + exports.timeWeeks = sundays; + exports.timeYear = year; + exports.timeYears = years; + exports.timeout = timeout$1; + exports.timer = timer; + exports.timerFlush = timerFlush; + exports.touch = touch; + exports.touches = touches; + exports.transition = transition; + exports.transpose = transpose; + exports.tree = tree; + exports.treemap = index$3; + exports.treemapBinary = binary; + exports.treemapDice = treemapDice; + exports.treemapResquarify = resquarify; + exports.treemapSlice = treemapSlice; + exports.treemapSliceDice = sliceDice; + exports.treemapSquarify = squarify; + exports.tsv = tsv$1; + exports.tsvFormat = tsvFormat; + exports.tsvFormatBody = tsvFormatBody; + exports.tsvFormatRow = tsvFormatRow; + exports.tsvFormatRows = tsvFormatRows; + exports.tsvFormatValue = tsvFormatValue; + exports.tsvParse = tsvParse; + exports.tsvParseRows = tsvParseRows; + exports.utcDay = utcDay; + exports.utcDays = utcDays; + exports.utcFriday = utcFriday; + exports.utcFridays = utcFridays; + exports.utcHour = utcHour; + exports.utcHours = utcHours; + exports.utcMillisecond = millisecond; + exports.utcMilliseconds = milliseconds; + exports.utcMinute = utcMinute; + exports.utcMinutes = utcMinutes; + exports.utcMonday = utcMonday; + exports.utcMondays = utcMondays; + exports.utcMonth = utcMonth; + exports.utcMonths = utcMonths; + exports.utcSaturday = utcSaturday; + exports.utcSaturdays = utcSaturdays; + exports.utcSecond = second; + exports.utcSeconds = seconds; + exports.utcSunday = utcSunday; + exports.utcSundays = utcSundays; + exports.utcThursday = utcThursday; + exports.utcThursdays = utcThursdays; + exports.utcTuesday = utcTuesday; + exports.utcTuesdays = utcTuesdays; + exports.utcWednesday = utcWednesday; + exports.utcWednesdays = utcWednesdays; + exports.utcWeek = utcSunday; + exports.utcWeeks = utcSundays; + exports.utcYear = utcYear; + exports.utcYears = utcYears; + exports.values = values; + exports.variance = variance; + exports.version = version; + exports.voronoi = voronoi; + exports.window = defaultView; + exports.xml = xml; + exports.zip = zip; + exports.zoom = zoom; + exports.zoomIdentity = identity$9; + exports.zoomTransform = transform$1; + + Object.defineProperty(exports, '__esModule', {value: true}); + + })); diff --git a/src/main/webapp/assets/js/vendors/d3.min.js b/src/main/webapp/assets/js/vendors/d3.min.js new file mode 100644 index 0000000..5f7129d --- /dev/null +++ b/src/main/webapp/assets/js/vendors/d3.min.js @@ -0,0 +1,478 @@ +(function(b,Sa){"object"===typeof exports&&"undefined"!==typeof module?Sa(exports):"function"===typeof define&&define.amd?define(["exports"],Sa):(b=b||self,Sa(b.d3=b.d3||{}))})(this,function(b){function Sa(a,c){return ac?1:a>=c?0:NaN}function Af(a){1===a.length&&(a=fo(a));return{left:function(c,d,e,g){null==e&&(e=0);null==g&&(g=c.length);for(;e>>1;0>a(c[h],d)?e=h+1:g=h}return e},right:function(c,d,e,g){null==e&&(e=0);null==g&&(g=c.length);for(;e>>1;0=g)for(h=k=g;++eg&&(h=g),k=g)for(h=k=g;++eg&&(h=g),k(g=arguments.length)?(c=a,a=0,1):3>g?1:+d;for(var e=-1,g=Math.max(0,Math.ceil((c-a)/d))|0,h=Array(g);++e=Df?10:c>=Ef?5:c>=Ff?2:1)*Math.pow(10,a):-Math.pow(10,-a)/(c>=Df?10:c>=Ef?5:c>=Ff?2:1)}function Kb(a,c,d){var e=Math.abs(c-a)/Math.max(0, +d);d=Math.pow(10,Math.floor(Math.log(e)/Math.LN10));e/=d;e>=Df?d*=10:e>=Ef?d*=5:e>=Ff&&(d*=2);return c=(c=+c)||2>e)return+d(a[0],0,a);if(1<=c)return+d(a[e-1],e-1,a);var e;c*=e-1;e=Math.floor(c);var g=+d(a[e],e,a);a=+d(a[e+1],e+1,a);return g+(a-g)*(c-e)}}function oi(a,c){var d=a.length,e=-1,g,h;if(null==c)for(;++e=g)for(h=g;++e +h&&(h=g)}else for(;++e=g)for(h=g;++eh&&(h=g);return h}function Hf(a){var c=a.length;var d=-1;for(var e=0,g,h;++d=g)for(h=g;++eg&&(h=g)}else for(;++e=g)for(h=g;++eg&&(h=g);return h} +function qi(a){if(!(h=a.length))return[];for(var c=-1,d=pi(a,ho),e=Array(d);++cc?1:a>=c?0:NaN}function yo(a){return function(){this.removeAttribute(a)}}function zo(a){return function(){this.removeAttributeNS(a.space,a.local)}}function Ao(a,c){return function(){this.setAttribute(a,c)}}function Bo(a,c){return function(){this.setAttributeNS(a.space,a.local,c)}}function Co(a,c){return function(){var d=c.apply(this,arguments);null==d?this.removeAttribute(a): +this.setAttribute(a,d)}}function Do(a,c){return function(){var d=c.apply(this,arguments);null==d?this.removeAttributeNS(a.space,a.local):this.setAttributeNS(a.space,a.local,d)}}function Mf(a){return a.ownerDocument&&a.ownerDocument.defaultView||a.document&&a||a.defaultView}function Eo(a){return function(){this.style.removeProperty(a)}}function Fo(a,c,d){return function(){this.style.setProperty(a,c,d)}}function Go(a,c,d){return function(){var e=c.apply(this,arguments);null==e?this.style.removeProperty(a): +this.style.setProperty(a,e,d)}}function Mb(a,c){return a.style.getPropertyValue(c)||Mf(a).getComputedStyle(a,null).getPropertyValue(c)}function Ho(a){return function(){delete this[a]}}function Io(a,c){return function(){this[a]=c}}function Jo(a,c){return function(){var d=c.apply(this,arguments);null==d?delete this[a]:this[a]=d}}function Nf(a){return a.classList||new ti(a)}function ti(a){this._node=a;this._names=(a.getAttribute("class")||"").trim().split(/^|\s+/)}function ui(a,c){a=Nf(a);for(var d= +-1,e=c.length;++darguments.length&&(d=c,c=Qf().changedTouches);for(var e=0,g=c?c.length:0,h;e>8&15|c>>4&240,c>>4&15|c&240,(c&15)<<4|c&15,1):8===d?Yd(c>>24&255,c>>16&255,c>>8&255,(c&255)/255):4===d?Yd(c>>12&15|c>>8&240,c>>8&15|c>>4&240,c>>4&15|c&240,((c&15)<<4|c&15)/255):null):(c=kp.exec(a))?new va(c[1],c[2],c[3],1):(c=lp.exec(a))?new va(255*c[1]/ +100,255*c[2]/100,255*c[3]/100,1):(c=mp.exec(a))?Yd(c[1],c[2],c[3],c[4]):(c=np.exec(a))?Yd(255*c[1]/100,255*c[2]/100,255*c[3]/100,c[4]):(c=op.exec(a))?Di(c[1],c[2]/100,c[3]/100,1):(c=pp.exec(a))?Di(c[1],c[2]/100,c[3]/100,c[4]):Ei.hasOwnProperty(a)?Ci(Ei[a]):"transparent"===a?new va(NaN,NaN,NaN,0):null}function Ci(a){return new va(a>>16&255,a>>8&255,a&255,1)}function Yd(a,c,d,e){0>=e&&(a=c=d=NaN);return new va(a,c,d,e)}function Sf(a){a instanceof yb||(a=zb(a));if(!a)return new va;a=a.rgb();return new va(a.r, +a.g,a.b,a.opacity)}function gc(a,c,d,e){return 1===arguments.length?Sf(a):new va(a,c,d,null==e?1:e)}function va(a,c,d,e){this.r=+a;this.g=+c;this.b=+d;this.opacity=+e}function Fi(){return"#"+Tf(this.r)+Tf(this.g)+Tf(this.b)}function Gi(){var a=this.opacity;a=isNaN(a)?1:Math.max(0,Math.min(1,a));return(1===a?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===a?")":", "+a+")")} +function Tf(a){a=Math.max(0,Math.min(255,Math.round(a)||0));return(16>a?"0":"")+a.toString(16)}function Di(a,c,d,e){0>=e?a=c=d=NaN:0>=d||1<=d?a=c=NaN:0>=c&&(a=NaN);return new eb(a,c,d,e)}function Hi(a){if(a instanceof eb)return new eb(a.h,a.s,a.l,a.opacity);a instanceof yb||(a=zb(a));if(!a)return new eb;if(a instanceof eb)return a;a=a.rgb();var c=a.r/255,d=a.g/255,e=a.b/255,g=Math.min(c,d,e),h=Math.max(c,d,e),k=NaN,p=h-g,t=(h+g)/2;p?(k=c===h?(d-e)/p+6*(dt?h+g:2- +h-g,k*=60):p=0t?0:k;return new eb(k,p,t,a.opacity)}function Zd(a,c,d,e){return 1===arguments.length?Hi(a):new eb(a,c,d,null==e?1:e)}function eb(a,c,d,e){this.h=+a;this.s=+c;this.l=+d;this.opacity=+e}function Uf(a,c,d){return 255*(60>a?c+(d-c)*a/60:180>a?d:240>a?c+(d-c)*(240-a)/60:c)}function Ii(a){if(a instanceof Ya)return new Ya(a.l,a.a,a.b,a.opacity);if(a instanceof fb)return Ji(a);a instanceof va||(a=Sf(a));var c=Vf(a.r),d=Vf(a.g),e=Vf(a.b),g=Wf(.2225045*c+.7168786*d+.0606169*e);if(c===d&& +d===e)var h=c=g;else h=Wf((.4360747*c+.3850649*d+.1430804*e)/.96422),c=Wf((.0139322*c+.0971045*d+.7141733*e)/.82521);return new Ya(116*g-16,500*(h-g),200*(g-c),a.opacity)}function $d(a,c,d,e){return 1===arguments.length?Ii(a):new Ya(a,c,d,null==e?1:e)}function Ya(a,c,d,e){this.l=+a;this.a=+c;this.b=+d;this.opacity=+e}function Wf(a){return a>qp?Math.pow(a,1/3):a/Ki+Li}function Xf(a){return a>hc?a*a*a:Ki*(a-Li)}function Yf(a){return 255*(.0031308>=a?12.92*a:1.055*Math.pow(a,1/2.4)-.055)}function Vf(a){return.04045>= +(a/=255)?a/12.92:Math.pow((a+.055)/1.055,2.4)}function Mi(a){if(a instanceof fb)return new fb(a.h,a.c,a.l,a.opacity);a instanceof Ya||(a=Ii(a));if(0===a.a&&0===a.b)return new fb(NaN,0a.l?0:NaN,a.l,a.opacity);var c=Math.atan2(a.b,a.a)*Ni;return new fb(0>c?c+360:c,Math.sqrt(a.a*a.a+a.b*a.b),a.l,a.opacity)}function ae(a,c,d,e){return 1===arguments.length?Mi(a):new fb(a,c,d,null==e?1:e)}function fb(a,c,d,e){this.h=+a;this.c=+c;this.l=+d;this.opacity=+e}function Ji(a){if(isNaN(a.h))return new Ya(a.l, +0,0,a.opacity);var c=a.h*Oi;return new Ya(a.l,Math.cos(c)*a.c,Math.sin(c)*a.c,a.opacity)}function Za(a,c,d,e){if(1===arguments.length){var g=a;if(g instanceof Pb)g=new Pb(g.h,g.s,g.l,g.opacity);else{g instanceof va||(g=Sf(g));var h=g.g/255,k=g.b/255,p=(Pi*k+g.r/255*-1.7884503806-3.5172982438*h)/(Pi+-1.7884503806-3.5172982438);k-=p;var t=(1.97294*(h-p)- -.29227*k)/-.90649;k=(h=Math.sqrt(t*t+k*k)/(1.97294*p*(1-p)))?Math.atan2(t,k)*Ni-120:NaN;g=new Pb(0>k?k+360:k,h,p,g.opacity)}}else g=new Pb(a,c,d, +null==e?1:e);return g}function Pb(a,c,d,e){this.h=+a;this.s=+c;this.l=+d;this.opacity=+e}function Qi(a,c,d,e,g){var h=a*a,k=h*a;return((1-3*a+3*h-k)*c+(4-6*h+3*k)*d+(1+3*a+3*h-3*k)*e+k*g)/6}function Ri(a){var c=a.length-1;return function(d){var e=0>=d?d=0:1<=d?(d=1,c-1):Math.floor(d*c),g=a[e],h=a[e+1];return Qi((d-e/c)*c,0(d%=1)?++d:d)*c);return Qi((d-e/c)*c,a[(e+c-1)%c],a[e%c],a[(e+1)%c], +a[(e+2)%c])}}function be(a){return function(){return a}}function Ti(a,c){return function(d){return a+d*c}}function rp(a,c,d){return a=Math.pow(a,d),c=Math.pow(c,d)-a,d=1/d,function(e){return Math.pow(a+e*c,d)}}function ce(a,c){var d=c-a;return d?Ti(a,180d?d-360*Math.round(d/360):d):be(isNaN(a)?c:a)}function sp(a){return 1===(a=+a)?sa:function(c,d){return d-c?rp(c,d,a):be(isNaN(c)?d:c)}}function sa(a,c){var d=c-a;return d?Ti(a,d):be(isNaN(a)?c:a)}function Ui(a){return function(c){var d=c.length, +e=Array(d),g=Array(d),h=Array(d),k;for(k=0;kd&&(h=c.slice(d,h),p[k]?p[k]+=h:p[++k]=h),(e=e[0])===(g=g[0])?p[k]?p[k]+=g:p[++k]=g:(p[++k]=null,t.push({i:k,x:Ta(e,g)})),d=bg.lastIndex;dp.length?t[0]?up(t[0].x):tp(c):(c=t.length,function(a){for(var d=0,e;dp){var t=Math.log(a/g)/Rc;a=function(a){return[d+a*h,e+a*k,g*Math.exp(Rc*a*t)]}}else{var b=Math.sqrt(p);c=(a*a-g*g+4*p)/(4*g*b);a=(a*a-g*g-4*p)/(4*a*b);var m=Math.log(Math.sqrt(c*c+1)-c);t=(Math.log(Math.sqrt(a*a+1)-a)-m)/Rc;a=function(a){a*=t;var c=cj(m),p=Rc*a+m;var q=((p=Math.exp(2*p))-1)/(p+1);var z=m;p=((z=Math.exp(z))-1/z)/2;q=g/(2* +b)*(c*q-p);return[d+q*h,e+q*k,g*c/cj(Rc*a+m)]}}a.duration=1E3*t;return a}function ej(a){return function(c,d){var e=a((c=Zd(c)).h,(d=Zd(d)).h),g=sa(c.s,d.s),h=sa(c.l,d.l),k=sa(c.opacity,d.opacity);return function(a){c.h=e(a);c.s=g(a);c.l=h(a);c.opacity=k(a);return c+""}}}function fj(a){return function(c,d){var e=a((c=ae(c)).h,(d=ae(d)).h),g=sa(c.c,d.c),h=sa(c.l,d.l),k=sa(c.opacity,d.opacity);return function(a){c.h=e(a);c.c=g(a);c.l=h(a);c.opacity=k(a);return c+""}}}function gj(a){return function e(d){function g(e, +g){var h=a((e=Za(e)).h,(g=Za(g)).h),k=sa(e.s,g.s),b=sa(e.l,g.l),m=sa(e.opacity,g.opacity);return function(a){e.h=h(a);e.s=k(a);e.l=b(Math.pow(a,d));e.opacity=m(a);return e+""}}d=+d;g.gamma=e;return g}(1)}function ic(){return Qb||(hj(vp),Qb=Sc.now()+de)}function vp(){Qb=0}function Tc(){this._call=this._time=this._next=null}function ee(a,c,d){var e=new Tc;e.restart(a,c,d);return e}function ij(){ic();++jc;for(var a=fe,c;a;)0<=(c=Qb-a._time)&&a._call.call(null,c),a=a._next;--jc}function jj(){Qb=(ge=Sc.now())+ +de;jc=Uc=0;try{ij()}finally{jc=0;for(var a,c=fe,d,e=Infinity;c;)c._call?(e>c._time&&(e=c._time),a=c,c=c._next):(d=c._next,c._next=null,c=a?a._next=d:fe=d);Vc=a;cg(e);Qb=0}}function wp(){var a=Sc.now(),c=a-ge;1E3a&&(Uc=setTimeout(jj,a-Sc.now()-de)),Wc&&(Wc=clearInterval(Wc))):(Wc||(ge=Sc.now(),Wc=setInterval(wp,1E3)),jc=1,hj(jj)))}function dg(a,c,d){var e=new Tc;c=null==c?0:+c;e.restart(function(d){e.stop();a(d+c)},c, +d);return e}function he(a,c,d,e,g,h){var k=a.__transition;if(!k)a.__transition={};else if(d in k)return;xp(a,d,{name:c,index:e,group:g,on:yp,tween:zp,time:h.time,delay:h.delay,duration:h.duration,ease:h.ease,timer:null,state:0})}function eg(a,c){a=$a(a,c);if(0e.state;e.state=6;e.timer.stop();e.on.call(k?"interrupt":"cancel",a,a.__data__,e.index,e.group);delete d[h]}g&&delete a.__transition}}function Ap(a,c){var d,e;return function(){var g=mb(this,a),h=g.tween;if(h!==d){e=d=h;h=0;for(var k=e.length;h=(a*=2)?a*a:--a*(2-a)+1)/2}function gg(a){return(1>=(a*=2)?a*a*a:(a-=2)*a*a+2)/2}function oj(a){return(1-Math.cos(pj*a))/2}function qj(a){return(1>=(a*=2)?Math.pow(2,10*a-10):2-Math.pow(2,10-10*a))/2}function rj(a){return(1>=(a*=2)?1-Math.sqrt(1-a*a):Math.sqrt(1-(a-=2)*a)+1)/ +2}function Xc(a){return(a=+a)Math.abs(a[1]-Oa[1])?X=!0:fa=!0);Oa=a;Q=!0;jg();g()}function g(){J=Oa[0]-$c[0];K=Oa[1]-$c[1];switch(z){case ng:case tj:v&&(J=Math.max(r-w,Math.min(C-B,J)),ca=w+J,A=B+J);f&&(K=Math.max(D-F,Math.min(S-H,K)),Aa=F+K,M=H+K);break;case kc:0>v?(J= +Math.max(r-w,Math.min(C-w,J)),ca=w+J,A=B):0f?(K=Math.max(D-F,Math.min(S-F,K)),Aa=F+K,M=H):0v?B=A-J:0f?H=M-K:0v?B=A:0f?H=M:0v?B=A:0f?H=M:0x!==F>x&&b<(u-r)*(x-w)/(F-w)+r&&(z=-z)}q=z}if(q){h=q;break a}}h=0}if(-1!==h){g.push(a);break}}});return{type:"MultiPolygon",value:c,coordinates:e}}function d(a,c,d){function e(a){var c=[a[0][0]+t,a[0][1]+p];a=[a[1][0]+t,a[1][1]+p];var e=2*c[0]+c[1]*(g+ +1)*4,h=2*a[0]+a[1]*(g+1)*4,q,f;(q=k[e])?(f=m[h])?(delete k[q.end],delete m[f.start],q===f?(q.ring.push(a),d(q.ring)):m[q.start]=k[f.end]={start:q.start,end:f.end,ring:q.ring.concat(f.ring)}):(delete k[q.end],q.ring.push(a),k[q.end=h]=q):(q=m[h])?(f=k[e])?(delete m[q.start],delete k[f.end],q===f?(q.ring.push(a),d(q.ring)):m[f.start]=k[q.end]={start:f.start,end:q.end,ring:f.ring.concat(q.ring)}):(delete m[q.start],q.ring.unshift(c),m[q.start=e]=q):m[e]=k[h]={start:e,end:h,ring:[c,a]}}var m=[],k=[], +p;var t=p=-1;var b=a[0]>=c;for(pb[b<<1].forEach(e);++t=c;pb[z|b<<1].forEach(e)}for(pb[b<<0].forEach(e);++p=c;var E=a[p*g]>=c;for(pb[b<<1|E<<2].forEach(e);++t=c;var y=E;E=a[p*g+t+1]>=c;pb[z|b<<1|E<<2|y<<3].forEach(e)}pb[b|E<<3].forEach(e)}t=-1;E=a[p*g]>=c;for(pb[E<<2].forEach(e);++t=c,pb[E<<2|y<<3].forEach(e);pb[E<<3].forEach(e)}function e(a,c,d){a.forEach(function(a){var e=a[0],m=a[1],k=e|0,p=m|0,q=c[p* +g+k];if(0=d&&(p>=h&&(t-=a.data[p-h+k*e]),c.data[p-d+k*e]=t/Math.min(p+1,e-1+h-p,h))}function rg(a,c,d){for(var e=a.width,g=a.height,h=(d<<1)+1,k=0;k=d&&(p>=h&&(t-=a.data[k+(p-h)*e]),c.data[k+(p-d)*e]=t/Math.min(p+1,g-1+h-p,h))}function zq(a){return a[0]}function Aq(a){return a[1]}function Bq(){return 1}function Bj(a){return new Function("d", +"return {"+a.map(function(a,d){return JSON.stringify(a)+": d["+d+'] || ""'}).join(",")+"}")}function Cq(a,c){var d=Bj(a);return function(e,g){return c(d(e),g,a)}}function Cj(a){var c=Object.create(null),d=[];a.forEach(function(a){for(var e in a)e in c||d.push(c[e]=e)});return d}function La(a,c){a+="";var d=a.length;return d=g?b=!0:10===(e=a.charCodeAt(h++))?I=!0:13===e&&(I=!0,10===a.charCodeAt(h)&&++h);return a.slice(d+1,c-1).replace(/""/g,'"')}for(;h=g,I=!1;10===a.charCodeAt(g-1)&&--g;for(13===a.charCodeAt(g-1)&&--g;(t=d())!==sg;){for(var N=[];t!==Dj&&t!==sg;)N.push(t),t=d();c&&null==(N=c(N,p++))|| +e.push(N)}return e}function d(c,d){return c.map(function(c){return d.map(function(a){return g(c[a])}).join(a)})}function e(c){return c.map(g).join(a)}function g(a){if(null==a)a="";else{if(a instanceof Date){var c=a.getUTCHours();var d=a.getUTCMinutes(),e=a.getUTCSeconds(),g=a.getUTCMilliseconds();if(isNaN(a))a="Invalid Date";else{var k=a.getUTCFullYear();a=(0>k?"-"+La(-k,6):9999=(m=(k+b)/2))?k=m:b=m,(v=d>=(q=(p+z)/2))?p= +q:z=q,g=h,!(h=h[x|=v<<1]))return g[x]=e,a;var B=+a._x.call(null,h.data);var G=+a._y.call(null,h.data);if(c===B&&d===G)return e.next=h,g?g[x]=e:a._root=e,a;do g=g?g[x]=Array(4):a._root=Array(4),(x=c>=(m=(k+b)/2))?k=m:b=m,(v=d>=(q=(p+z)/2))?p=q:z=q;while((x|=v<<1)===(v=(G>=q)<<1|B>=m));return g[v]=h,g[x]=e,a}function Ca(a,c,d,e,g){this.node=a;this.x0=c;this.y0=d;this.x1=e;this.y1=g}function Hq(a){return a[0]}function Iq(a){return a[1]}function pe(a,c,d){c=new ug(null==c?Hq:c,null==d?Iq:d,NaN,NaN,NaN, +NaN);return null==a?c:c.addAll(a)}function ug(a,c,d,e,g,h){this._x=a;this._y=c;this._x0=d;this._y0=e;this._x1=g;this._y1=h;this._root=void 0}function Gj(a){for(var c={data:a.data},d=c;a=a.next;)d=d.next={data:a.data};return c}function Jq(a){return a.x+a.vx}function Kq(a){return a.y+a.vy}function Lq(a){return a.index}function Hj(a,c){a=a.get(c);if(!a)throw Error("missing: "+c);return a}function Mq(a){return a.x}function Nq(a){return a.y}function qe(a,c){if(0>(c=(a=c?a.toExponential(c-1):a.toExponential()).indexOf("e")))return null; +var d=a.slice(0,c);return[1e&&(p=Math.max(1,e-b));h.push(d.substring(g-=p,g+p));if((b+=p+1)>e)break;p=a[k=(k+1)%a.length]}return h.reverse().join(c)}}function Pq(a){return function(c){return c.replace(/[0-9]/g,function(c){return a[+c]})}}function ad(a){if(!(c=Qq.exec(a)))throw Error("invalid format: "+a);var c;return new re({fill:c[1], +align:c[2],sign:c[3],symbol:c[4],zero:c[5],width:c[6],comma:c[7],precision:c[8]&&c[8].slice(1),trim:c[9],type:c[10]})}function re(a){this.fill=void 0===a.fill?" ":a.fill+"";this.align=void 0===a.align?">":a.align+"";this.sign=void 0===a.sign?"-":a.sign+"";this.symbol=void 0===a.symbol?"":a.symbol+"";this.zero=!!a.zero;this.width=void 0===a.width?void 0:+a.width;this.comma=!!a.comma;this.precision=void 0===a.precision?void 0:+a.precision;this.trim=!!a.trim;this.type=void 0===a.type?"":a.type+""}function Ij(a, +c){c=qe(a,c);if(!c)return a+"";a=c[0];c=c[1];return 0>c?"0."+Array(-c).join("0")+a:a.length>c+1?a.slice(0,c+1)+"."+a.slice(c+1):a+Array(c-a.length+2).join("0")}function Jj(a){return a}function Kj(a){function c(a){function c(a){var c=O,e=U,g,p;if("c"===L)e=ia(a)+e,a="";else{a=+a;var q=0>a||0>1/a;a=isNaN(a)?z:ia(Math.abs(a),y);if(P){var l=a.length,x=1,v=-1;a:for(;xp||57>1)+c+a+e+q.slice(p);break; +default:a=q+c+a+e}return k(a)}a=ad(a);var m=a.fill,t=a.align,B=a.sign,G=a.symbol,I=a.zero,N=a.width,E=a.comma,y=a.precision,P=a.trim,L=a.type;"n"===L?(E=!0,L="g"):Nj[L]||(void 0===y&&(y=12),P=!0,L="g");if(I||"0"===m&&"="===t)I=!0,m="0",t="=";var O="$"===G?e:"#"===G&&/[boxX]/.test(L)?"0"+L.toLowerCase():"",U="$"===G?g:/[%p]/.test(L)?p:"",ia=Nj[L],f=/[defgprs%]/.test(L);y=void 0===y?6:/[gprs]/.test(L)?Math.max(1,Math.min(21,y)):Math.max(0,Math.min(20,y));c.toString=function(){return a+""};return c} +var d=void 0===a.grouping||void 0===a.thousands?Jj:Oq(Oj.call(a.grouping,Number),a.thousands+""),e=void 0===a.currency?"":a.currency[0]+"",g=void 0===a.currency?"":a.currency[1]+"",h=void 0===a.decimal?".":a.decimal+"",k=void 0===a.numerals?Jj:Pq(Oj.call(a.numerals,String)),p=void 0===a.percent?"%":a.percent+"",b=void 0===a.minus?"-":a.minus+"",z=void 0===a.nan?"NaN":a.nan+"";return{format:c,formatPrefix:function(a,d){var e=c((a=ad(a),a.type="f",a));a=3*Math.max(-8,Math.min(8,Math.floor(mc(d)/3))); +var g=Math.pow(10,-a),h=Lj[8+a/3];return function(a){return e(g*a)+h}}}}function Pj(a){se=Kj(a);b.format=se.format;b.formatPrefix=se.formatPrefix;return se}function Qj(a){return Math.max(0,-mc(Math.abs(a)))}function Rj(a,c){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(mc(c)/3)))-mc(Math.abs(a)))}function Sj(a,c){a=Math.abs(a);c=Math.abs(c)-a;return Math.max(0,mc(c)-mc(a))+1}function ab(){this.reset()}function Tj(a,c,d){var e=a.s=c+d,g=e-c;a.t=c-(e-g)+(d-g)}function Uj(a){return 1 +a?Y:Math.acos(a)}function Da(a){return 1a?-ka:Math.asin(a)}function Vj(a){return(a=A(a/2))*a}function la(){}function te(a,c){if(a&&Wj.hasOwnProperty(a.type))Wj[a.type](a,c)}function vg(a,c,d){var e=-1;d=a.length-d;for(c.lineStart();++ePa&&(Pa=c)}function ck(a,c){var d=Sb([a*W,c*W]);if(oc){var e=nc(oc,d);e=nc([e[1],-e[0],0],e);ze(e);e=we(e);var g=a-Tb,h=0Pa&&(Pa=e)):(k=(k+360)%360-180,g^(h*TbPa&&(Pa=c));g?aQa(ma,na)&&(na=a):Qa(a,na)>Qa(ma,na)&&(ma=a):na>=ma?(ana&&(na=a)):a>Tb?Qa(ma,a)>Qa(ma,na)&&(na=a):Qa(a,na)>Qa(ma,na)&&(ma=a)}else Eb.push(qb=[ma=a,na=a]);cPa&&(Pa=c);oc=d;Tb=a}function dk(){rb.point=ck}function ek(){qb[0]=ma;qb[1]=na;rb.point=Ag;oc=null}function fk(a,c){if(oc){var d=a-Tb;bd.add(180(c-=a)?c+360:c}function Wq(a,c){return a[0]-c[0]}function ik(a,c){return a[0]<=a[1]?a[0]<=c&&c<=a[1]:cY?a+Math.round(-a/Ia)*Ia:a,c]}function Hg(a,c,d){return(a%=Ia)?c||d?Fg(ok(a),pk(c,d)):ok(a):c||d?pk(c,d):Gg}function qk(a){return function(c,d){return c+=a,[c>Y?c-Ia:c<-Y?c+Ia:c,d]}}function ok(a){var c=qk(a);c.invert=qk(-a);return c} +function pk(a,c){function d(a,c){var d=M(c),m=M(a)*d;a=A(a)*d;c=A(c);d=c*e+m*g;return[Ea(a*h-d*k,m*e-c*g),Da(d*h+a*k)]}var e=M(a),g=A(a),h=M(c),k=A(c);d.invert=function(a,c){var d=M(c),m=M(a)*d;a=A(a)*d;c=A(c);d=c*h-a*k;return[Ea(a*h+c*k,m*e+d*g),Da(d*e-m*g)]};return d}function rk(a){function c(c){c=a(c[0]*W,c[1]*W);return c[0]*=ha,c[1]*=ha,c}a=Hg(a[0]*W,a[1]*W,2h)g+=e*Ia;for(;0h:g-c[2]?-a:a)+Ia-1E-6)%Ia}function uk(){var a=[],c;return{point:function(a,e){c.push([a,e])},lineStart:function(){a.push(c=[])},lineEnd:la,rejoin:function(){1 +aa(a[0]-c[0])&&1E-6>aa(a[1]-c[1])}function Ie(a,c,d,e){this.x=a;this.z=c;this.o=d;this.e=e;this.v=!1;this.n=this.p=null}function vk(a,c,d,e,g){var h=[],k=[];a.forEach(function(a){if(!(0>=(c=a.length-1))){var c,d=a[0],e=a[c];if(He(d,e)){g.lineStart();for(p=0;pY;v*=N;Jg.add(Ea(v*P*A(L),B*E+v*M(L)));h+=O?y+P*Ia:y;O^q>=d^I>=d&&(m=nc(Sb(m),Sb(G)),ze(m),q=nc(g,m),ze(q),q=(O^0<=y?-1:1)*Da(q[2]),c>q||c===q&&(m[0]||m[1]))&&(k+= +O^0<=y?1:-1)}}return(-1E-6>h||1E-6>h&&-1E-6>Jg)^k&1}function yk(a,c,d,e){return function(g){function h(c,d){a(c,d)&&g.point(c,d)}function k(a,c){x.point(a,c)}function p(){y.point=k;x.lineStart()}function b(){y.point=h;x.lineEnd()}function z(a,c){E.push([a,c]);B.point(a,c)}function m(){B.lineStart();E=[]}function q(){z(E[0][0],E[0][1]);B.lineEnd();var a=B.clean(),c=v.result(),d=c.length,e;E.pop();I.push(E);E=null;if(d)if(a&1){if(d=c[0],0<(c=d.length-1)){G||(g.polygonStart(),G=!0);g.lineStart();for(a= +0;a(a=a.x)[0]?a[1]-ka-1E-6:ka-a[1])-(0>(c=c.x)[0]?c[1]-ka-1E-6:ka-c[1])}function zk(a){function c(a,c){return M(a)*M(c)>g}function d(a,c,d){var e=Sb(a),h=Sb(c),k=[1,0,0];h=nc(e,h);var m=xe(h,h);e=h[0];var p=m-e*e;if(!p)return!d&&a;m=g*m/p;p=-g*e/p;e=nc(k,h);k=ye(k,m);h=ye(h,p);zg(k,h);h=xe(k,e);m=xe(e,e);p=h*h-m*(xe(k,k)-1);if(!(0>p)){var b= +pa(p);p=ye(e,(-h-b)/m);zg(p,k);p=we(p);if(!d)return p;d=a[0];var t=c[0];a=a[1];c=c[1];if(taa(z-Y);!P&&cz?P?0aa(p[0]-d)?a:c):a<=p[1]&&p[1]<=c:z>Y^(d<=p[0]&&p[0]<=t))return c=ye(e,(-h+b)/m),zg(c,k),[p,we(c)]}}function e(c,d){var e=k?a:Y-a,g=0;c<-e?g|=1:c>e&&(g|=2);d<-e?g|=4:d>e&&(g|=8);return g}var g=M(a),h=6*W,k=0m?Y:-Y),x):0;!g&&(b=q=z)&&a.lineStart();z!==q&&(m=d(g,v),!m||He(g,m)||He(v,m))&&(v[0]+=1E-6,v[1]+=1E-6,z=c(v[0],v[1]));if(z!==q)t=0,z?(a.lineStart(),m=d(v,g),a.point(m[0],m[1])):(m=d(g,v),a.point(m[0],m[1]),a.lineEnd()),g=m;else if(p&&g&&k^z){var E;x&h||!(E=d(v,g,!0))||(t=0,k?(a.lineStart(),a.point(E[0][0],E[0][1]),a.point(E[1][0],E[1][1]),a.lineEnd()):(a.point(E[1][0],E[1][1]),a.lineEnd(),a.lineStart(),a.point(E[0][0],E[0][1])))}!z||g&&He(g,v)||a.point(v[0], +v[1]);g=v;q=z;h=x},lineEnd:function(){q&&a.lineEnd();g=null},clean:function(){return t|(b&&q)<<1}}},function(c,d,e,g){sk(g,a,h,e,c,d)},k?[0,-a]:[-Y,a-Y])}function dr(a,c,d,e,g,h){var k=a[0],p=a[1],b=0,z=1,m=c[0]-k,q=c[1]-p;d-=k;if(m||!(0m){if(dz)return;d>b&&(b=d)}d=g-k;if(m||!(0>d)){d/=m;if(0>m){if(d>z)return;d>b&&(b=d)}else if(0q){if(dz)return;d> +b&&(b=d)}d=h-p;if(q||!(0>d)){d/=q;if(0>q){if(d>z)return;d>b&&(b=d)}else if(0z&&(c[0]=k+z*m,c[1]=p+z*q);return!0}}}}}function Je(a,c,d,e){function g(g,k,m,b){var q=0,t=0;if(null==g||(q=h(g,m))!==(t=h(k,m))||0>p(g,k)^0aa(e[0]-a)?0aa(e[0]-d)?0aa(e[1]-c)?0e&&(E-y)*(e-z)>(x-z)*(a-y)&&++c:x<=e&&(E-y)*(e-z)<(x-z)*(a-y)&&--c}}d=U&&c;m=(v=Hf(v)).length;if(d||m)h.polygonStart(),d&&(h.lineStart(),g(null,null,1,h),h.lineEnd()),m&&vk(v,k,c,g,h),h.polygonEnd();b=h;v=B=G=null}};return ia}}function er(){qc.point=qc.lineEnd=la}function fr(a,c){a*=W;c*=W;Kg=a;Ke=A(c);Le=M(c);qc.point=gr}function gr(a,c){a*=W;c*=W;var d=A(c);c=M(c);var e=aa(a-Kg),g=M(e);e=A(e);e*=c;var h=Le*d-Ke*c*g;g=Ke*d+Le*c*g;Lg.add(Ea(pa(e*e+h*h),g));Kg=a;Ke=d;Le=c}function Ak(a){Lg.reset(); +bb(a,qc);return+Lg}function ed(a,c){Mg[0]=a;Mg[1]=c;return Ak(hr)}function Me(a,c){return a&&Bk.hasOwnProperty(a.type)?Bk[a.type](a,c):!1}function Ck(a,c){for(var d,e,g,h=0,k=a.length;hg&&(c=h,h=g,g=c);z>b&&(c=z,z=b,b=c);return a.precision(E)};a.extentMinor=function(c){if(!arguments.length)return[[e,p],[d,k]];e=+c[0][0];d=+c[1][0]; +p=+c[0][1];k=+c[1][1];e>d&&(c=e,e=d,d=c);p>k&&(c=p,p=k,k=c);return a.precision(E)};a.step=function(c){return arguments.length?a.stepMajor(c).stepMinor(c):a.stepMinor()};a.stepMajor=function(c){if(!arguments.length)return[x,v];x=+c[0];v=+c[1];return a};a.stepMinor=function(c){if(!arguments.length)return[m,q];m=+c[0];q=+c[1];return a};a.precision=function(c){if(!arguments.length)return E;E=+c;B=Fk(p,k,90);G=Gk(e,d,E);I=Fk(z,b,90);N=Gk(h,g,E);return a};return a.extentMajor([[-180,-89.999999],[180,89.999999]]).extentMinor([[-180, +-80.000001],[180,80.000001]])}function fd(a){return a}function jr(){sb.point=kr}function kr(a,c){sb.point=Ik;Jk=Ng=a;Kk=Og=c}function Ik(a,c){Pg.add(Og*a-Ng*c);Ng=a;Og=c}function lr(){Ik(Jk,Kk)}function Ub(a,c){Qg+=a;Rg+=c;++gd}function Lk(){Wa.point=mr}function mr(a,c){Wa.point=nr;Ub(ib=a,jb=c)}function nr(a,c){var d=a-ib,e=c-jb;d=pa(d*d+e*e);Oe+=d*(ib+a)/2;Pe+=d*(jb+c)/2;rc+=d;Ub(ib=a,jb=c)}function Mk(){Wa.point=Ub}function or(){Wa.point=pr}function qr(){Nk(Ok,Pk)}function pr(a,c){Wa.point=Nk; +Ub(Ok=ib=a,Pk=jb=c)}function Nk(a,c){var d=a-ib,e=c-jb;d=pa(d*d+e*e);Oe+=d*(ib+a)/2;Pe+=d*(jb+c)/2;rc+=d;d=jb*a-ib*c;Sg+=d*(ib+a);Tg+=d*(jb+c);hd+=3*d;Ub(ib=a,jb=c)}function Qk(a){this._context=a}function rr(a,c){id.point=Rk;Sk=jd=a;Tk=kd=c}function Rk(a,c){jd-=a;kd-=c;Ug.add(pa(jd*jd+kd*kd));jd=a;kd=c}function Uk(){this._string=[]}function Vk(a){return"m0,"+a+"a"+a+","+a+" 0 1,1 0,"+-2*a+"a"+a+","+a+" 0 1,1 0,"+2*a+"z"}function ld(a){return function(c){var d=new Vg,e;for(e in a)d[e]=a[e];d.stream= +c;return d}}function Vg(){}function Wg(a,c,d){var e=a.clipExtent&&a.clipExtent();a.scale(150).translate([0,0]);null!=e&&a.clipExtent(null);bb(d,a.stream(Qe));c(Qe.result());null!=e&&a.clipExtent(e);return a}function sc(a,c,d){return Wg(a,function(d){var e=c[1][0]-c[0][0],h=c[1][1]-c[0][1],k=Math.min(e/(d[1][0]-d[0][0]),h/(d[1][1]-d[0][1]));e=+c[0][0]+(e-k*(d[1][0]+d[0][0]))/2;d=+c[0][1]+(h-k*(d[1][1]+d[0][1]))/2;a.scale(150*k).translate([e,d])},d)}function Xg(a,c,d){return Wg(a,function(d){var e= ++c,h=e/(d[1][0]-d[0][0]);e=(e-h*(d[1][0]+d[0][0]))/2;d=-h*d[0][1];a.scale(150*h).translate([e,d])},d)}function Yg(a,c,d){return Wg(a,function(d){var e=+c,h=e/(d[1][1]-d[0][1]),k=-h*d[0][0];d=(e-h*(d[1][1]+d[0][1]))/2;a.scale(150*h).translate([k,d])},d)}function Wk(a){return ld({point:function(c,d){c=a(c,d);this.stream.point(c[0],c[1])}})}function Xk(a,c){function d(e,g,h,k,p,b,z,m,q,x,v,B,G,I){var t=z-e,E=m-g,y=t*t+E*E;if(y>4*c&&G--){var P=k+x,L=p+v,O=b+B,U=pa(P*P+L*L+O*O),ia=Da(O/=U),f=1E-6>aa(aa(O)- +1)||1E-6>aa(h-q)?(h+q)/2:Ea(L,P),l=a(f,ia);ia=l[0];l=l[1];var u=ia-e,n=l-g,r=E*u-t*n;if(r*r/y>c||.3I};c.reflectY=function(a){return arguments.length?(N=a?-1:1,e()):0>N};c.precision=function(a){if(arguments.length){var c=u;var d=f=a*a;c=(l=+d?Xk(c,d):Wk(c),g())}else c=pa(f);return c};c.fitExtent=function(a,d){return sc(c,a,d)};c.fitSize=function(a,d){return sc(c,[[0,0],a],d)};c.fitWidth=function(a,d){return Xg(c,a,d)};c.fitHeight=function(a,d){return Yg(c,a,d)}; +return function(){h=a.apply(this,arguments);c.invert=h.invert&&d;return e()}}function ah(a){var c=0,d=Y/3,e=Zg(a);a=e(c,d);a.parallels=function(a){return arguments.length?e(c=a[0]*W,d=a[1]*W):[c*ha,d*ha]};return a}function wr(a){function c(a,c){return[a*d,A(c)/d]}var d=M(a);c.invert=function(a,c){return[a/d,Da(c*d)]};return c}function Zk(a,c){function d(a,c){c=pa(h-2*g*A(c))/g;return[c*A(a*=g),k-c*M(a)]}var e=A(a),g=(e+A(c))/2;if(1E-6>aa(g))return wr(a);var h=1+e*(2*g-e),k=pa(h)/g;d.invert=function(a, +c){c=k-c;var d=Ea(a,aa(c))*Va(c);0>c*g&&(d-=Y*Va(a)*Va(c));return[d/g,Da((h-(a*a+c*c)*g*g)/(2*g))]};return d}function Re(){return ah(Zk).scale(155.424).center([0,33.6442])}function $k(){return Re().parallels([29.5,45.5]).scale(1070).translate([480,250]).rotate([96,0]).center([-.6,38.7])}function xr(a){var c=a.length;return{point:function(d,e){for(var g=-1;++gka-1E-6&&(c=ka-1E-6);c=h/bh(tc((ka+c)/2),g);return[c*A(g*a),h-c*M(g*a)]}var e=M(a),g=a===c?A(a):Se(e/M(c))/Se(tc((ka+c)/2)/tc((ka+a)/2)),h=e*bh(tc((ka+a)/2),g)/g;if(!g)return nd;d.invert=function(a,c){c=h-c;var d=Va(g)*pa(a*a+c*c),e=Ea(a,aa(c))*Va(c);0>c*g&&(e-=Y*Va(a)*Va(c));return[e/g,2*uc(bh(h/d,1/g))-ka]};return d}function od(a,c){return[a,c]}function dl(a,c){function d(a,c){c=h-c;a*=g;return[c* +A(a),h-c*M(a)]}var e=M(a),g=a===c?A(a):(e-M(c))/(c-a),h=e/g+a;if(1E-6>aa(g))return od;d.invert=function(a,c){c=h-c;var d=Ea(a,aa(c))*Va(c);0>c*g&&(d-=Y*Va(a)*Va(c));return[d/g,h-Va(g)*pa(a*a+c*c)]};return d}function ch(a,c){c=Da(Te*A(c));var d=c*c,e=d*d*d;return[a*M(c)/(Te*(1.340264+3*-.081106*d+e*(7*8.93E-4+.034164*d))),c*(1.340264+-.081106*d+e*(8.93E-4+.003796*d))]}function dh(a,c){var d=M(c),e=M(a)*d;return[d*A(a)/e,A(c)/e]}function eh(a,c){var d=c*c,e=d*d;return[a*(.8707-.131979*d+e*(-.013791+ +e*(.003971*d-.001529*e))),c*(1.007226+d*(.015085+e*(-.044475+.028874*d-.005916*e)))]}function fh(a,c){return[M(c)*A(a),A(c)]}function gh(a,c){var d=M(c),e=1+M(a)*d;return[d*A(a)/e,A(c)/e]}function hh(a,c){return[Se(tc((ka+c)/2)),-a]}function yr(a,c){return a.parent===c.parent?1:2}function zr(a,c){return a+c.x}function Ar(a,c){return Math.max(a,c.y)}function Br(a){for(var c;c=a.children;)a=c[0];return a}function Cr(a){for(var c;c=a.children;)a=c[c.length-1];return a}function Dr(a){var c=0,d=a.children, +e=d&&d.length;if(e)for(;0<=--e;)c+=d[e].value;else c=1;a.value=c}function ih(a,c){var d=new vc(a);a=+a.value&&(d.value=a.value);var e,g=[d],h,k,b,t;for(null==c&&(c=Er);e=g.pop();)if(a&&(e.value=+e.data.value),(k=c(e.data))&&(t=k.length))for(e.children=Array(t),b=t-1;0<=b;--b)g.push(h=e.children[b]=new vc(k[b])),h.parent=e,h.depth=e.depth+1;return d.eachBefore(el)}function Er(a){return a.children}function Fr(a){a.data=a.data.data}function el(a){var c=0;do a.height=c;while((a=a.parent)&&a.height<++c)} +function vc(a){this.data=a;this.depth=this.height=0;this.parent=null}function fl(a){var c=0;a=Gr.call(a);for(var d=a.length,e,g;d;)g=Math.random()*d--|0,e=a[d],a[d]=a[g],a[g]=e;d=a.length;e=[];for(var h;cd||d*de*e+a*a}function jh(a,c){for(var d=0;d +b){var t=(h+b-k)/(2*h);k=Math.sqrt(Math.max(0,b/h-t*t));d.x=a.x-t*e-k*g;d.y=a.y-t*g+k*e}else t=(h+k-b)/(2*h),k=Math.sqrt(Math.max(0,k/h-t*t)),d.x=c.x+t*e-k*g,d.y=c.y+t*g+k*e}else d.x=c.x+d.r,d.y=c.y}function jl(a,c){var d=a.r+c.r-1E-6,e=c.x-a.x;a=c.y-a.y;return 0e*e+a*a}function kl(a){var c=a._,d=a.next._,e=c.r+d.r;a=(c.x*d.r+d.x*c.r)/e;c=(c.y*d.r+d.y*c.r)/e;return a*a+c*c}function Ve(a){this._=a;this.previous=this.next=null}function ll(a){if(!(d=a.length))return 0;var c,d;var e=a[0];e.x= +0;e.y=0;if(!(1I&&(I=z);N=B*B*y;N=Math.max(I/N,N/G);if(N>E){B-=z;break}E=N}k.push(t={value:B,dice:c=Mr(a[d[e-2]],a[d[e-1]],a[g]);)--e;d[e++]=g}return d.slice(0,e)}function xc(){return Math.random()}function db(a,c){switch(arguments.length){case 0:break;case 1:this.range(a);break;default:this.range(c).domain(a)}return this}function tb(a,c){switch(arguments.length){case 0:break; +case 1:this.interpolator(a);break;default:this.interpolator(c).domain(a)}return this}function nh(){function a(a){var h=a+"",b=c.get(h);if(!b){if(g!==oh)return g;c.set(h,b=d.push(a))}return e[(b-1)%e.length]}var c=ob(),d=[],e=[],g=oh;a.domain=function(e){if(!arguments.length)return d.slice();d=[];c=ob();for(var g=-1,h=e.length,b,z;++gd&&(a=c,c=d,d=a);return function(a){return Math.max(c,Math.min(d,a))}}function Pr(a,c,d){var e=a[0];a=a[1];var g=c[0];c=c[1];at&&(b=Math.ceil(b*t)/t,p=Math.floor(p*t)/t,t=Jc(b,p,d));0t&&(e[g]=Math.ceil(b*t)/t,e[h]=Math.floor(p*t)/t,c(e));return a};return a}function wl(){var a=ul(wa,wa);a.copy=function(){return rd(a,wl())};db.apply(a,arguments);return Xb(a)}function xl(a){function c(a){return isNaN(a=+a)?d:a}var d;c.invert=c;c.domain=c.range=function(d){return arguments.length?(a=$e.call(d,qh),c):a.slice()};c.unknown=function(a){return arguments.length? +(d=a,c):d};c.copy=function(){return xl(a).unknown(d)};a=arguments.length?$e.call(a,qh):[0,1];return Xb(c)}function yl(a,c){a=a.slice();var d=0,e=a.length-1,g=a[d],h=a[e];if(ha?0:a}function Ur(a){return 10===a?Tr:a===Math.E?Math.exp:function(c){return Math.pow(a, +c)}}function Vr(a){return a===Math.E?Math.log:10===a&&Math.log10||2===a&&Math.log2||(a=Math.log(a),function(c){return Math.log(c)/a})}function Bl(a){return function(c){return-a(-c)}}function sh(a){function c(){h=Vr(g);k=Ur(g);0>e()[0]?(h=Bl(h),k=Bl(k),a(Rr,Sr)):a(zl,Al);return d}var d=a(zl,Al),e=d.domain,g=10,h,k;d.base=function(a){return arguments.length?(g=+a,c()):g};d.domain=function(a){return arguments.length?(e(a),c()):e()};d.ticks=function(a){var c=e(),d=c[0];c=c[c.length-1];var b;if(b=cc)break;a.push(G)}}}else for(;qc)break;a.push(G)}}else a=Cf(q,p,Math.min(p-q,v)).map(k);return b?a.reverse():a};d.tickFormat=function(a,c){null==c&&(c=10===g?".0e":",");"function"!==typeof c&&(c=b.format(c));if(Infinity===a)return c;null==a&&(a=10);var e=Math.max(1, +g*a/d.ticks().length);return function(a){var d=a/k(Math.round(h(a)));d*gc?-Math.pow(-c,a):Math.pow(c,a)}}function Wr(a){return 0>a?-Math.sqrt(-a):Math.sqrt(a)}function Xr(a){return 0>a?-a*a:a*a}function uh(a){var c=a(wa,wa),d=1;c.exponent=function(c){return arguments.length? +(d=+c,1===d?a(wa,wa):.5===d?a(Wr,Xr):a(Gl(d),Gl(1/d))):d};return Xb(c)}function vh(){var a=uh(Ze());a.copy=function(){return rd(a,vh()).exponent(a.exponent())};db.apply(a,arguments);return a}function Hl(){function a(){var a=0,h=Math.max(1,e.length);for(g=Array(h-1);++aa?[NaN,NaN]:[0a?[NaN,NaN]:1>a?[d,h[0]]:a>=g?[h[g-1],e]:[h[a-1],h[a]]};a.unknown=function(c){return arguments.length?(p=c,a):a};a.thresholds=function(){return h.slice()};a.copy=function(){return Il().domain([d,e]).range(b).unknown(p)};return db.apply(Xb(a),arguments)}function Jl(){function a(a){return a<= +a?d[Fb(c,a,0,g)]:e}var c=[.5],d=[0,1],e,g=1;a.domain=function(e){return arguments.length?(c=Wb.call(e),g=Math.min(c.length,d.length-1),a):c.slice()};a.range=function(e){return arguments.length?(d=Wb.call(e),g=Math.min(c.length,d.length-1),a):d.slice()};a.invertExtent=function(a){a=d.indexOf(a);return[c[a-1],c[a]]};a.unknown=function(c){return arguments.length?(e=c,a):e};a.copy=function(){return Jl().domain(c).range(d).unknown(e)};return db.apply(a,arguments)}function ra(a,c,d,e){function g(c){return a(c= +0===arguments.length?new Date:new Date(+c)),c}g.floor=function(c){return a(c=new Date(+c)),c};g.ceil=function(d){return a(d=new Date(d-1)),c(d,1),a(d),d};g.round=function(a){var c=g(a),d=g.ceil(a);return a-c= +c)for(;a(c),!d(c);)c.setTime(c-1)},function(a,e){if(a>=a)if(0>e)for(;0>=++e;)for(;c(a,-1),!d(a););else for(;0<=--e;)for(;c(a,1),!d(a););})};d&&(g.count=function(c,e){wh.setTime(+c);xh.setTime(+e);a(wh);a(xh);return Math.floor(d(wh,xh))},g.every=function(a){a=Math.floor(a);return isFinite(a)&&0a.y){var c=new Date(-1,a.m,a.d,a.H,a.M,a.S,a.L);c.setFullYear(a.y);return c}return new Date(a.y,a.m,a.d,a.H,a.M,a.S,a.L)}function zh(a){if(0<=a.y&&100> +a.y){var c=new Date(Date.UTC(-1,a.m,a.d,a.H,a.M,a.S,a.L));c.setUTCFullYear(a.y);return c}return new Date(Date.UTC(a.y,a.m,a.d,a.H,a.M,a.S,a.L))}function sd(a,c,d){return{y:a,m:c,d,H:0,M:0,S:0,L:0}}function Kl(a){function c(a,c){return function(d){var e=[],g=-1,f=0,h=a.length,b,m;for(d instanceof Date||(d=new Date(+d));++gg.V||53=h)return-1;b=c.charCodeAt(g++);if(37===b){if(b= +c.charAt(g++),b=ia[b in Ll?c.charAt(g++):b],!b||0>(e=b(a,d,e)))return-1}else if(b!=d.charCodeAt(e++))return-1}return e}var g=a.dateTime,h=a.date,b=a.time,p=a.periods,t=a.days,z=a.shortDays,m=a.months,q=a.shortMonths,x=xd(p),v=yd(p),B=xd(t),G=yd(t),I=xd(z),N=yd(z),E=xd(m),y=yd(m),P=xd(q),L=yd(q),O={a:function(a){return z[a.getDay()]},A:function(a){return t[a.getDay()]},b:function(a){return q[a.getMonth()]},B:function(a){return m[a.getMonth()]},c:null,d:Ml,e:Ml,f:Yr,H:Zr,I:$r,j:as,L:Nl,m:bs,M:cs,p:function(a){return p[+(12<= +a.getHours())]},q:function(a){return 1+~~(a.getMonth()/3)},Q:Ol,s:Pl,S:ds,u:es,U:fs,V:gs,w:hs,W:is,x:null,X:null,y:js,Y:ks,Z:ls,"%":Ql},U={a:function(a){return z[a.getUTCDay()]},A:function(a){return t[a.getUTCDay()]},b:function(a){return q[a.getUTCMonth()]},B:function(a){return m[a.getUTCMonth()]},c:null,d:Rl,e:Rl,f:ms,H:ns,I:os,j:ps,L:Sl,m:qs,M:rs,p:function(a){return p[+(12<=a.getUTCHours())]},q:function(a){return 1+~~(a.getUTCMonth()/3)},Q:Ol,s:Pl,S:ss,u:ts,U:us,V:vs,w:ws,W:xs,x:null,X:null,y:ys, +Y:zs,Z:As,"%":Ql},ia={a:function(a,c,d){return(c=I.exec(c.slice(d)))?(a.w=N[c[0].toLowerCase()],d+c[0].length):-1},A:function(a,c,d){return(c=B.exec(c.slice(d)))?(a.w=G[c[0].toLowerCase()],d+c[0].length):-1},b:function(a,c,d){return(c=P.exec(c.slice(d)))?(a.m=L[c[0].toLowerCase()],d+c[0].length):-1},B:function(a,c,d){return(c=E.exec(c.slice(d)))?(a.m=y[c[0].toLowerCase()],d+c[0].length):-1},c:function(a,c,d){return e(a,g,c,d)},d:Tl,e:Tl,f:Bs,H:Ul,I:Ul,j:Cs,L:Ds,m:Es,M:Fs,p:function(a,c,d){return(c= +x.exec(c.slice(d)))?(a.p=v[c[0].toLowerCase()],d+c[0].length):-1},q:Gs,Q:Hs,s:Is,S:Js,u:Ks,U:Ls,V:Ms,w:Ns,W:Os,x:function(a,c,d){return e(a,h,c,d)},X:function(a,c,d){return e(a,b,c,d)},y:Ps,Y:Qs,Z:Rs,"%":Ss};O.x=c(h,O);O.X=c(b,O);O.c=c(g,O);U.x=c(h,U);U.X=c(b,U);U.c=c(g,U);return{format:function(a){var d=c(a+="",O);d.toString=function(){return a};return d},parse:function(a){var c=d(a+="",!1);c.toString=function(){return a};return c},utcFormat:function(a){var d=c(a+="",U);d.toString=function(){return a}; +return d},utcParse:function(a){var c=d(a+="",!0);c.toString=function(){return a};return c}}}function da(a,c,d){var e=0>a?"-":"";a=(e?-a:a)+"";var g=a.length;return e+(g=a?-df:Math.asin(a)}function at(a){return a.innerRadius}function bt(a){return a.outerRadius}function ct(a){return a.startAngle}function dt(a){return a.endAngle}function et(a){return a&&a.padAngle}function ef(a,c,d,e,g,h,b){var k=a-d,t=c-e;b=(b?h:-h)/zc(k*k+t*t);t*=b;k*=-b;var z=a+t,m=c+k,q=d+t,x=e+k;d=(z+q)/2;e=(m+x)/2;c=q-z;a=x-m;b=c*c+a*a;h=g-h;x=z*x-q*m;var v=(0>a?-1:1)*zc(ft(0,h*h*b-x* +x));z=(x*a-c*v)/b;m=(-x*c-a*v)/b;q=(x*a+c*v)/b;c=(-x*c+a*v)/b;a=z-d;b=m-e;d=q-d;e=c-e;a*a+b*b>d*d+e*e&&(z=q,m=c);return{cx:z,cy:m,x01:-t,y01:-k,x11:z*(g/h-1),y11:m*(g/h-1)}}function fm(a){this._context=a}function ff(a){return new fm(a)}function Eh(a){return a[0]}function Fh(a){return a[1]}function Gh(){function a(a){var k,p=a.length,m,q=!1,x;null==g&&(b=h(x=Bb()));for(k=0;k<=p;++k)!(k=y;--m)z.point(N[m],E[m]);z.lineEnd();z.areaEnd()}G&&(N[c]=+d(B,c,a),E[c]=+g(B,c,a),z.point(e?+e(B,c,a):N[c],h?+h(B,c,a):E[c]))}if(I)return z=null,I+""||null}function c(){return Gh().defined(b).curve(t).context(p)}var d=Eh,e=null,g=ba(0),h=Fh,b=ba(!0),p=null,t=ff,z=null;a.x=function(c){return arguments.length?(d= +"function"===typeof c?c:ba(+c),e=null,a):d};a.x0=function(c){return arguments.length?(d="function"===typeof c?c:ba(+c),a):d};a.x1=function(c){return arguments.length?(e=null==c?null:"function"===typeof c?c:ba(+c),a):e};a.y=function(c){return arguments.length?(g="function"===typeof c?c:ba(+c),h=null,a):g};a.y0=function(c){return arguments.length?(g="function"===typeof c?c:ba(+c),a):g};a.y1=function(c){return arguments.length?(h=null==c?null:"function"===typeof c?c:ba(+c),a):h};a.lineX0=a.lineY0=function(){return c().x(d).y(g)}; +a.lineY1=function(){return c().x(d).y(h)};a.lineX1=function(){return c().x(e).y(g)};a.defined=function(c){return arguments.length?(b="function"===typeof c?c:ba(!!c),a):b};a.curve=function(c){return arguments.length?(t=c,null!=p&&(z=t(p)),a):t};a.context=function(c){return arguments.length?(null==c?p=z=null:z=t(p=c),a):p};return a}function gt(a,c){return ca?1:c>=a?0:NaN}function ht(a){return a}function hm(a){this._curve=a}function Hh(a){function c(c){return new hm(a(c))}c._curve=a;return c} +function Dd(a){var c=a.curve;a.angle=a.x;delete a.x;a.radius=a.y;delete a.y;a.curve=function(a){return arguments.length?c(Hh(a)):c()._curve};return a}function im(){return Dd(Gh().curve(jm))}function km(){var a=gm().curve(jm),c=a.curve,d=a.lineX0,e=a.lineX1,g=a.lineY0,b=a.lineY1;a.angle=a.x;delete a.x;a.startAngle=a.x0;delete a.x0;a.endAngle=a.x1;delete a.x1;a.radius=a.y;delete a.y;a.innerRadius=a.y0;delete a.y0;a.outerRadius=a.y1;delete a.y1;a.lineStartAngle=function(){return Dd(d())};delete a.lineX0; +a.lineEndAngle=function(){return Dd(e())};delete a.lineX1;a.lineInnerRadius=function(){return Dd(g())};delete a.lineY0;a.lineOuterRadius=function(){return Dd(b())};delete a.lineY1;a.curve=function(a){return arguments.length?c(Hh(a)):c()._curve};return a}function Ed(a,c){return[(c=+c)*Math.cos(a-=Math.PI/2),c*Math.sin(a)]}function it(a){return a.source}function jt(a){return a.target}function Ih(a){function c(){var c,h=Jh.call(arguments),z=d.apply(this,h),m=e.apply(this,h);k||(k=c=Bb());a(k,+g.apply(this, +(h[0]=z,h)),+b.apply(this,h),+g.apply(this,(h[0]=m,h)),+b.apply(this,h));if(c)return k=null,c+""||null}var d=it,e=jt,g=Eh,b=Fh,k=null;c.source=function(a){return arguments.length?(d=a,c):d};c.target=function(a){return arguments.length?(e=a,c):e};c.x=function(a){return arguments.length?(g="function"===typeof a?a:ba(+a),c):g};c.y=function(a){return arguments.length?(b="function"===typeof a?a:ba(+a),c):b};c.context=function(a){return arguments.length?(k=null==a?null:a,c):k};return c}function kt(a,c, +d,e,g){a.moveTo(c,d);a.bezierCurveTo(c=(c+e)/2,d,c,g,e,g)}function lt(a,c,d,e,g){a.moveTo(c,d);a.bezierCurveTo(c,d=(d+g)/2,e,d,e,g)}function mt(a,c,d,e,g){var b=Ed(c,d);c=Ed(c,d=(d+g)/2);d=Ed(e,d);e=Ed(e,g);a.moveTo(b[0],b[1]);a.bezierCurveTo(c[0],c[1],d[0],d[1],e[0],e[1])}function Hb(){}function gf(a,c,d){a._context.bezierCurveTo((2*a._x0+a._x1)/3,(2*a._y0+a._y1)/3,(a._x0+2*a._x1)/3,(a._y0+2*a._y1)/3,(a._x0+4*a._x1+c)/6,(a._y0+4*a._y1+d)/6)}function hf(a){this._context=a}function lm(a){this._context= +a}function mm(a){this._context=a}function nm(a,c){this._basis=new hf(a);this._beta=c}function jf(a,c,d){a._context.bezierCurveTo(a._x1+a._k*(a._x2-a._x0),a._y1+a._k*(a._y2-a._y0),a._x2+a._k*(a._x1-c),a._y2+a._k*(a._y1-d),a._x2,a._y2)}function Kh(a,c){this._context=a;this._k=(1-c)/6}function Lh(a,c){this._context=a;this._k=(1-c)/6}function Mh(a,c){this._context=a;this._k=(1-c)/6}function Nh(a,c,d){var e=a._x1,g=a._y1,b=a._x2,k=a._y2;if(1E-12c&&-0);a=(d-a._y1)/(c||0>e&&-0);return((0>g?-1:1)+(0>a?-1:1))*Math.min(Math.abs(g),Math.abs(a),.5*Math.abs((g*c+a*e)/(e+c)))||0}function tm(a,c){var d=a._x1-a._x0;return d?(3*(a._y1-a._y0)/d-c)/2:c}function Oh(a,c,d){var e=a._x0,g=a._x1,b=a._y1,k=(g-e)/3;a._context.bezierCurveTo(e+k,a._y0+k*c,g-k,b-k*d,g,b)}function kf(a){this._context=a}function um(a){this._context=new vm(a)}function vm(a){this._context=a}function wm(a){this._context= +a}function xm(a){var c,d=a.length-1,e=Array(d),g=Array(d),b=Array(d);e[0]=0;g[0]=2;b[0]=a[0]+2*a[1];for(c=1;cb&&(b=g,d=c);return d}function zm(a){var c=a.map(Am);return Bc(a).sort(function(a,e){return c[a]-c[e]})}function Am(a){for(var c=0,d=-1,e=a.length,g;++dm){if(cz)return;c>t&&(t=c)}c=e-p;if(m||!(0>c)){c/=m;if(0>m){if(c>z)return;c>t&&(t=c)}else if(0k){if(cz)return;c>t&&(t=c)}c=g-b;if(k||!(0>c)){c/=k;if(0>k){if(c>z)return;c>t&&(t=c)}else if(0z))return!0;0z&&(a[1]=[p+z*m,b+z*k]);return!0}}}}}function st(a,c,d,e,g){var b=a[1];if(b)return!0;var k=a[0],p=a.left,t=a.right;b=p[0];p=p[1];var z=t[0];t=t[1];var m=(b+z)/2;if(t===p){if(m=e)return;if(b>z){if(!k)k=[m,d];else if(k[1]>=g)return;b=[m,g]}else{if(!k)k= +[m,g];else if(k[1]q||1z){if(!k)k=[(d-m)/q,d];else if(k[1]>=g)return;b=[(g-m)/q,g]}else{if(!k)k=[(g-m)/q,g];else if(k[1]=e)return;b=[e,q*e+m]}else{if(!k)k=[e,q*e+m];else if(k[0]=-wt)){var z=k*k+p*p,m=e*e+t*t;p=(t*z-p*m)/g;e=(k*m-e*z)/g;k=Em.pop()||new vt;k.arc=a;k.site=c;k.x=p+d;k.y=(k.cy=e+b)+Math.sqrt(p*p+e*e);a.circle=k;a=null;for(c=Jd._;c;)if(k.yea)t=t.L;else{var m=t;var q=p;var x=m.N;x?q=Hm(x,q):(m=m.site,q=m[1]===q?m[0]:Infinity);q=k-q;if(q>ea){if(!t.R){b=t;break}t=t.R}else{z>-ea?(b=t.P,e=t):q>-ea?(b=t,e=t.N):b=e=t;break}}}Ra[g.index]={site:g,halfedges:[]};z=Fm(g);Ec.insert(b,z);if(b||e)if(b===e)Dc(b),e=Fm(b.site),Ec.insert(z,e),z.edge=e.edge=Hd(b.site,z.site),Cc(b),Cc(e);else if(e){Dc(b);Dc(e); +k=b.site;t=k[0];q=k[1];m=g[0]-t;x=g[1]-q;p=e.site;var v=p[0]-t,B=p[1]-q,G=2*(m*B-x*v),I=m*m+x*x,N=v*v+B*B;t=[(B*I-x*N)/G+t,(m*N-v*I)/G+q];of(e.edge,k,p,t);z.edge=Hd(k,g,null,t);e.edge=Hd(g,p,null,t);Cc(b);Cc(e)}else z.edge=Hd(b.site,z.site);e=d[0];b=d[1]}d=a.pop()}else if(g){p=g.arc;g=p.circle;k=g.x;t=g.cy;g=[k,t];m=p.P;q=p.N;z=[p];Qh(p);for(p=m;p.circle&&Math.abs(k-p.circle.x)ea||Math.abs(E[0][1]-E[1][1])>ea)||delete xa[b];E=Ra.length;b=!0;for(g=0;gea||Math.abs(v-B)>ea)p.splice(k,0,xa.push(Id(y,m,Math.abs(x-e)ea?[e,Math.abs(q-e)ea?[Math.abs(B-c)ea?[d,Math.abs(q-d)ea?[Math.abs(B-a)e?(e+g)/2:Math.min(0,e)||Math.max(0,g),c>b?(b+c)/2:Math.min(0,b)||Math.max(0,c))}var Km=Af(Sa),Fb=Km.right,Ft=Km.left,Lm=Array.prototype,Gt=Lm.slice,Ht=Lm.map,Df=Math.sqrt(50),Ef=Math.sqrt(10),Ff=Math.sqrt(2),If=Array.prototype.slice,po={value:function(){}};Qd.prototype=Lb.prototype={constructor:Qd,on:function(a,c){var d= +this._,e=oo(a+"",d),g,b=-1,k=e.length;if(2>arguments.length)for(;++bthis._names.indexOf(a)&&(this._names.push(a),this._node.setAttribute("class",this._names.join(" ")))},remove:function(a){a=this._names.indexOf(a); +0<=a&&(this._names.splice(a,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(a){return 0<=this._names.indexOf(a)}};var xi={};b.event=null;"undefined"!==typeof document&&("onmouseenter"in document.documentElement||(xi={mouseenter:"mouseover",mouseleave:"mouseout"}));var Of=[null];za.prototype=Nb.prototype={constructor:za,select:function(a){"function"!==typeof a&&(a=Sd(a));for(var c=this._groups,d=c.length,e=Array(d),g=0;g= +q&&(q=m+1);!(N=I[q])&&++qarguments.length){var e=this.node();return d.local?e.getAttributeNS(d.space,d.local):e.getAttribute(d)}return this.each((null==c?d.local?zo:yo:"function"===typeof c?d.local?Do:Co:d.local?Bo:Ao)(d,c))},style:function(a,c,d){return 1arguments.length){for(var e=Nf(this.node()),g=-1,b=d.length;++garguments.length){var k=this.node().__on;if(k)for(var p=0,t=k.length,z;pthis.r&&-.5<=this.g&&255.5>this.g&&-.5<=this.b&&255.5>this.b&&0<=this.opacity&&1>=this.opacity},hex:Fi,formatHex:Fi,formatRgb:Gi,toString:Gi}));fc(eb,Zd,Oc(yb,{brighter:function(a){a= +null==a?Fc:Math.pow(Fc,a);return new eb(this.h,this.s,this.l*a,this.opacity)},darker:function(a){a=null==a?.7:Math.pow(.7,a);return new eb(this.h,this.s,this.l*a,this.opacity)},rgb:function(){var a=this.h%360+360*(0>this.h),c=isNaN(a)||isNaN(this.s)?0:this.s,d=this.l;c=d+(.5>d?d:1-d)*c;d=2*d-c;return new va(Uf(240<=a?a-240:a+120,d,c),Uf(a,d,c),Uf(120>a?a+240:a-120,d,c),this.opacity)},displayable:function(){return(0<=this.s&&1>=this.s||isNaN(this.s))&&0<=this.l&&1>=this.l&&0<=this.opacity&&1>=this.opacity}, +formatHsl:function(){var a=this.opacity;a=isNaN(a)?1:Math.max(0,Math.min(1,a));return(1===a?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===a?")":", "+a+")")}}));var Oi=Math.PI/180,Ni=180/Math.PI,Li=4/29,hc=6/29,Ki=3*hc*hc,qp=hc*hc*hc;fc(Ya,$d,Oc(yb,{brighter:function(a){return new Ya(this.l+18*(null==a?1:a),this.a,this.b,this.opacity)},darker:function(a){return new Ya(this.l-18*(null==a?1:a),this.a,this.b,this.opacity)},rgb:function(){var a=(this.l+16)/116,c=isNaN(this.a)? +a:a+this.a/500,d=isNaN(this.b)?a:a-this.b/200;c=.96422*Xf(c);a=1*Xf(a);d=.82521*Xf(d);return new va(Yf(3.1338561*c-1.6168667*a-.4906146*d),Yf(-.9787684*c+1.9161415*a+.033454*d),Yf(.0719453*c-.2289914*a+1.4052427*d),this.opacity)}}));fc(fb,ae,Oc(yb,{brighter:function(a){return new fb(this.h,this.c,this.l+18*(null==a?1:a),this.opacity)},darker:function(a){return new fb(this.h,this.c,this.l-18*(null==a?1:a),this.opacity)},rgb:function(){return Ji(this).rgb()}}));var Pi=1.78277*-.29227-.1347134789;fc(Pb, +Za,Oc(yb,{brighter:function(a){a=null==a?Fc:Math.pow(Fc,a);return new Pb(this.h,this.s,this.l*a,this.opacity)},darker:function(a){a=null==a?.7:Math.pow(.7,a);return new Pb(this.h,this.s,this.l*a,this.opacity)},rgb:function(){var a=isNaN(this.h)?0:(this.h+120)*Oi,c=+this.l,d=isNaN(this.s)?0:this.s*c*(1-c),e=Math.cos(a);a=Math.sin(a);return new va(255*(c+d*(-.14861*e+1.78277*a)),255*(c+d*(-.29227*e+-.90649*a)),255*(c+1.97294*d*e),this.opacity)}}));var Qc=function d(c){function e(c,d){var e=g((c=gc(c)).r, +(d=gc(d)).r),b=g(c.g,d.g),h=g(c.b,d.b),m=sa(c.opacity,d.opacity);return function(d){c.r=e(d);c.g=b(d);c.b=h(d);c.opacity=m(d);return c+""}}var g=sp(c);e.gamma=d;return e}(1),dm=Ui(Ri),It=Ui(Si),ag=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,bg=new RegExp(ag.source,"g"),aj=180/Math.PI,Sh={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1},Ld,Th,Mm,rf,Nm=bj(function(c){if("none"===c)return Sh;Ld||(Ld=document.createElement("DIV"),Th=document.documentElement,Mm=document.defaultView);Ld.style.transform= +c;c=Mm.getComputedStyle(Th.appendChild(Ld),null).getPropertyValue("transform");Th.removeChild(Ld);c=c.slice(7,-1).split(",");return $i(+c[0],+c[1],+c[2],+c[3],+c[4],+c[5])},"px, ","px)","deg)"),Om=bj(function(c){if(null==c)return Sh;rf||(rf=document.createElementNS("http://www.w3.org/2000/svg","g"));rf.setAttribute("transform",c);if(!(c=rf.transform.baseVal.consolidate()))return Sh;c=c.matrix;return $i(c.a,c.b,c.c,c.d,c.e,c.f)},", ",")",")"),Rc=Math.SQRT2,Jt=ej(ce),Kt=ej(sa),Lt=fj(ce),Mt=fj(sa),Nt= +gj(ce),sf=gj(sa),jc=0,Uc=0,Wc=0,fe,Vc,ge=0,Qb=0,de=0,Sc="object"===typeof performance&&performance.now?performance:Date,hj="object"===typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(c){setTimeout(c,17)};Tc.prototype=ee.prototype={constructor:Tc,restart:function(c,d,e){if("function"!==typeof c)throw new TypeError("callback is not a function");e=(null==e?ic():+e)+(null==d?0:+d);this._next||Vc===this||(Vc?Vc._next=this:fe=this,Vc=this);this._call=c;this._time= +e;cg()},stop:function(){this._call&&(this._call=null,this._time=Infinity,cg())}};var yp=Lb("start","end","cancel","interrupt"),zp=[],Ot=Nb.prototype.constructor,Pm=0,Gc=Nb.prototype;gb.prototype=mj.prototype={constructor:gb,select:function(c){var d=this._name,e=this._id;"function"!==typeof c&&(c=Sd(c));for(var g=this._groups,b=g.length,k=Array(b),p=0;parguments.length?$a(this.node(),e).on.on(c):this.each(Sp(e,c,d))},attr:function(c,d){var e= +Lc(c),g="transform"===e?Om:kj;return this.attrTween(c,"function"===typeof d?(e.local?Hp:Gp)(e,g,fg(this,"attr."+c,d)):null==d?(e.local?Dp:Cp)(e):(e.local?Fp:Ep)(e,g,d))},attrTween:function(c,d){var e="attr."+c;if(2>arguments.length)return(e=this.tween(e))&&e._value;if(null==d)return this.tween(e,null);if("function"!==typeof d)throw Error();var g=Lc(c);return this.tween(e,(g.local?Kp:Lp)(g,d))},style:function(c,d,e){var g="transform"===(c+="")?Nm:kj;return null==d?this.styleTween(c,Up(c,g)).on("end.style."+ +c,lj(c)):"function"===typeof d?this.styleTween(c,Wp(c,g,fg(this,"style."+c,d))).each(Xp(this._id,c)):this.styleTween(c,Vp(c,g,d),e).on("end.style."+c,null)},styleTween:function(c,d,e){var g="style."+(c+="");if(2>arguments.length)return(g=this.tween(g))&&g._value;if(null==d)return this.tween(g,null);if("function"!==typeof d)throw Error();return this.tween(g,Zp(c,d,null==e?"":e))},text:function(c){return this.tween("text","function"===typeof c?aq(fg(this,"text",c)):$p(null==c?"":c+""))},textTween:function(c){var d= +"text";if(1>arguments.length)return(d=this.tween(d))&&d._value;if(null==c)return this.tween(d,null);if("function"!==typeof c)throw Error();return this.tween(d,cq(c))},remove:function(){return this.on("end.remove",Tp(this._id))},tween:function(c,d){var e=this._id;c+="";if(2>arguments.length){e=$a(this.node(),e).tween;for(var g=0,b=e.length,k;g=(b*=2)?Math.pow(b,g):2-Math.pow(2-b,g))/2}g=+g;b.exponent=h;return b}(3),pj=Math.PI,Rm=pj/2,hg=4/11,eq=6/11,dq=8/11,gq=9/11,fq=10/11,hq=21/22,ie=1/hg/hg,Rt=function k(b){function h(h){return h*h*((b+1)*h-b)}b=+b;h.overshoot=k;return h}(1.70158),St=function p(b){function k(k){return--k* +k*((b+1)*k+b)+1}b=+b;k.overshoot=p;return k}(1.70158),Sm=function t(b){function p(m){return(1>(m*=2)?m*m*((b+1)*m-b):(m-=2)*m*((b+1)*m+b)+2)/2}b=+b;p.overshoot=t;return p}(1.70158),Hc=2*Math.PI,Tt=function m(b,z){function q(m){return b*Math.pow(2,10*--m)*Math.sin((x-m)/z)}var x=Math.asin(1/(b=Math.max(1,b)))*(z/=Hc);q.amplitude=function(b){return m(b,z*Hc)};q.period=function(q){return m(b,q)};return q}(1,.3),Tm=function q(b,m){function x(q){return 1-b*Math.pow(2,-10*(q=+q))*Math.sin((q+v)/m)}var v= +Math.asin(1/(b=Math.max(1,b)))*(m/=Hc);x.amplitude=function(b){return q(b,m*Hc)};x.period=function(m){return q(b,m)};return x}(1,.3),Ut=function x(b,q){function m(m){return(0>(m=2*m-1)?b*Math.pow(2,10*m)*Math.sin((B-m)/q):2-b*Math.pow(2,-10*m)*Math.sin((B+m)/q))/2}var B=Math.asin(1/(b=Math.max(1,b)))*(q/=Hc);m.amplitude=function(b){return x(b,q*Hc)};m.period=function(m){return x(b,m)};return m}(1,.3),Uh={time:null,delay:0,duration:250,ease:gg};Nb.prototype.interrupt=function(b){return this.each(function(){Rb(this, +b)})};Nb.prototype.transition=function(b){var m;if(b instanceof gb){var x=b._id;b=b._name}else x=++Pm,(m=Uh).time=ic(),b=null==b?null:b+"";for(var v=this._groups,B=v.length,G=0;GB)throw Error("negative radius: "+B);if(null===this._x1)this._+="M"+(this._x1=b)+","+(this._y1=q);else if(1E-6y*v)+","+(this._x1=b+L*N)+","+(this._y1=q+L*E)}else this._+= +"L"+(this._x1=b)+","+(this._y1=q)},arc:function(b,q,x,v,B,G){b=+b;q=+q;x=+x;G=!!G;var m=x*Math.cos(v),N=x*Math.sin(v),E=b+m,y=q+N,P=1^G;v=G?v-B:B-v;if(0>x)throw Error("negative radius: "+x);if(null===this._x1)this._+="M"+E+","+y;else if(1E-6v&&(v=v%Wh+Wh),v>Yt?this._+="A"+x+","+x+",0,1,"+P+","+(b-m)+","+(q-N)+"A"+x+","+x+",0,1,"+P+","+(this._x1=E)+","+(this._y1=y):1E-6=Vh)+","+P+","+(this._x1= +b+x*Math.cos(B))+","+(this._y1=q+x*Math.sin(B))))},rect:function(b,q,x,v){this._+="M"+(this._x0=this._x1=+b)+","+(this._y0=this._y1=+q)+"h"+ +x+"v"+ +v+"h"+-x+"Z"},toString:function(){return this._}};le.prototype=ob.prototype={constructor:le,has:function(b){return"$"+b in this},get:function(b){return this["$"+b]},set:function(b,q){this["$"+b]=q;return this},remove:function(b){b="$"+b;return b in this&&delete this[b]},clear:function(){for(var b in this)"$"===b[0]&&delete this[b]},keys:function(){var b= +[],q;for(q in this)"$"===q[0]&&b.push(q.slice(1));return b},values:function(){var b=[],q;for(q in this)"$"===q[0]&&b.push(this[q]);return b},entries:function(){var b=[],q;for(q in this)"$"===q[0]&&b.push({key:q.slice(1),value:this[q]});return b},size:function(){var b=0,q;for(q in this)"$"===q[0]&&++b;return b},empty:function(){for(var b in this)if("$"===b[0])return!1;return!0},each:function(b){for(var m in this)"$"===m[0]&&b(this[m],m.slice(1),this)}};var $b=ob.prototype;me.prototype=yj.prototype= +{constructor:me,has:$b.has,add:function(b){b+="";this["$"+b]=b;return this},remove:$b.remove,clear:$b.clear,values:$b.keys,size:$b.size,empty:$b.empty,each:$b.each};var Aj=Array.prototype.slice,pb=[[],[[[1,1.5],[.5,1]]],[[[1.5,1],[1,1.5]]],[[[1.5,1],[.5,1]]],[[[1,.5],[1.5,1]]],[[[1,1.5],[.5,1]],[[1,.5],[1.5,1]]],[[[1,.5],[1,1.5]]],[[[1,.5],[.5,1]]],[[[.5,1],[1,.5]]],[[[1,1.5],[1,.5]]],[[[.5,1],[1,.5]],[[1.5,1],[1,1.5]]],[[[1.5,1],[1,.5]]],[[[.5,1],[1.5,1]]],[[[1,1.5],[1.5,1]]],[[[.5,1],[1,1.5]]], +[]],Dj={},sg={},ac=ne(","),Zm=ac.parse,Zt=ac.parseRows,$t=ac.format,au=ac.formatBody,bu=ac.formatRows,cu=ac.formatRow,du=ac.formatValue,bc=ne("\t"),$m=bc.parse,eu=bc.parseRows,fu=bc.format,gu=bc.formatBody,hu=bc.formatRows,iu=bc.formatRow,ju=bc.formatValue,ku=(new Date("2019-01-01T00:00")).getHours()||(new Date("2019-07-01T00:00")).getHours(),lu=Ej(Zm),mu=Ej($m),nu=tg("application/xml"),ou=tg("text/html"),pu=tg("image/svg+xml"),Ja=pe.prototype=ug.prototype;Ja.copy=function(){var b=new ug(this._x, +this._y,this._x0,this._y0,this._x1,this._y1),q=this._root,x,v;if(!q)return b;if(!q.length)return b._root=Gj(q),b;for(x=[{source:q,target:b._root=Array(4)}];q=x.pop();)for(var B=0;4>B;++B)if(v=q.source[B])v.length?x.push({source:v,target:q.target[B]=Array(4)}):q.target[B]=Gj(v);return b};Ja.add=function(b){var m=+this._x.call(null,b),x=+this._y.call(null,b);return Fj(this.cover(m,x),m,x,b)};Ja.addAll=function(b){var m,x,v=b.length,B,G,I=Array(v),N=Array(v),E=Infinity,y=Infinity,P=-Infinity,L=-Infinity; +for(x=0;xP&&(P=B),GL&&(L=G));if(E>P||y>L)return this;this.cover(E,y).cover(P,L);for(x=0;xb||b>=B||v>q||q>=G;)switch(y=(qy||(I=U.y0)>P||(N=U.x1)=A)<<1|b>=U)U=L[L.length-1],L[L.length-1]=L[L.length-1-O],L[L.length-1-O]=U}else if(U=b-+this._x.call(null,O.data), +A=q-+this._y.call(null,O.data),U=U*U+A*A,U=(P=(B+I)/2))?B=P:I=P;(U=y>=(L=(G+N)/2))?G=L:N=L;if(!(m=x,x=x[O|=U<<1]))return this;if(!x.length)break;if(m[O+1&3]||m[O+2&3]||m[O+3&3]){var A=m;var f=O}}for(;x.data!==b;)if(!(v= +x,x=x.next))return this;(b=x.next)&&delete x.next;if(v)return b?v.next=b:delete v.next,this;if(!m)return this._root=b,this;b?m[O]=b:delete m[O];(x=m[0]||m[1]||m[2]||m[3])&&x===(m[3]||m[2]||m[1]||m[0])&&!x.length&&(A?A[f]=x:this._root=x);return this};Ja.removeAll=function(b){for(var m=0,x=b.length;m=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i; +ad.prototype=re.prototype;re.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,this.width|0))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};var Mj,Nj={"%":function(b,q){return(100*b).toFixed(q)},b:function(b){return Math.round(b).toString(2)},c:function(b){return b+""},d:function(b){return Math.round(b).toString(10)},e:function(b,q){return b.toExponential(q)}, +f:function(b,q){return b.toFixed(q)},g:function(b,q){return b.toPrecision(q)},o:function(b){return Math.round(b).toString(8)},p:function(b,q){return Ij(100*b,q)},r:Ij,s:function(b,q){var m=qe(b,q);if(!m)return b+"";var v=m[0];m=m[1];m=m-(Mj=3*Math.max(-8,Math.min(8,Math.floor(m/3))))+1;var B=v.length;return m===B?v:m>B?v+Array(m-B+1).join("0"):0b?-1:0},pa=Math.sqrt,tc=Math.tan,Yj={Feature:function(b,q){te(b.geometry,q)},FeatureCollection:function(b,q){b=b.features;for(var m=-1,v=b.length;++mb?Ia+b:b);this.lineStart=this.lineEnd=this.point=la},sphere:function(){vf.add(Ia)}}, +ma,Ma,na,Pa,Tb,gk,hk,oc,bd=new ab,Eb,qb,rb={point:Ag,lineStart:dk,lineEnd:ek,polygonStart:function(){rb.point=fk;rb.lineStart=Uq;rb.lineEnd=Vq;bd.reset();hb.polygonStart()},polygonEnd:function(){hb.polygonEnd();rb.point=Ag;rb.lineStart=dk;rb.lineEnd=ek;0>ve?(ma=-(na=180),Ma=-(Pa=90)):1E-6bd&&(Ma=-90);qb[0]=ma;qb[1]=na},sphere:function(){ma=-(na=180);Ma=-(Pa=90)}},dd,De,Ae,Be,Ce,Ee,Fe,Ge,Cg,Dg,Eg,mk,nk,Fa,Ga,Ha,cb={sphere:la,point:Bg,lineStart:jk,lineEnd:kk,polygonStart:function(){cb.lineStart= +Zq;cb.lineEnd=ar},polygonEnd:function(){cb.lineStart=jk;cb.lineEnd=kk}};Gg.invert=Gg;var Jg=new ab,$g=yk(function(){return!0},function(b){var m=NaN,x=NaN,v=NaN,B;return{lineStart:function(){b.lineStart();B=1},point:function(q,I){var G=0aa(E-Y))b.point(m,x=0<(x+I)/2?ka:-ka),b.point(v,x),b.lineEnd(),b.lineStart(),b.point(G,x),b.point(q,x),B=0;else if(v!==G&&E>=Y){1E-6>aa(m-v)&&(m-=1E-6*v);1E-6>aa(q-G)&&(q-=1E-6*G);E=m;var y=x,P=q,L,O,U=A(E-P);x=1E-6Md&&(Md=b);qxf&&(xf=q)},lineStart:la,lineEnd:la,polygonStart:la,polygonEnd:la,result:function(){var b=[[Ic,wf],[Md,xf]];Md=xf=-(wf=Ic=Infinity);return b}},Qg=0,Rg=0,gd=0,Oe=0,Pe=0,rc=0,Sg=0,Tg=0,hd=0,Ok,Pk,ib,jb,Wa={point:Ub,lineStart:Lk, +lineEnd:Mk,polygonStart:function(){Wa.lineStart=or;Wa.lineEnd=qr},polygonEnd:function(){Wa.point=Ub;Wa.lineStart=Lk;Wa.lineEnd=Mk},result:function(){var b=hd?[Sg/hd,Tg/hd]:rc?[Oe/rc,Pe/rc]:gd?[Qg/gd,Rg/gd]:[NaN,NaN];Qg=Rg=gd=Oe=Pe=rc=Sg=Tg=hd=0;return b}};Qk.prototype={_radius:4.5,pointRadius:function(b){return this._radius=b,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(); +this._point=NaN},point:function(b,q){switch(this._point){case 0:this._context.moveTo(b,q);this._point=1;break;case 1:this._context.lineTo(b,q);break;default:this._context.moveTo(b+this._radius,q),this._context.arc(b,q,this._radius,0,Ia)}},result:la};var Ug=new ab,Yh,Sk,Tk,jd,kd,id={point:la,lineStart:function(){id.point=rr},lineEnd:function(){Yh&&Rk(Sk,Tk);id.point=la},polygonStart:function(){Yh=!0},polygonEnd:function(){Yh=null},result:function(){var b=+Ug;Ug.reset();return b}};Uk.prototype={_radius:4.5, +_circle:Vk(4.5),pointRadius:function(b){(b=+b)!==this._radius&&(this._radius=b,this._circle=null);return this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._string.push("Z");this._point=NaN},point:function(b,q){switch(this._point){case 0:this._string.push("M",b,",",q);this._point=1;break;case 1:this._string.push("L",b,",",q);break;default:null==this._circle&&(this._circle=Vk(this._radius)),this._string.push("M", +b,",",q,this._circle)}},result:function(){if(this._string.length){var b=this._string.join("");this._string=[];return b}return null}};Vg.prototype={constructor:Vg,point:function(b,q){this.stream.point(b,q)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};var sr=M(30*W),vr=ld({point:function(b,q){this.stream.point(b*W,q* +W)}}),Zh=al(function(b){return pa(2/(1+b))});Zh.invert=md(function(b){return 2*Da(b/2)});var $h=al(function(b){return(b=Uj(b))&&b/A(b)});$h.invert=md(function(b){return b});nd.invert=function(b,q){return[b,2*uc(an(q))-ka]};od.invert=od;var Te=pa(3)/2;ch.invert=function(b,q){for(var m=q,v=m*m,B=v*v*v,G=0,I;12>G&&!(I=m*(1.340264+-.081106*v+B*(8.93E-4+.003796*v))-q,v=1.340264+3*-.081106*v+B*(7*8.93E-4+.034164*v),m-=I/=v,v=m*m,B=v*v*v,1E-12>aa(I));++G);return[Te*b*(1.340264+3*-.081106*v+B*(7*8.93E-4+ +.034164*v))/M(m),Da(A(m)/Te)]};dh.invert=md(uc);eh.invert=function(b,q){var m=q,v=25;do{var B=m*m;var G=B*B;m-=G=(m*(1.007226+B*(.015085+G*(-.044475+.028874*B-.005916*G)))-q)/(1.007226+B*(.045255+G*(-.311325+.259866*B-.005916*11*G)))}while(1E-6O;++O){var U=Jb*O/5,A=Math.cos(U);U=Math.sin(U);b.lineTo(U*y,-A*y);b.lineTo(A*E-U*L,U*E+A*L)}b.closePath()}},bo={draw:function(b,y){y=Math.sqrt(y);var E=-y/2;b.rect(E,E,y,y)}},ii=Math.sqrt(3),co={draw:function(b,y){y=-Math.sqrt(y/(3*ii));b.moveTo(0,2*y);b.lineTo(-ii*y,-y);b.lineTo(ii*y,-y);b.closePath()}},Xa=Math.sqrt(3)/2,ji=1/Math.sqrt(12),Rv=3*(ji/2+1),eo={draw:function(b,y){var E=Math.sqrt(y/Rv);y=E/2;var L=E*ji;E=E*ji+E;var O=-y;b.moveTo(y,L);b.lineTo(y,E);b.lineTo(O,E);b.lineTo(-.5* +y-Xa*L,Xa*y+-.5*L);b.lineTo(-.5*y-Xa*E,Xa*y+-.5*E);b.lineTo(-.5*O-Xa*E,Xa*O+-.5*E);b.lineTo(-.5*y+Xa*L,-.5*L-Xa*y);b.lineTo(-.5*y+Xa*E,-.5*E-Xa*y);b.lineTo(-.5*O+Xa*E,-.5*E-Xa*O);b.closePath()}},Sv=[hi,Xn,Zn,bo,ao,co,eo];hf.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN;this._point=0},lineEnd:function(){switch(this._point){case 3:gf(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line|| +0!==this._line&&1===this._point)&&this._context.closePath();this._line=1-this._line},point:function(b,y){b=+b;y=+y;switch(this._point){case 0:this._point=1;this._line?this._context.lineTo(b,y):this._context.moveTo(b,y);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:gf(this,b,y)}this._x0=this._x1;this._x1=b;this._y0=this._y1;this._y1=y}};lm.prototype={areaStart:Hb,areaEnd:Hb,lineStart:function(){this._x0=this._x1= +this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN;this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2);this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3);this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3);this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(b, +y){b=+b;y=+y;switch(this._point){case 0:this._point=1;this._x2=b;this._y2=y;break;case 1:this._point=2;this._x3=b;this._y3=y;break;case 2:this._point=3;this._x4=b;this._y4=y;this._context.moveTo((this._x0+4*this._x1+b)/6,(this._y0+4*this._y1+y)/6);break;default:gf(this,b,y)}this._x0=this._x1;this._x1=b;this._y0=this._y1;this._y1=y}};mm.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN;this._point=0},lineEnd:function(){(this._line|| +0!==this._line&&3===this._point)&&this._context.closePath();this._line=1-this._line},point:function(b,y){b=+b;y=+y;switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var E=(this._x0+4*this._x1+b)/6,L=(this._y0+4*this._y1+y)/6;this._line?this._context.lineTo(E,L):this._context.moveTo(E,L);break;case 3:this._point=4;default:gf(this,b,y)}this._x0=this._x1;this._x1=b;this._y0=this._y1;this._y1=y}};nm.prototype={lineStart:function(){this._x=[];this._y=[];this._basis.lineStart()}, +lineEnd:function(){var b=this._x,y=this._y,P=b.length-1;if(0this._t&&2===this._point&&this._context.lineTo(this._x,this._y);(this._line||0!==this._line&&1===this._point)&&this._context.closePath();0<=this._line&&(this._t=1-this._t,this._line=1-this._line)},point:function(b,l){b=+b;l=+l;switch(this._point){case 0:this._point= +1;this._line?this._context.lineTo(b,l):this._context.moveTo(b,l);break;case 1:this._point=2;default:if(0>=this._t)this._context.lineTo(this._x,l),this._context.lineTo(b,l);else{var f=this._x*(1-this._t)+b*this._t;this._context.lineTo(f,this._y);this._context.lineTo(f,l)}}this._x=b;this._y=l}};mf.prototype={constructor:mf,insert:function(b,l){var f;if(b){l.P=b;if(l.N=b.N)b.N.P=l;b.N=l;if(b.R){for(b=b.R;b.L;)b=b.L;b.L=l}else b.R=l;var n=b}else this._?(b=Cm(this._),l.P=null,l.N=b,b.P=b.L=l,n=b):(l.P= +l.N=null,this._=l,n=null);l.L=l.R=null;l.U=n;l.C=!0;for(b=l;n&&n.C;)l=n.U,n===l.L?(f=l.R)&&f.C?(n.C=f.C=!1,l.C=!0,b=l):(b===n.R&&(Fd(this,n),b=n,n=b.U),n.C=!1,l.C=!0,Gd(this,l)):(f=l.L)&&f.C?(n.C=f.C=!1,l.C=!0,b=l):(b===n.L&&(Gd(this,n),b=n,n=b.U),n.C=!1,l.C=!0,Fd(this,l)),n=b.U;this._.C=!1},remove:function(b){b.N&&(b.N.P=b.P);b.P&&(b.P.N=b.N);b.N=b.P=null;var f=b.U,u=b.L,n=b.R;var r=u?n?Cm(n):u:n;f?f.L===b?f.L=r:f.R=r:this._=r;if(u&&n){var w=r.C;r.C=b.C;r.L=u;u.U=r;r!==n?(f=r.U,r.U=b.U,b=r.R,f.L= +b,r.R=n,n.U=r):(r.U=f,f=r,b=r.R)}else w=b.C,b=r;b&&(b.U=f);if(!w)if(b&&b.C)b.C=!1;else{do{if(b===this._)break;if(b===f.L){if(b=f.R,b.C&&(b.C=!1,f.C=!0,Fd(this,f),b=f.R),b.L&&b.L.C||b.R&&b.R.C){b.R&&b.R.C||(b.L.C=!1,b.C=!0,Gd(this,b),b=f.R);b.C=f.C;f.C=b.R.C=!1;Fd(this,f);b=this._;break}}else if(b=f.L,b.C&&(b.C=!1,f.C=!0,Gd(this,f),b=f.L),b.L&&b.L.C||b.R&&b.R.C){b.L&&b.L.C||(b.R.C=!1,b.C=!0,Fd(this,b),b=f.L);b.C=f.C;f.C=b.L.C=!1;Gd(this,f);b=this._;break}b.C=!0;b=f;f=f.U}while(!b.C);b&&(b.C=!1)}}}; +var Em=[],Ph,Gm=[],ea=1E-6,wt=1E-12,Ec,Ra,Jd,xa;Rh.prototype={constructor:Rh,polygons:function(){var b=this.edges;return this.cells.map(function(f){var l=f.halfedges.map(function(l){return Dm(f,b[l])});l.data=f.site.data;return l})},triangles:function(){var b=[],l=this.edges;this.cells.forEach(function(f,n){if(u=(r=f.halfedges).length){f=f.site;var r,w=-1,u,F=l[r[u-1]];for(F=F.left===f?F.right:F.left;++w(f[0]-F[0])*(C[1]- +f[1])-(f[0]-C[0])*(F[1]-f[1])&&b.push([f.data,C.data,F.data])}}});return b},links:function(){return this.edges.filter(function(b){return b.right}).map(function(b){return{source:b.left.data,target:b.right.data}})},find:function(b,l,u){var f=this,r=f._found||0;var w=f.cells.length;for(var D;!(D=f.cells[r]);)if(++r>=w)return null;w=b-D.site[0];var F=l-D.site[1],C=w*w+F*F;do D=f.cells[w=r],r=null,D.halfedges.forEach(function(n){var w=f.edges[n];n=w.left;if(n!==D.site&&n||(n=w.right)){w=b-n[0];var u=l- +n[1];w=w*w+u*u;wJ;C||(C=b=Bb());if(HJb-1E-12)C.moveTo(H*dc(J),H*lb(J)),C.arc(0,0,H,J,K,!T),1E-12aa*aa?ua=void 0:(aa=(M*(K-Zc)-ba*(J-Ab))/aa,ua=[J+aa*ua,K+ +aa*Q]);Q=ua}Q&&(V=J-ua[0],oa=K-ua[1],Q=Ab-ua[0],M=Zc-ua[1],V=(V*Q+oa*M)/(zc(V*V+oa*oa)*zc(Q*Q+M*M)),oa=1/lb((1V?Ib:Math.acos(V))/2),ua=zc(ua[0]*ua[0]+ua[1]*ua[1]),V=gi(W,(f-ua)/(oa-1)),oa=gi(W,(H-ua)/(oa+1)))}1E-12>J,u=+F(b,l,r)+K>>J;b=+C(b,l,r);0<=n&&n>J);rg({width:Q,height:T,data:r},{width:Q,height:T,data:f},H>>J);qg({width:Q,height:T,data:f},{width:Q,height:T,data:r},H>>J);rg({width:Q,height:T,data:r},{width:Q,height:T,data:f},H>> +J);qg({width:Q,height:T,data:f},{width:Q,height:T,data:r},H>>J);rg({width:Q,height:T,data:r},{width:Q,height:T,data:f},H>>J);b=fa(f);Array.isArray(b)||(r=oi(f),b=Kb(0,r,b),b=Na(0,Math.floor(r/b)*b,b),b.shift());return zj().thresholds(b).size([Q,T])(f).map(l)}function l(b){b.value*=Math.pow(2,-2*J);b.coordinates.forEach(u);return b}function u(b){b.forEach(n)}function n(b){b.forEach(r)}function r(b){b[0]=b[0]*Math.pow(2,J)-K;b[1]=b[1]*Math.pow(2,J)-K}function w(){K=3*H;Q=R+2*K>>J;T=S+2*K>>J;return b} +var D=zq,F=Aq,C=Bq,R=960,S=500,H=20,J=2,K=3*H,Q=R+2*K>>J,T=S+2*K>>J,fa=Cb(20);b.x=function(f){return arguments.length?(D="function"===typeof f?f:Cb(+f),b):D};b.y=function(f){return arguments.length?(F="function"===typeof f?f:Cb(+f),b):F};b.weight=function(f){return arguments.length?(C="function"===typeof f?f:Cb(+f),b):C};b.size=function(b){if(!arguments.length)return[R,S];var f=Math.ceil(b[0]),l=Math.ceil(b[1]);if(!(0<=f||0<=f))throw Error("invalid size");return R=f,S=l,w()};b.cellSize=function(b){if(!arguments.length)return 1<< +J;if(!(1<=(b=+b)))throw Error("invalid cell size");return J=Math.floor(Math.log(b)/Math.LN2),w()};b.thresholds=function(f){return arguments.length?(fa="function"===typeof f?f:Array.isArray(f)?Cb(Aj.call(f)):Cb(f),b):fa};b.bandwidth=function(b){if(!arguments.length)return Math.sqrt(H*(H+1));if(!(0<=(b=+b)))throw Error("invalid bandwidth");return H=Math.round((Math.sqrt(4*b*b+1)-1)/2),w()};return b};b.contours=zj;b.create=function(b){return Ka(Rd(b).call(document.documentElement))};b.creator=Rd;b.cross= +function(b,l,u){var f=b.length,r=l.length,w=Array(f*r),D,F,C;null==u&&(u=li);for(D=C=0;Db?1:l>=b?0:NaN}; +b.deviation=ni;b.dispatch=Lb;b.drag=function(){function f(b){b.on("mousedown.drag",l).filter(H).on("touchstart.drag",r).on("touchmove.drag",w).on("touchend.drag touchcancel.drag",D).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function l(){if(!Z&&C.apply(this,arguments)){var f=F("mouse",R.apply(this,arguments),Ob,this,arguments);f&&(Ka(b.event.view).on("mousemove.drag",u,!0).on("mouseup.drag",n,!0),Vd(b.event.view),b.event.stopImmediatePropagation(),A=!1,T=b.event.clientX, +fa=b.event.clientY,f("start"))}}function u(){ec();if(!A){var f=b.event.clientX-T,l=b.event.clientY-fa;A=f*f+l*l>M}J.mouse("drag")}function n(){Ka(b.event.view).on("mousemove.drag mouseup.drag",null);Wd(b.event.view,A);ec();J.mouse("end")}function r(){if(C.apply(this,arguments)){var f=b.event.changedTouches,l=R.apply(this,arguments),r=f.length,n,u;for(n=0;n=(b*=2)?1-Xc(1-b):Xc(b-1)+1)/2};b.easeBounceOut=Xc;b.easeCircle=rj;b.easeCircleIn=function(b){return 1-Math.sqrt(1-b*b)};b.easeCircleInOut=rj;b.easeCircleOut=function(b){return Math.sqrt(1- --b*b)};b.easeCubic=gg;b.easeCubicIn=function(b){return b*b*b};b.easeCubicInOut=gg;b.easeCubicOut=function(b){return--b*b*b+1};b.easeElastic=Tm;b.easeElasticIn=Tt;b.easeElasticInOut=Ut;b.easeElasticOut=Tm;b.easeExp=qj;b.easeExpIn=function(b){return Math.pow(2,10* +b-10)};b.easeExpInOut=qj;b.easeExpOut=function(b){return 1-Math.pow(2,-10*b)};b.easeLinear=function(b){return+b};b.easePoly=Qm;b.easePolyIn=Pt;b.easePolyInOut=Qm;b.easePolyOut=Qt;b.easeQuad=nj;b.easeQuadIn=function(b){return b*b};b.easeQuadInOut=nj;b.easeQuadOut=function(b){return b*(2-b)};b.easeSin=oj;b.easeSinIn=function(b){return 1-Math.cos(b*Rm)};b.easeSinInOut=oj;b.easeSinOut=function(b){return Math.sin(b*Rm)};b.entries=function(b){var f=[],u;for(u in b)f.push({key:u,value:b[u]});return f};b.extent= +Bf;b.forceCenter=function(b,l){function f(){var f,u=n.length,D=0,F=0;for(f=0;fJ.index&&(f=K-u.x-u.vx,l=Q-u.y-u.vy,r=f*f+l*l,rK+w||rQ+w||nf;++f)b[f]&&b[f].r>b.r&&(b.r=b[f].r)}function n(){if(r){var f,l=r.length;w=Array(l);for(f=0;fF;++F)(l=b[F])&&(r=Math.abs(l.value))&&(f+=l.value,n+=r,u+=r*l.x,w+=r*l.y); +b.x=u/n;b.y=w/n}else{l=b;l.x=l.data.x;l.y=l.data.y;do f+=C[l.data.index];while(l=l.next)}b.value=f}function n(b,f,l,r){if(!b.value)return!0;l=b.x-w.x;var n=b.y-w.y;f=r-f;r=l*l+n*n;if(f*f/H=S)){if(b.data!==w||b.next)0===l&&(l=Db(),r+=l*l),0===n&&(n=Db(),r+=n*n),rf&&-.425<=n&&-.214>n?D:.166<=f&&.234>f&&-.214<=n&&-.115>n?C:r).invert(b)};b.stream=function(b){return u&&n===b?u:u=xr([r.stream(n=b),D.stream(b),C.stream(b)])};b.precision=function(b){if(!arguments.length)return r.precision();r.precision(b);D.precision(b);C.precision(b);return l()};b.scale=function(f){if(!arguments.length)return r.scale();r.scale(f);D.scale(.35*f);C.scale(f);return b.translate(r.translate())};b.translate=function(b){if(!arguments.length)return r.translate(); +var f=r.scale(),n=+b[0],u=+b[1];w=r.translate(b).clipExtent([[n-.455*f,u-.238*f],[n+.455*f,u+.238*f]]).stream(H);F=D.translate([n-.307*f,u+.201*f]).clipExtent([[n-.425*f+1E-6,u+.12*f+1E-6],[n-.214*f-1E-6,u+.234*f-1E-6]]).stream(H);R=C.translate([n-.205*f,u+.212*f]).clipExtent([[n-.214*f+1E-6,u+.166*f+1E-6],[n-.115*f-1E-6,u+.234*f-1E-6]]).stream(H);return l()};b.fitExtent=function(f,l){return sc(b,f,l)};b.fitSize=function(f,l){return sc(b,[[0,0],f],l)};b.fitWidth=function(f,l){return Xg(b,f,l)};b.fitHeight= +function(f,l){return Yg(b,f,l)};return b.scale(1070)};b.geoArea=function(b){vf.reset();bb(b,hb);return 2*vf};b.geoAzimuthalEqualArea=function(){return kb(Zh).scale(124.75).clipAngle(179.999)};b.geoAzimuthalEqualAreaRaw=Zh;b.geoAzimuthalEquidistant=function(){return kb($h).scale(79.4188).clipAngle(179.999)};b.geoAzimuthalEquidistantRaw=$h;b.geoBounds=function(b){var f,u,n;Pa=na=-(ma=Ma=Infinity);Eb=[];bb(b,rb);if(f=Eb.length){Eb.sort(Wq);b=1;var r=Eb[0];for(u=[r];bQa(r[0],r[1])&&(r[1]=w[1]),Qa(w[0],r[1])>Qa(r[0],r[1])&&(r[0]=w[0])):u.push(r=w)}var D=-Infinity;f=u.length-1;b=0;for(r=u[f];b<=f;r=w,++b)w=u[b],(n=Qa(r[1],w[0]))>D&&(D=n,ma=w[0],na=r[1])}Eb=qb=null;return Infinity===ma||Infinity===Ma?[[NaN,NaN],[NaN,NaN]]:[[ma,Ma],[na,Pa]]};b.geoCentroid=function(b){dd=De=Ae=Be=Ce=Ee=Fe=Ge=Cg=Dg=Eg=0;bb(b,cb);b=Cg;var f=Dg,u=Eg,n=b*b+f*f+u*u;return 1E-12>n&&(b=Ee,f=Fe,u=Ge,1E-6>De&&(b=Ae,f=Be,u=Ce),n=b*b+f*f+u*u,1E-12>n)?[NaN,NaN]:[Ea(f,b)*ha, +Da(u/pa(n))*ha]};b.geoCircle=function(){function b(){var b=l.apply(this,arguments),f=u.apply(this,arguments)*W,R=n.apply(this,arguments)*W;r=[];w=Hg(-b[0]*W,-b[1]*W,0).invert;sk(D,f,R,1);b={type:"Polygon",coordinates:[r]};r=w=null;return b}var l=pc([0,0]),u=pc(90),n=pc(6),r,w,D={point:function(b,f){r.push(b=w(b,f));b[0]*=ha;b[1]*=ha}};b.center=function(f){return arguments.length?(l="function"===typeof f?f:pc([+f[0],+f[1]]),b):l};b.radius=function(f){return arguments.length?(u="function"===typeof f? +f:pc(+f),b):u};b.precision=function(f){return arguments.length?(n="function"===typeof f?f:pc(+f),b):n};return b};b.geoClipAntimeridian=$g;b.geoClipCircle=zk;b.geoClipExtent=function(){var b=0,l=0,u=960,n=500,r,w,D;return D={stream:function(f){return r&&w===f?r:r=Je(b,l,u,n)(w=f)},extent:function(f){return arguments.length?(b=+f[0][0],l=+f[0][1],u=+f[1][0],n=+f[1][1],r=w=null,D):[[b,l],[u,n]]}}};b.geoClipRectangle=Je;b.geoConicConformal=function(){return ah(cl).scale(109.5).parallels([30,30])};b.geoConicConformalRaw= +cl;b.geoConicEqualArea=Re;b.geoConicEqualAreaRaw=Zk;b.geoConicEquidistant=function(){return ah(dl).scale(131.154).center([0,13.9389])};b.geoConicEquidistantRaw=dl;b.geoContains=function(b,l){return(b&&bn.hasOwnProperty(b.type)?bn[b.type]:Me)(b,l)};b.geoDistance=ed;b.geoEqualEarth=function(){return kb(ch).scale(177.158)};b.geoEqualEarthRaw=ch;b.geoEquirectangular=function(){return kb(od).scale(152.63)};b.geoEquirectangularRaw=od;b.geoGnomonic=function(){return kb(dh).scale(144.049).clipAngle(60)}; +b.geoGnomonicRaw=dh;b.geoGraticule=Hk;b.geoGraticule10=function(){return Hk()()};b.geoIdentity=function(){function b(){Q=u*w;T=u*D;Z=V=null;return l}function l(b){var f=b[0]*Q;b=b[1]*T;if(F){var l=b*C-f*R;f=f*C+b*R;b=l}return[f+n,b+r]}var u=1,n=0,r=0,w=1,D=1,F=0,C,R,S=null,H,J,K,Q=1,T=1,fa=ld({point:function(b,f){b=l([b,f]);this.stream.point(b[0],b[1])}}),X=fd,Z,V;l.invert=function(b){var f=b[0]-n;b=b[1]-r;if(F){var l=b*C+f*R;f=f*C-b*R;b=l}return[f/Q,b/T]};l.stream=function(b){return Z&&V===b?Z:Z= +fa(X(V=b))};l.postclip=function(f){return arguments.length?(X=f,S=H=J=K=null,b()):X};l.clipExtent=function(f){return arguments.length?(X=null==f?(S=H=J=K=null,fd):Je(S=+f[0][0],H=+f[0][1],J=+f[1][0],K=+f[1][1]),b()):null==S?null:[[S,H],[J,K]]};l.scale=function(f){return arguments.length?(u=+f,b()):u};l.translate=function(f){return arguments.length?(n=+f[0],r=+f[1],b()):[n,r]};l.angle=function(f){return arguments.length?(F=f%360*W,R=A(F),C=M(F),b()):F*ha};l.reflectX=function(f){return arguments.length? +(w=f?-1:1,b()):0>w};l.reflectY=function(f){return arguments.length?(D=f?-1:1,b()):0>D};l.fitExtent=function(b,f){return sc(l,b,f)};l.fitSize=function(b,f){return sc(l,[[0,0],b],f)};l.fitWidth=function(b,f){return Xg(l,b,f)};l.fitHeight=function(b,f){return Yg(l,b,f)};return l};b.geoInterpolate=function(b,l){var f=b[0]*W,n=b[1]*W;b=l[0]*W;l=l[1]*W;var r=M(n),w=A(n),D=M(l),F=A(l),C=r*M(f),R=r*A(f),S=D*M(b),H=D*A(b),J=2*Da(pa(Vj(l-n)+r*D*Vj(b-f))),K=A(J);b=J?function(b){var f=A(b*=J)/K,l=A(J-b)/K;b= +l*C+f*S;var r=l*R+f*H;f=l*w+f*F;return[Ea(r,b)*ha,Ea(f,pa(b*b+r*r))*ha]}:function(){return[f*ha,n*ha]};b.distance=J;return b};b.geoLength=Ak;b.geoMercator=function(){return bl(nd).scale(961/Ia)};b.geoMercatorRaw=nd;b.geoNaturalEarth1=function(){return kb(eh).scale(175.295)};b.geoNaturalEarth1Raw=eh;b.geoOrthographic=function(){return kb(fh).scale(249.5).clipAngle(90.000001)};b.geoOrthographicRaw=fh;b.geoPath=function(b,l){function f(b){b&&("function"===typeof n&&w.pointRadius(+n.apply(this,arguments)), +bb(b,r(w)));return w.result()}var n=4.5,r,w;f.area=function(b){bb(b,r(sb));return sb.result()};f.measure=function(b){bb(b,r(id));return id.result()};f.bounds=function(b){bb(b,r(Qe));return Qe.result()};f.centroid=function(b){bb(b,r(Wa));return Wa.result()};f.projection=function(l){return arguments.length?(r=null==l?(b=null,fd):(b=l).stream,f):b};f.context=function(b){if(!arguments.length)return l;w=null==b?(l=null,new Uk):new Qk(l=b);"function"!==typeof n&&w.pointRadius(n);return f};f.pointRadius= +function(b){if(!arguments.length)return n;n="function"===typeof b?b:(w.pointRadius(+b),+b);return f};return f.projection(b).context(l)};b.geoProjection=kb;b.geoProjectionMutator=Zg;b.geoRotation=rk;b.geoStereographic=function(){return kb(gh).scale(250).clipAngle(142)};b.geoStereographicRaw=gh;b.geoStream=bb;b.geoTransform=function(b){return{stream:ld(b)}};b.geoTransverseMercator=function(){var b=bl(hh),l=b.center,u=b.rotate;b.center=function(b){return arguments.length?l([-b[1],b[0]]):(b=l(),[b[1], +-b[0]])};b.rotate=function(b){return arguments.length?u([b[0],b[1],2R;)A.pop(),--H;var J=Array(H+1);for(f=0;f<=H;++f){var K=J[f]=[];K.x0=0b||1=u.length)return null!=r&&f.sort(r),null!=w?w(f):f;for(var C=-1,F=f.length,A=u[l++],R,S,M=ob(),X,Z=n();++Cu.length)return b;var r=n[f-1];if(null!=w&&f>=u.length)var C=b.entries();else C=[],b.each(function(b,r){C.push({key:r,values:l(b,f)})});return null!=r?C.sort(function(b,f){return r(b.key,f.key)}):C}var u=[],n=[],r,w,D;return D={object:function(f){return b(f, +0,vq,wq)},map:function(f){return b(f,0,wj,xj)},entries:function(f){return l(b(f,0,wj,xj),0)},key:function(b){u.push(b);return D},sortKeys:function(b){n[u.length-1]=b;return D},sortValues:function(b){r=b;return D},rollup:function(b){w=b;return D}}};b.now=ic;b.pack=function(){function b(b){b.x=u/2;b.y=n/2;l?b.eachBefore(ml(l)).eachAfter(kh(r,.5)).eachBefore(nl(1)):b.eachBefore(ml(Hr)).eachAfter(kh(Vb,1)).eachAfter(kh(r,b.r/Math.min(u,n))).eachBefore(nl(Math.min(u,n)/(2*b.r)));return b}var l=null,u= +1,n=1,r=Vb;b.radius=function(f){return arguments.length?(l=null==f?null:We(f),b):l};b.size=function(f){return arguments.length?(u=+f[0],n=+f[1],b):[u,n]};b.padding=function(f){return arguments.length?(r="function"===typeof f?f:wc(+f),b):r};return b};b.packEnclose=fl;b.packSiblings=function(b){ll(b);return b};b.pairs=function(b,l){null==l&&(l=li);for(var f=0,n=b.length-1,r=b[0],w=Array(0>n?0:n);fQ?-1:1),X;for(f=0;fn?0:n);fl!==D>l&&r<(w-F)*(l-n)/(D-n)+F&&(C=!C),w=F,D=n;return C};b.polygonHull=function(b){if(3>(u=b.length))return null;var f,u,n=Array(u),r=Array(u);for(f=0;fl(w=b[n],D)||0!==l(D,D))D=w,r=n;if(0===l(D,D))return r}};b.schemeAccent=Wu;b.schemeBlues=Qn;b.schemeBrBG=vn;b.schemeBuGn=En;b.schemeBuPu=Fn;b.schemeCategory10=Vu;b.schemeDark2=Xu;b.schemeGnBu=Gn;b.schemeGreens=Rn;b.schemeGreys=Sn;b.schemeOrRd=Hn;b.schemeOranges=Vn;b.schemePRGn=wn;b.schemePaired=Yu;b.schemePastel1=Zu;b.schemePastel2=$u;b.schemePiYG=xn;b.schemePuBu=Jn;b.schemePuBuGn= +In;b.schemePuOr=yn;b.schemePuRd=Kn;b.schemePurples=Tn;b.schemeRdBu=zn;b.schemeRdGy=An;b.schemeRdPu=Ln;b.schemeRdYlBu=Bn;b.schemeRdYlGn=Cn;b.schemeReds=Un;b.schemeSet1=av;b.schemeSet2=bv;b.schemeSet3=cv;b.schemeSpectral=Dn;b.schemeTableau10=dv;b.schemeYlGn=Nn;b.schemeYlGnBu=Mn;b.schemeYlOrBr=On;b.schemeYlOrRd=Pn;b.select=Ka;b.selectAll=function(b){return"string"===typeof b?new za([document.querySelectorAll(b)],[document.documentElement]):new za([null==b?[]:b],Of)};b.selection=Nb;b.selector=Sd;b.selectorAll= +Kf;b.set=yj;b.shuffle=function(b,l,u){u=(null==u?b.length:u)-(l=null==l?0:+l);for(var f,r;u;)r=Math.random()*u--|0,f=b[u+l],b[u+l]=b[r+l],b[r+l]=f;return b};b.stack=function(){function b(b){var f=l.apply(this,arguments),w,C=b.length,A=f.length,S=Array(A);for(w=0;ww?(r[1]=F,r[0]=F+=w):(r[0]=0,r[1]= +w)};b.stackOffsetExpand=function(b,l){if(0<(n=b.length)){for(var f,n,r=0,w=b[0].length,D;rF.x&&(F=b);b.depth>J.depth&&(J=b)});f=C===F?1:r(C,F)/2;var K=f-C.x,Q=w/(F.x+f+K),T=D/(J.depth||1);b.eachBefore(function(b){b.x=(b.x+K)*Q;b.y=b.depth*T})}return b}function l(b){var f=b.children,l=b.parent.children,n=b.i?l[b.i-1]:null; +if(f){for(var u=0,w=0,C=b.children,D=C.length,A;0<=--D;)A=C[D],A.z+=u,A.m+=u,u+=A.s+(w+=A.c);f=(f[0].z+f[f.length-1].z)/2;n?(b.z=n.z+r(b._,n._),b.m=b.z-f):b.z=f}else n&&(b.z=n.z+r(b._,n._));f=b.parent;l=b.parent.A||l[0];if(n){w=u=b;C=u.parent.children[0];D=u.m;A=w.m;for(var F=n.m,M=C.m,W;n=mh(n),u=lh(u),n&&u;){C=lh(C);w=mh(w);w.a=b;W=n.z+F-u.z-D+r(n._,u._);if(0=l-1)b=A[b],b.x0=r,b.y0=u,b.x1=w,b.y1=D;else{for(var C=S[b],F=n/2+C,H=b+1,J=l-1;H>>1;S[K]D-u?(n=(r*F+w*C)/n,f(b,H,C,r,u,n,D),f(H,l,F,n,u,w,D)):(n=(u*F+D*C)/n,f(b,H, +C,r,u,w,n),f(H,l,F,r,n,w,D))}}var A=b.children,F,C=A.length,M,S=Array(C+1);for(S[0]=M=F=0;Fha}f.zoom("mouse",T(u(f.that.__zoom,f.mouse[0]=Ob(f.that),f.mouse[1]),f.extent,Y))},!0).on("mouseup.zoom",function(){l.on("mousemove.zoom mouseup.zoom",null);Wd(b.event.view,f.moved);Kd();f.end()},!0),n=Ob(this),r=b.event.clientX,A=b.event.clientY;Vd(b.event.view);b.event.stopImmediatePropagation();f.mouse=[n,this.__zoom.invert(n)];Rb(this);f.start()}}function M(){if(K.apply(this,arguments)){var n=this.__zoom, +w=Ob(this),A=n.invert(w);n=T(u(l(n,n.k*(b.event.shiftKey?.5:2)),w,A),Q.apply(this,arguments),Y);Kd();0n.taps&&(da=setTimeout(function(){da=null},500)),Rb(this),n.start())}}function H(){if(this.__zooming){var f=w(this,arguments),n=b.event.changedTouches,r=n.length,A;Kd();da&&(da=clearTimeout(da));for(A=f.taps=0;A to be set while inserting or modifying + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/views/agendas.vue b/src/main/webapp/assets/js/views/agendas.vue new file mode 100644 index 0000000..baadb02 --- /dev/null +++ b/src/main/webapp/assets/js/views/agendas.vue @@ -0,0 +1,204 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/views/createDebate.vue b/src/main/webapp/assets/js/views/createDebate.vue new file mode 100644 index 0000000..24cd605 --- /dev/null +++ b/src/main/webapp/assets/js/views/createDebate.vue @@ -0,0 +1,283 @@ + + + diff --git a/src/main/webapp/assets/js/views/debate.vue b/src/main/webapp/assets/js/views/debate.vue new file mode 100644 index 0000000..95b785a --- /dev/null +++ b/src/main/webapp/assets/js/views/debate.vue @@ -0,0 +1,615 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/views/debates.vue b/src/main/webapp/assets/js/views/debates.vue new file mode 100644 index 0000000..ca7a75b --- /dev/null +++ b/src/main/webapp/assets/js/views/debates.vue @@ -0,0 +1,91 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/views/document.vue b/src/main/webapp/assets/js/views/document.vue new file mode 100644 index 0000000..4ace7bf --- /dev/null +++ b/src/main/webapp/assets/js/views/document.vue @@ -0,0 +1,110 @@ + + + diff --git a/src/main/webapp/assets/js/views/documents.vue b/src/main/webapp/assets/js/views/documents.vue new file mode 100644 index 0000000..71625ac --- /dev/null +++ b/src/main/webapp/assets/js/views/documents.vue @@ -0,0 +1,140 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/views/home.vue b/src/main/webapp/assets/js/views/home.vue new file mode 100644 index 0000000..e15826f --- /dev/null +++ b/src/main/webapp/assets/js/views/home.vue @@ -0,0 +1,154 @@ +. + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/views/restitution.vue b/src/main/webapp/assets/js/views/restitution.vue new file mode 100644 index 0000000..bc500c9 --- /dev/null +++ b/src/main/webapp/assets/js/views/restitution.vue @@ -0,0 +1,97 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/views/sondage.vue b/src/main/webapp/assets/js/views/sondage.vue new file mode 100644 index 0000000..f6fd2b0 --- /dev/null +++ b/src/main/webapp/assets/js/views/sondage.vue @@ -0,0 +1,285 @@ + + + diff --git a/src/main/webapp/assets/js/views/sondages.vue b/src/main/webapp/assets/js/views/sondages.vue new file mode 100644 index 0000000..c4c3d53 --- /dev/null +++ b/src/main/webapp/assets/js/views/sondages.vue @@ -0,0 +1,472 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/views/team.vue b/src/main/webapp/assets/js/views/team.vue new file mode 100644 index 0000000..e178b31 --- /dev/null +++ b/src/main/webapp/assets/js/views/team.vue @@ -0,0 +1,79 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/views/teams.vue b/src/main/webapp/assets/js/views/teams.vue new file mode 100644 index 0000000..8e2be3a --- /dev/null +++ b/src/main/webapp/assets/js/views/teams.vue @@ -0,0 +1,208 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/views/updateTags.vue b/src/main/webapp/assets/js/views/updateTags.vue new file mode 100644 index 0000000..6334594 --- /dev/null +++ b/src/main/webapp/assets/js/views/updateTags.vue @@ -0,0 +1,63 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/assets/js/vueCfg.js b/src/main/webapp/assets/js/vueCfg.js new file mode 100644 index 0000000..57031e8 --- /dev/null +++ b/src/main/webapp/assets/js/vueCfg.js @@ -0,0 +1,63 @@ +/***** Register Vue components *****/ +Vue.component('base-layout', vueLoader('layouts/baseLayout')); +Vue.component('grid-layout', vueLoader('layouts/gridLayout')); +Vue.component('modal-layout', vueLoader('layouts/modalLayout')); +Vue.component('tabs-layout', vueLoader('layouts/tabsLayout')); +Vue.component('institution-select', vueLoader('components/widgets/institutionSelect')); +Vue.component('tooltiped', vueLoader('components/widgets/tooltiped')); +Vue.component('documented', vueLoader('components/widgets/documented')); +Vue.component('search-box', vueLoader('components/widgets/searchBox')); +Vue.component('action-button', vueLoader('components/widgets/actionButton')); +Vue.component('toggle-action-button', vueLoader('components/widgets/toggleActionButton')); +Vue.component('text-input', vueLoader('components/widgets/textInput')); + +const VueModal = { + data() { + return { + callback: false + }; + }, + methods: { + open(callback) { + if (callback) { + this.callback = callback; + } + this.$children[0].open = true; + this.$emit('open'); + if (this.afterOpen) { + this.afterOpen( ); + } + }, + close(returnValue = false) { + this.$children[0].open = false; + this.$emit('close'); + if (this.callback) { + this.callback(returnValue); + } + if (this.afterClose) { + this.afterClose( ); + } + }, + isOpen() { + return this.$children[0].open; + } + } +}; + +const VueGrid = { + methods: { + getRowById(id) { + let row = this.$children[0].$refs[id]; + if (Array.isArray(row)) { + return row[0]; + } + return row; + }, + selectRow(id) { + let row = this.getRowById(id); + let el = row.querySelector("[tabindex]"); + el.focus(); + scrollCenter(document.documentElement, el); + } + } +}; diff --git a/src/main/webapp/assets/js/vueCfg.min.js b/src/main/webapp/assets/js/vueCfg.min.js new file mode 100644 index 0000000..560fe14 --- /dev/null +++ b/src/main/webapp/assets/js/vueCfg.min.js @@ -0,0 +1,4 @@ +Vue.component("base-layout",vueLoader("layouts/baseLayout"));Vue.component("grid-layout",vueLoader("layouts/gridLayout"));Vue.component("modal-layout",vueLoader("layouts/modalLayout"));Vue.component("tabs-layout",vueLoader("layouts/tabsLayout"));Vue.component("institution-select",vueLoader("components/widgets/institutionSelect"));Vue.component("tooltiped",vueLoader("components/widgets/tooltiped"));Vue.component("documented",vueLoader("components/widgets/documented"));Vue.component("search-box",vueLoader("components/widgets/searchBox")); +Vue.component("action-button",vueLoader("components/widgets/actionButton"));Vue.component("toggle-action-button",vueLoader("components/widgets/toggleActionButton"));Vue.component("text-input",vueLoader("components/widgets/textInput")); +const VueModal={data(){return{callback:!1}},methods:{open(a){a&&(this.callback=a);this.$children[0].open=!0;this.$emit("open");this.afterOpen&&this.afterOpen()},close(a=!1){this.$children[0].open=!1;this.$emit("close");this.callback&&this.callback(a);this.afterClose&&this.afterClose()},isOpen(){return this.$children[0].open}}},VueGrid={methods:{getRowById(a){a=this.$children[0].$refs[a];return Array.isArray(a)?a[0]:a},selectRow(a){a=this.getRowById(a).querySelector("[tabindex]");a.focus();scrollCenter(document.documentElement, +a)}}}; \ No newline at end of file diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp new file mode 100644 index 0000000..d859dbd --- /dev/null +++ b/src/main/webapp/index.jsp @@ -0,0 +1,350 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page language="java" import="java.util.*" %> +<%@ page import = "java.util.ResourceBundle" %> +<% ResourceBundle resource = ResourceBundle.getBundle("application"); + String productionMode = resource.getString("production"); + String serverRoot = resource.getString("reverse-proxy"); + if (serverRoot.length() == 0) { + serverRoot = request.getRequestURL().substring(0, request.getRequestURL().length() - "/index.jsp".length()); + } + boolean canMail = resource.getString("smtp.server").length() > 0;%> + + + + + + + + + + + Plateforme AREN + + + + + + <% if (productionMode.equals("true")) {%> + + + + + + + + + + + + + + + + + + + + + <% } else { %> + + + + + + + + + + + + + + + + + + + + + <% }%> + + + + +
+ + +
+
+
+ +
+ +
+ + + + + + + + + + + + +
+ + + + + \ No newline at end of file