From b6e1526f892caa6a818071816449ff95b22bf502 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Wed, 3 May 2017 18:48:27 +0200 Subject: [PATCH 01/45] Fix #239, (refresh is needed to load charts) --- app/views/stats/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/stats/index.html.haml b/app/views/stats/index.html.haml index 88e596ab4..b6c0fd893 100644 --- a/app/views/stats/index.html.haml +++ b/app/views/stats/index.html.haml @@ -1,4 +1,4 @@ -= javascript_include_tag 'https://code.highcharts.com/highcharts.js', 'chartkick' += javascript_include_tag 'https://code.highcharts.com/highcharts.js', 'chartkick', "data-turbolinks-track" => true .statistiques From 988947696e3ef24ca0dd653e37ae742f1775399e Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Tue, 2 May 2017 09:48:25 +0200 Subject: [PATCH 02/45] [Fix #161] Remove incorrect commas from Dossier#text_summary --- app/models/dossier.rb | 6 +++--- spec/controllers/users/dossiers_controller_spec.rb | 2 +- spec/models/dossier_spec.rb | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 17c7bf03e..ac11f9fc6 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -283,16 +283,16 @@ class Dossier < ActiveRecord::Base parts = [ "Dossier en brouillon répondant à la démarche ", procedure.libelle, - ", gérée par l'organisme ", + " gérée par l'organisme ", procedure.organisation ] else parts = [ "Dossier déposé le ", initiated_at.strftime("%d/%m/%Y"), - ", sur la démarche ", + " sur la démarche ", procedure.libelle, - ", gérée par l'organisme ", + " gérée par l'organisme ", procedure.organisation ] end diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index f479f6eb9..31188c207 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -563,7 +563,7 @@ describe Users::DossiersController, type: :controller do context 'when the dossier exist' do before { get :text_summary, params: { dossier_id: dossier.id } } it 'returns the procedure name' do - expect(JSON.parse(response.body)).to eq("textSummary" => "Dossier en brouillon répondant à la démarche #{procedure.libelle}, gérée par l'organisme #{procedure.organisation}") + expect(JSON.parse(response.body)).to eq("textSummary" => "Dossier en brouillon répondant à la démarche #{procedure.libelle} gérée par l'organisme #{procedure.organisation}") end end diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 576949f7b..617071c24 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -817,7 +817,7 @@ describe Dossier do subject { dossier.text_summary } - it { is_expected.to eq("Dossier déposé le 31/12/2010, sur la démarche Démarche, gérée par l'organisme Organisation") } + it { is_expected.to eq("Dossier déposé le 31/12/2010 sur la démarche Démarche gérée par l'organisme Organisation") } end context 'when the dossier has not been initiated' do @@ -825,7 +825,7 @@ describe Dossier do subject { dossier.text_summary } - it { is_expected.to eq("Dossier en brouillon répondant à la démarche Démarche, gérée par l'organisme Organisation") } + it { is_expected.to eq("Dossier en brouillon répondant à la démarche Démarche gérée par l'organisme Organisation") } end end From 4ce6c9239472601ca49a69677575b8417609330f Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 26 Apr 2017 12:44:32 +0200 Subject: [PATCH 03/45] Reformat the _render_list_champs template test --- .../_render_list_champs.html.haml_spec.rb | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/spec/views/users/description/champs/_render_list_champs.html.haml_spec.rb b/spec/views/users/description/champs/_render_list_champs.html.haml_spec.rb index b5a74ed58..4e8982faf 100644 --- a/spec/views/users/description/champs/_render_list_champs.html.haml_spec.rb +++ b/spec/views/users/description/champs/_render_list_champs.html.haml_spec.rb @@ -1,27 +1,29 @@ describe 'users/description/champs/render_list_champs.html.haml', type: :view do let(:type_champ) { create(:type_de_champ_public, :checkbox) } - context "with a checkbox champ with value equals nil" do - let!(:champ_checkbox_checked) { create(:champ, type_de_champ: type_champ, value: nil) } + context "with a checkbox champ" do + context "whose value equals nil" do + let!(:champ_checkbox_checked) { create(:champ, type_de_champ: type_champ, value: nil) } - before do - render 'users/description/champs/render_list_champs.html.haml', champs: Champ.all, order_place: 0 + before do + render 'users/description/champs/render_list_champs.html.haml', champs: Champ.all, order_place: 0 + end + + it 'should not render a checked checkbox' do + expect(rendered).not_to have_css('input[type=checkbox][checked]') + end end - it 'should not render a checked checkbox' do - expect(rendered).not_to have_css('input[type=checkbox][checked]') - end - end + context "whose value equals 'on'" do + let!(:champ_checkbox_checked) { create(:champ, type_de_champ: type_champ, value: 'on') } - context "with a checkbox champ with value equals 'on'" do - let!(:champ_checkbox_checked) { create(:champ, type_de_champ: type_champ, value: 'on') } + before do + render 'users/description/champs/render_list_champs.html.haml', champs: Champ.all, order_place: 0 + end - before do - render 'users/description/champs/render_list_champs.html.haml', champs: Champ.all, order_place: 0 - end - - it 'should render a checked checkbox' do - expect(rendered).to have_css('input[type=checkbox][checked]') + it 'should render a checked checkbox' do + expect(rendered).to have_css('input[type=checkbox][checked]') + end end end From fd07a88ed6e359596b565495fe87f7e63e1d9987 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 26 Apr 2017 12:46:57 +0200 Subject: [PATCH 04/45] =?UTF-8?q?Add=20a=20missing=20test=20to=20the=20=5F?= =?UTF-8?q?render=5Flist=5Fchamps=20template=E2=80=99s=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../champs/_render_list_champs.html.haml_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/spec/views/users/description/champs/_render_list_champs.html.haml_spec.rb b/spec/views/users/description/champs/_render_list_champs.html.haml_spec.rb index 4e8982faf..233114a9b 100644 --- a/spec/views/users/description/champs/_render_list_champs.html.haml_spec.rb +++ b/spec/views/users/description/champs/_render_list_champs.html.haml_spec.rb @@ -1,6 +1,18 @@ describe 'users/description/champs/render_list_champs.html.haml', type: :view do let(:type_champ) { create(:type_de_champ_public, :checkbox) } + context "with any champ" do + let!(:champ) { create(:champ, type_de_champ: type_champ, value: nil) } + + before do + render 'users/description/champs/render_list_champs.html.haml', champs: Champ.all, order_place: 0 + end + + it "should render the champ's libelle" do + expect(rendered).to have_content(champ.libelle) + end + end + context "with a checkbox champ" do context "whose value equals nil" do let!(:champ_checkbox_checked) { create(:champ, type_de_champ: type_champ, value: nil) } From d3a84eb20a60f3c4a526675a6c35e1e321229d22 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 26 Apr 2017 15:08:15 +0200 Subject: [PATCH 05/45] =?UTF-8?q?D=C3=A9marche=20->=20Proc=C3=A9dure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- app/models/dossier.rb | 4 ++-- app/views/cgu/index.html.haml | 14 +++++++------- app/views/commencer/archived.html.haml | 2 +- app/views/root/landing.html.haml | 4 ++-- app/views/stats/index.html.haml | 4 ++-- config/locales/fr.yml | 2 +- spec/controllers/users/dossiers_controller_spec.rb | 2 +- spec/models/dossier_spec.rb | 6 +++--- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 2d9a96a0b..77efb29e2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Context -TéléProcédure Simplifiée, ou TPS pour les intimes, est une plateforme 100 % web et 0 % email, conçue afin de répondre au besoin urgent de l'État d'appliquer la directive sur le 100 % démat' à l'horizon 2018 pour les démarches administratives. +TéléProcédure Simplifiée, ou TPS pour les intimes, est une plateforme 100 % web et 0 % email, conçue afin de répondre au besoin urgent de l'État d'appliquer la directive sur le 100 % démat' à l'horizon 2018 pour les procédures administratives. ## Dépendances diff --git a/app/models/dossier.rb b/app/models/dossier.rb index ac11f9fc6..ed875bceb 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -281,7 +281,7 @@ class Dossier < ActiveRecord::Base def text_summary if brouillon? parts = [ - "Dossier en brouillon répondant à la démarche ", + "Dossier en brouillon répondant à la procédure ", procedure.libelle, " gérée par l'organisme ", procedure.organisation @@ -290,7 +290,7 @@ class Dossier < ActiveRecord::Base parts = [ "Dossier déposé le ", initiated_at.strftime("%d/%m/%Y"), - " sur la démarche ", + " sur la procédure ", procedure.libelle, " gérée par l'organisme ", procedure.organisation diff --git a/app/views/cgu/index.html.haml b/app/views/cgu/index.html.haml index 779d6ff83..5f52fee6d 100644 --- a/app/views/cgu/index.html.haml +++ b/app/views/cgu/index.html.haml @@ -44,7 +44,7 @@ %a{ :href => "https://tps.apientreprise.fr/" } %strong tps.apientreprise.fr %p - Le site internet tps.apientreprise.fr a pour objet de faciliter la création de démarches administratives en ligne par les acteurs publics, et l’examen par plusieurs services des demandes formulées par les usagers auprès d’un ou organismes publics. + Le site internet tps.apientreprise.fr a pour objet de faciliter la création de procédures administratives en ligne par les acteurs publics, et l’examen par plusieurs services des demandes formulées par les usagers auprès d’un ou organismes publics. %br %h3#acteurs Acteurs de @@ -53,8 +53,8 @@ %p Les acteurs de TPS sont les suivants : %ul %li Le SGMAP qui héberge le service TPS, le maintien en condition opérationnelle et gère les droits d’accès - %li L’administrateur au sein d’une administration donnée qui crée la démarche en ligne - %li Le ou les accompagnateurs au sein d’une administration donnée, qui reçoivent les démarches des usagers, les accompagnent le cas échéant dans le bouclage de leurs dossier, instruisent la demande et décident des suites à donner aux demandes + %li L’administrateur au sein d’une administration donnée qui crée la procédure en ligne + %li Le ou les accompagnateurs au sein d’une administration donnée, qui reçoivent les dossiers des usagers, les accompagnent le cas échéant dans le bouclage de leurs dossier, instruisent la demande et décident des suites à donner aux demandes %li Les Usagers qui formulent les demandes en ligne via le formulaire qui leur est mis à disposition %br %h3#CNIL @@ -67,10 +67,10 @@ %a{ :href => "https://www.declaration.cnil.fr/declarations/declaration/donneesSensibles_DN.display.action" } Opinions philosophiques, politiques, religieuses, syndicales, vie sexuelle, données de santé, origine raciale. %br %h3#data_collects - Données collectées et responsabilité des organismes publics à l’initiative de démarches en ligne avec TPS. + Données collectées et responsabilité des organismes publics à l’initiative de procédures en ligne avec TPS. %p Les données collectées par le service sont définis par les services publics utilisateurs du service qui arrêtent, sous leur responsabilité, la liste des informations qui seront demandées à l’usager. - %p Les organismes publics s’engagent à créer des démarches pour collecter les informations strictement nécessaires à l’examen des demandes formulées auprès des acteurs publics, dans le cadre juridique prévu par chacune des démarches. - %p Ces données sont collectées et traitées par les seuls services concernés par l’examen des demandes, et précisées dans la notice d’utilisation de chaque démarche publiée par l’organisme public. + %p Les organismes publics s’engagent à créer des procédures pour collecter les informations strictement nécessaires à l’examen des demandes formulées auprès des acteurs publics, dans le cadre juridique prévu par chacune des procédures. + %p Ces données sont collectées et traitées par les seuls services concernés par l’examen des demandes, et précisées dans la notice d’utilisation de chaque procédure publiée par l’organisme public. %br %h3#individual_data @@ -117,7 +117,7 @@ %a{ :href => "https://www.infogreffe.fr/societes/cgu-cgv.html" } Conditions générales d’utilisation des données d’infogreffe %br - %h4 TPS fait appel à d’autres services opérés par le SGMAP afin de faciliter les démarches administratives : + %h4 TPS fait appel à d’autres services opérés par le SGMAP afin de faciliter les procédures administratives : %br %p %strong> France CONNECT diff --git a/app/views/commencer/archived.html.haml b/app/views/commencer/archived.html.haml index 84c72ab34..2cdf8c7f2 100644 --- a/app/views/commencer/archived.html.haml +++ b/app/views/commencer/archived.html.haml @@ -6,7 +6,7 @@ %h3 La campagne de création de nouveau dossier %br - pour cette démarche en ligne est maintenant terminée. + pour cette procédure en ligne est maintenant terminée. %br %p diff --git a/app/views/root/landing.html.haml b/app/views/root/landing.html.haml index f49b66bb7..561246170 100644 --- a/app/views/root/landing.html.haml +++ b/app/views/root/landing.html.haml @@ -5,7 +5,7 @@ %p.hero-tagline %em.hero-tagline-em Dématérialisez %br - vos démarches administratives en quelques minutes + vos procédures administratives en quelques minutes = link_to "Demander une démo", "mailto:#{t("dynamics.contact_email")}?subject=Demande de démo TPS", @@ -135,7 +135,7 @@ %p.cta-panel-phone-cta ou nous appeler au 01 40 15 68 49 .pull-left - %h1.cta-panel-title Commencez à dématerialiser vos démarches + %h1.cta-panel-title Commencez à dématerialiser vos procédures %p.cta-panel-explanation Nous vous accompagnons dans la prise en main de l’outil .clearfix diff --git a/app/views/stats/index.html.haml b/app/views/stats/index.html.haml index b6c0fd893..b2e297797 100644 --- a/app/views/stats/index.html.haml +++ b/app/views/stats/index.html.haml @@ -12,7 +12,7 @@ Cumul %li.segmented-control-item{ :onclick => "TPS.toggleChart(event, '.flux-procedures-chart');" } Flux (30 jours) - %span.stat-card-title.pull-left Démarches dématérialisées + %span.stat-card-title.pull-left Procédures dématérialisées .clearfix .chart-container @@ -41,7 +41,7 @@ :colors => ["rgba(61, 149, 236, 1)"] .card.stat-card.stat-card-half.big-number-card.pull-left - %span.big-number-card-title TOTAL DÉMARCHES DÉMATÉRIALISÉES + %span.big-number-card-title TOTAL PROCÉDURES DÉMATÉRIALISÉES %span.big-number-card-number = number_with_delimiter(@procedures_count) diff --git a/config/locales/fr.yml b/config/locales/fr.yml index d67a7166c..4dc1def44 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -187,7 +187,7 @@ fr: france_connect: connexion: "Erreur lors de la connexion à France Connect." extension_white_list_error: "Le format de fichier de la pièce jointe n'est pas valide." - procedure_archived: "Cette démarche en ligne a été fermée, il n'est plus possible de déposer de dossier." + procedure_archived: "Cette procédure en ligne a été fermée, il n'est plus possible de déposer de dossier." date: abbr_day_names: diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index 31188c207..458db571f 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -563,7 +563,7 @@ describe Users::DossiersController, type: :controller do context 'when the dossier exist' do before { get :text_summary, params: { dossier_id: dossier.id } } it 'returns the procedure name' do - expect(JSON.parse(response.body)).to eq("textSummary" => "Dossier en brouillon répondant à la démarche #{procedure.libelle} gérée par l'organisme #{procedure.organisation}") + expect(JSON.parse(response.body)).to eq("textSummary" => "Dossier en brouillon répondant à la procédure #{procedure.libelle} gérée par l'organisme #{procedure.organisation}") end end diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 617071c24..9b4ed5d78 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -810,14 +810,14 @@ describe Dossier do end describe "#text_summary" do - let(:procedure) { create(:procedure, libelle: "Démarche", organisation: "Organisation") } + let(:procedure) { create(:procedure, libelle: "Procédure", organisation: "Organisation") } context 'when the dossier has been initiated' do let(:dossier) { create :dossier, procedure: procedure, state: 'initiated', initiated_at: "31/12/2010".to_date } subject { dossier.text_summary } - it { is_expected.to eq("Dossier déposé le 31/12/2010 sur la démarche Démarche gérée par l'organisme Organisation") } + it { is_expected.to eq("Dossier déposé le 31/12/2010 sur la procédure Procédure gérée par l'organisme Organisation") } end context 'when the dossier has not been initiated' do @@ -825,7 +825,7 @@ describe Dossier do subject { dossier.text_summary } - it { is_expected.to eq("Dossier en brouillon répondant à la démarche Démarche gérée par l'organisme Organisation") } + it { is_expected.to eq("Dossier en brouillon répondant à la procédure Procédure gérée par l'organisme Organisation") } end end From 4303dcef2ce6148bb7ac9bb39a1cc7a7cddc5d9f Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 26 Apr 2017 15:11:50 +0200 Subject: [PATCH 06/45] Organisation -> Organisme --- app/models/preference_list_dossier.rb | 2 +- app/views/admin/procedures/_informations.html.haml | 2 +- app/views/demo/_list.html.haml | 2 +- spec/models/dossier_spec.rb | 6 +++--- spec/models/preference_list_dossier_spec.rb | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/models/preference_list_dossier.rb b/app/models/preference_list_dossier.rb index 60ec5b82c..68c627b87 100644 --- a/app/models/preference_list_dossier.rb +++ b/app/models/preference_list_dossier.rb @@ -48,7 +48,7 @@ class PreferenceListDossier < ActiveRecord::Base { libelle: create_column('Libellé procédure', table, 'libelle', 'libelle', 4), - organisation: create_column('Organisation', table, 'organisation', 'organisation', 3), + organisation: create_column('Organisme', table, 'organisation', 'organisation', 3), direction: create_column('Direction', table, 'direction', 'direction', 3) } end diff --git a/app/views/admin/procedures/_informations.html.haml b/app/views/admin/procedures/_informations.html.haml index 553457b48..253ee6729 100644 --- a/app/views/admin/procedures/_informations.html.haml +++ b/app/views/admin/procedures/_informations.html.haml @@ -2,7 +2,7 @@ .alert.alert-info Cette procédure est publiée, certains éléments de la description ne sont plus modifiables -- { libelle: 'Libellé*', description: 'Description*', organisation: 'Organisation', direction: 'Direction', lien_site_web: 'Lien site internet', lien_notice: 'Lien notice' }.each do |key, value| +- { libelle: 'Libellé*', description: 'Description*', organisation: 'Organisme', direction: 'Direction', lien_site_web: 'Lien site internet', lien_notice: 'Lien notice' }.each do |key, value| .form-group %h4 = value diff --git a/app/views/demo/_list.html.haml b/app/views/demo/_list.html.haml index 60ea99bdc..b439c7884 100644 --- a/app/views/demo/_list.html.haml +++ b/app/views/demo/_list.html.haml @@ -7,7 +7,7 @@ %th= smart_listing.sortable 'ID', 'id' %th= smart_listing.sortable 'Titre', 'libelle' %th Description - %th= smart_listing.sortable 'Organisation', 'organisation' + %th= smart_listing.sortable 'Organisme', 'organisation' - smart_listing.collection.each do |procedure| - procedure = procedure.decorate diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 9b4ed5d78..e964e4b0d 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -810,14 +810,14 @@ describe Dossier do end describe "#text_summary" do - let(:procedure) { create(:procedure, libelle: "Procédure", organisation: "Organisation") } + let(:procedure) { create(:procedure, libelle: "Procédure", organisation: "Organisme") } context 'when the dossier has been initiated' do let(:dossier) { create :dossier, procedure: procedure, state: 'initiated', initiated_at: "31/12/2010".to_date } subject { dossier.text_summary } - it { is_expected.to eq("Dossier déposé le 31/12/2010 sur la procédure Procédure gérée par l'organisme Organisation") } + it { is_expected.to eq("Dossier déposé le 31/12/2010 sur la procédure Procédure gérée par l'organisme Organisme") } end context 'when the dossier has not been initiated' do @@ -825,7 +825,7 @@ describe Dossier do subject { dossier.text_summary } - it { is_expected.to eq("Dossier en brouillon répondant à la procédure Procédure gérée par l'organisme Organisation") } + it { is_expected.to eq("Dossier en brouillon répondant à la procédure Procédure gérée par l'organisme Organisme") } end end diff --git a/spec/models/preference_list_dossier_spec.rb b/spec/models/preference_list_dossier_spec.rb index c54163e12..cba6265a3 100644 --- a/spec/models/preference_list_dossier_spec.rb +++ b/spec/models/preference_list_dossier_spec.rb @@ -92,7 +92,7 @@ describe PreferenceListDossier do describe 'organisation' do subject { super()[:organisation] } - it { expect(subject[:libelle]).to eq 'Organisation' } + it { expect(subject[:libelle]).to eq 'Organisme' } it { expect(subject[:table]).to eq 'procedure' } it { expect(subject[:attr]).to eq 'organisation' } it { expect(subject[:attr_decorate]).to eq 'organisation' } From 77dae0462b44e7bd644ecad770f42a420e2b0cb4 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 26 Apr 2017 15:13:50 +0200 Subject: [PATCH 07/45] Utilisateur -> Usager --- app/views/admin/procedures/show.html.haml | 2 +- app/views/dossiers/_infos_dossier.html.haml | 2 +- app/views/layouts/_switch_devise_profile_module.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/admin/procedures/show.html.haml b/app/views/admin/procedures/show.html.haml index 171eb5ace..71b0c3501 100644 --- a/app/views/admin/procedures/show.html.haml +++ b/app/views/admin/procedures/show.html.haml @@ -102,7 +102,7 @@ %div = @facade.dossiers_waiting_gestionnaire_total - %h4.text-info Attente Utilisateur + %h4.text-info Attente Usager %div = @facade.dossiers_waiting_user_total diff --git a/app/views/dossiers/_infos_dossier.html.haml b/app/views/dossiers/_infos_dossier.html.haml index 15a1aa744..959f82c78 100644 --- a/app/views/dossiers/_infos_dossier.html.haml +++ b/app/views/dossiers/_infos_dossier.html.haml @@ -127,7 +127,7 @@ %table.table %thead %th - Utilisateur + Usager %th Date d'envoi %th diff --git a/app/views/layouts/_switch_devise_profile_module.html.haml b/app/views/layouts/_switch_devise_profile_module.html.haml index 6b718ca0a..ab51a0053 100644 --- a/app/views/layouts/_switch_devise_profile_module.html.haml +++ b/app/views/layouts/_switch_devise_profile_module.html.haml @@ -9,7 +9,7 @@ = link_to(users_dossiers_path, id: :menu_item_procedure) do %i.fa.fa-user   - Utilisateur + Usager - if gestionnaire_signed_in? %li = link_to(backoffice_dossiers_path) do From 402f44c5fd94717df28c7a3a6fb8b6eb5450cc08 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 26 Apr 2017 15:15:38 +0200 Subject: [PATCH 08/45] =?UTF-8?q?Champs=20priv=C3=A9s=20->=20Annotations?= =?UTF-8?q?=20priv=C3=A9es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/facades/admin_types_de_champ_facades.rb | 2 +- app/views/admin/procedures/show.html.haml | 2 +- .../_left_panel_admin_procedurescontroller_navbar.html.haml | 4 ++-- ...t_panel_admin_typesdechampprivatecontroller_show.html.haml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/facades/admin_types_de_champ_facades.rb b/app/facades/admin_types_de_champ_facades.rb index d6488193d..a8f7fe578 100644 --- a/app/facades/admin_types_de_champ_facades.rb +++ b/app/facades/admin_types_de_champ_facades.rb @@ -11,7 +11,7 @@ class AdminTypesDeChampFacades end def active - @private ? 'Champs privés' : 'Champs' + @private ? 'Annotations privées' : 'Champs' end def url diff --git a/app/views/admin/procedures/show.html.haml b/app/views/admin/procedures/show.html.haml index 71b0c3501..cce49b7a2 100644 --- a/app/views/admin/procedures/show.html.haml +++ b/app/views/admin/procedures/show.html.haml @@ -73,7 +73,7 @@ .champs_private.col-xs-6.col-md-3 %h4.text-info - Champs privés + Annotations privées .badge.progress-bar-info = @facade.procedure.types_de_champ_private.size %ul diff --git a/app/views/layouts/left_panels/_left_panel_admin_procedurescontroller_navbar.html.haml b/app/views/layouts/left_panels/_left_panel_admin_procedurescontroller_navbar.html.haml index 3185ce653..0bb60d458 100644 --- a/app/views/layouts/left_panels/_left_panel_admin_procedurescontroller_navbar.html.haml +++ b/app/views/layouts/left_panels/_left_panel_admin_procedurescontroller_navbar.html.haml @@ -34,8 +34,8 @@ - unless @procedure.locked? %a#onglet-private-champs{ :href => "#{url_for admin_procedure_types_de_champ_private_path(@procedure)}" } - .procedure-list-element{ class: ('active' if active == 'Champs privés') } - Champs privés + .procedure-list-element{ class: ('active' if active == 'Annotations privées') } + Annotations privées %a#onglet-inemailsfos{ :href => "#{url_for admin_procedure_mail_templates_path(@procedure)}" } .procedure-list-element{ class: ('active' if active == 'E-mails') } diff --git a/app/views/layouts/left_panels/_left_panel_admin_typesdechampprivatecontroller_show.html.haml b/app/views/layouts/left_panels/_left_panel_admin_typesdechampprivatecontroller_show.html.haml index 7c678cf26..37ee65c0f 100644 --- a/app/views/layouts/left_panels/_left_panel_admin_typesdechampprivatecontroller_show.html.haml +++ b/app/views/layouts/left_panels/_left_panel_admin_typesdechampprivatecontroller_show.html.haml @@ -1 +1 @@ -= render partial: 'layouts/left_panels/left_panel_admin_procedurescontroller_navbar', locals: { active: "Champs privés" } += render partial: 'layouts/left_panels/left_panel_admin_procedurescontroller_navbar', locals: { active: "Annotations privées" } From 0384b5d0ae7e4342426c7d8c8b2f243257aa1a31 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Wed, 3 May 2017 14:21:17 +0200 Subject: [PATCH 09/45] Local: add french translation for gestionnaire too_short password --- config/locales/fr.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/config/locales/fr.yml b/config/locales/fr.yml index d67a7166c..2686bdc9a 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -121,6 +121,7 @@ fr: blank: est vide password: blank: ': Le mot de passe est vide' + too_short: ': Le mot de passe est trop court' devise: confirmations: From 4d6a3653ed4cb8b91cfa712c3aabbce8d4fbc623 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Thu, 4 May 2017 11:26:08 +0200 Subject: [PATCH 10/45] Gitignore: add Procfile.dev to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8d761de27..308ee4352 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ coverage/**/* .DS_Store .byebug_history .env +Procfile.dev From 53e54166270172155777297a3b0079dcc00a4c0c Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Thu, 4 May 2017 16:01:41 +0200 Subject: [PATCH 11/45] Remove an unused file --- .../dossiers/_state_description.html.haml | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 app/views/backoffice/dossiers/_state_description.html.haml diff --git a/app/views/backoffice/dossiers/_state_description.html.haml b/app/views/backoffice/dossiers/_state_description.html.haml deleted file mode 100644 index 345b3fecf..000000000 --- a/app/views/backoffice/dossiers/_state_description.html.haml +++ /dev/null @@ -1,37 +0,0 @@ -#state_description.row{ style: 'width: 50%; margin-left: auto; margin-right: auto;' } - .panel.panel-info - .panel-body.center - .row - .col-md-1.col-lg-1.col-sm-1.col-xs-1.col-sm-1.col-xs-1 - .fa.fa-info-circle.text-info{ style: 'font-size: 2em; margin-top: 20%;' } - .col-xs-11 - - case dossiers_list_facade.liste - - when 'nouveaux' - Tous les dossiers présents dans cette liste sont ceux qui - %b - n'ont jamais été ouvert par votre service. - Il attende une première lecture et intervention de votre part. - - when 'a_traiter' - Tous les dossiers présents dans cette liste sont ceux qui sont - %b - en cours de construction avec l'usager. - Ils ne sont pas figés et ne sont donc pas complets. - - when 'fige' - Tous les dossiers présents dans cette liste ont été déclarés - %b - complets - et ne sont - %b - plus modifiables par l'usager. - Ils attendent donc leurs dépots officiels qui doit être effectué par l'usager. - - when 'deposes' - Tous les dossiers présents dans cette liste ont été - %b - officiellement déposé par l'usager pour examen. - Il faut donc que vous confirmiez par "accusé de réception" la bonne réception de toutes les informations et documents demandés avant examen final. - - when 'a_instruire' - Tous les dossiers présents dans cette liste sont à instruire. Ceux sont tous les dossiers - %b - qui ont reçu bonne réception. - - when 'termine' - Tous les dossiers présents dans cette liste sont considérés comme cloturé car ils ont tous reçu un verdict final qui peut être "Validé", "Refusé" ou "Sans suite". From 6e1818bb7936f49470ac4355e2c9f004e6442194 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Thu, 4 May 2017 12:25:08 +0200 Subject: [PATCH 12/45] Add missing dependencies to README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 77efb29e2..4a5df7605 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,11 @@ TéléProcédure Simplifiée, ou TPS pour les intimes, est une plateforme 100 % ### Tous environnements - postgresql +- redis + +### Développement + +- Mailcatcher : `gem install mailcatcher` ### Tests From 70f717547137bea236553c90ae3d29a1e2c09f7d Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Thu, 4 May 2017 12:25:26 +0200 Subject: [PATCH 13/45] Add a Launching section to README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 4a5df7605..b7a7b7412 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,14 @@ Afin de générer la BDD de l'application, il est nécessaire d'éxécuter les c rake db:create db:schema:load db:migrate RAILS_ENV=test +## Lancement de l'application + + redis-server + sidekiq + mailcatcher -f + rails s + + ## Exécution des tests (RSpec) Pour exécuter les tests de l'application, plusieurs possibilités : From 1691ce1899a62f7b8cf9148186f1d6503ef5e959 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Thu, 4 May 2017 12:27:39 +0200 Subject: [PATCH 14/45] Add a missing lint command to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b7a7b7412..eb1164f14 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Pour exécuter les tests de l'application, plusieurs possibilités : ## Linting - Linter les fichiers HAML : `bundle exec haml-lint app/views/` +- Linter les fichiers SCSS : `bundle exec scss-lint app/assets/stylesheets/` ## Régénérer les binstubs From f3343f593fe51394000f6e4f8ba3b40218d3c718 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Thu, 4 May 2017 16:07:45 +0200 Subject: [PATCH 15/45] Fix some spelling mistakes --- app/views/dossiers/etapes/etape_2/_individual.html.haml | 2 +- app/views/users/dossiers/_state_description.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/dossiers/etapes/etape_2/_individual.html.haml b/app/views/dossiers/etapes/etape_2/_individual.html.haml index ce87a50fc..d71aa8ea9 100644 --- a/app/views/dossiers/etapes/etape_2/_individual.html.haml +++ b/app/views/dossiers/etapes/etape_2/_individual.html.haml @@ -37,7 +37,7 @@ %label{ style: 'font-weight: normal;' } = f.check_box :autorisation_donnees = " ".html_safe - Vos informations personnelles ne seront jamais utilisées dans un but lucratif ou commercial. Elles ne pourront être communiquées à de tiers personnes sans votre accord préalable. Elles pourront en revanche être communiquées aux administrations compétentes afin d'instruire votre dossier, conformément à la déclaration CNIL effectué par le service TPS. + Vos informations personnelles ne seront jamais utilisées dans un but lucratif ou commercial. Elles ne pourront être communiquées à de tierces personnes sans votre accord préalable. Elles pourront en revanche être communiquées aux administrations compétentes afin d'instruire votre dossier, conformément à la déclaration CNIL effectuée par le service TPS. = link_to 'en savoir plus', cgu_path, target: '_blank' .row .col-xs-5.col-xs-5 diff --git a/app/views/users/dossiers/_state_description.html.haml b/app/views/users/dossiers/_state_description.html.haml index da1abe824..105ca1197 100644 --- a/app/views/users/dossiers/_state_description.html.haml +++ b/app/views/users/dossiers/_state_description.html.haml @@ -25,7 +25,7 @@ - when 'en_attente' Les dossiers présents dans cette liste sont %b - en cours de relecture par les services instructeurs. + en cours de relecture par le service instructeur. Il reviendra vers vous si des informations ou documents sont manquants pour le futur examen de votre dossier. - when 'valides' Les dossiers présents dans cette liste ont été From f389bbeb5376de054e69548a63907e430096c082 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 3 May 2017 11:34:42 +0200 Subject: [PATCH 16/45] Fix indentation in mail_template_concern.rb --- app/models/concerns/mail_template_concern.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/models/concerns/mail_template_concern.rb b/app/models/concerns/mail_template_concern.rb index 0da40c322..05ee8483c 100644 --- a/app/models/concerns/mail_template_concern.rb +++ b/app/models/concerns/mail_template_concern.rb @@ -5,16 +5,16 @@ module MailTemplateConcern include ActionView::Helpers::UrlHelper TAGS = { - numero_dossier: { - description: "Permet d'afficher le numéro de dossier de l'utilisateur." - }, - lien_dossier: { - description: "Permet d'afficher un lien vers le dossier de l'utilisateur." - }, - libelle_procedure: { - description: "Permet d'afficher le libellé de la procédure." - } - } + numero_dossier: { + description: "Permet d'afficher le numéro de dossier de l'utilisateur." + }, + lien_dossier: { + description: "Permet d'afficher un lien vers le dossier de l'utilisateur." + }, + libelle_procedure: { + description: "Permet d'afficher le libellé de la procédure." + } + } def object_for_dossier dossier replace_tags(object, dossier) From 43ae28de8703126c74fb837be5d4be832e95b36c Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 3 May 2017 11:50:02 +0200 Subject: [PATCH 17/45] Make the email templates tags table occupy the whole width available It improves the content formatting (no more ugly line breaks splitting a tag on several lines) --- app/views/admin/mail_templates/edit.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admin/mail_templates/edit.html.haml b/app/views/admin/mail_templates/edit.html.haml index 99e7e7c1a..9c33687bc 100644 --- a/app/views/admin/mail_templates/edit.html.haml +++ b/app/views/admin/mail_templates/edit.html.haml @@ -15,10 +15,10 @@ = f.button :submit, 'Mettre à jour', class: "btn-success" .row - .col-md-8 + .col-md-12 %table.table %tr - %th + %th.col-md-3 Balise %th Description From 30cf475485a671fc82b312c33309191f9df0572f Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 3 May 2017 11:58:34 +0200 Subject: [PATCH 18/45] Add missing brackets in mail_template_concern.rb --- app/models/concerns/mail_template_concern.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/concerns/mail_template_concern.rb b/app/models/concerns/mail_template_concern.rb index 05ee8483c..519ad346c 100644 --- a/app/models/concerns/mail_template_concern.rb +++ b/app/models/concerns/mail_template_concern.rb @@ -16,15 +16,15 @@ module MailTemplateConcern } } - def object_for_dossier dossier + def object_for_dossier(dossier) replace_tags(object, dossier) end - def body_for_dossier dossier + def body_for_dossier(dossier) replace_tags(body, dossier) end - def replace_tags string, dossier + def replace_tags(string, dossier) TAGS.inject(string) do |acc, tag| acc.gsub!("--#{tag.first}--", replace_tag(tag.first.to_sym, dossier)) || acc end @@ -43,7 +43,7 @@ module MailTemplateConcern private - def replace_tag tag, dossier + def replace_tag(tag, dossier) case tag when :numero_dossier dossier.id.to_s From 3bd5e32dffa0781903634be66d0b76eccaa39364 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 3 May 2017 11:46:41 +0200 Subject: [PATCH 19/45] Add a system to restrain the email templates tags to specific templates --- .../admin/mail_templates_controller.rb | 1 + app/models/concerns/mail_template_concern.rb | 31 +++++++++++++++++-- app/views/admin/mail_templates/edit.html.haml | 2 +- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/app/controllers/admin/mail_templates_controller.rb b/app/controllers/admin/mail_templates_controller.rb index 7c94d4a0f..5967c3dd5 100644 --- a/app/controllers/admin/mail_templates_controller.rb +++ b/app/controllers/admin/mail_templates_controller.rb @@ -7,6 +7,7 @@ class Admin::MailTemplatesController < AdminController def edit @mail_template = find_the_right_mail params[:id] + @mail_template_name = params[:id] end def update diff --git a/app/models/concerns/mail_template_concern.rb b/app/models/concerns/mail_template_concern.rb index 519ad346c..70879b6d8 100644 --- a/app/models/concerns/mail_template_concern.rb +++ b/app/models/concerns/mail_template_concern.rb @@ -6,16 +6,41 @@ module MailTemplateConcern TAGS = { numero_dossier: { - description: "Permet d'afficher le numéro de dossier de l'utilisateur." + description: "Permet d'afficher le numéro de dossier de l'utilisateur.", + templates: [ + "initiated_mail", + "received_mail", + "closed_mail", + "refused_mail", + "without_continuation_mail" + ] }, lien_dossier: { - description: "Permet d'afficher un lien vers le dossier de l'utilisateur." + description: "Permet d'afficher un lien vers le dossier de l'utilisateur.", + templates: [ + "initiated_mail", + "received_mail", + "closed_mail", + "refused_mail", + "without_continuation_mail" + ] }, libelle_procedure: { - description: "Permet d'afficher le libellé de la procédure." + description: "Permet d'afficher le libellé de la procédure.", + templates: [ + "initiated_mail", + "received_mail", + "closed_mail", + "refused_mail", + "without_continuation_mail" + ] } } + def self.tags_for_template(template) + TAGS.select { |key, value| value[:templates].include?(template) } + end + def object_for_dossier(dossier) replace_tags(object, dossier) end diff --git a/app/views/admin/mail_templates/edit.html.haml b/app/views/admin/mail_templates/edit.html.haml index 9c33687bc..a35c13334 100644 --- a/app/views/admin/mail_templates/edit.html.haml +++ b/app/views/admin/mail_templates/edit.html.haml @@ -22,7 +22,7 @@ Balise %th Description - - MailTemplateConcern::TAGS.each do |balise| + - MailTemplateConcern.tags_for_template(@mail_template_name).each do |balise| %tr %td.center = "--#{balise.first}--" From 2582b44f070dc7f5bbdb7abdb9bc9013e239ca69 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 3 May 2017 11:50:14 +0200 Subject: [PATCH 20/45] [Fix #204] Add the date_de_decision tag --- app/models/concerns/mail_template_concern.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/models/concerns/mail_template_concern.rb b/app/models/concerns/mail_template_concern.rb index 70879b6d8..f5a41a156 100644 --- a/app/models/concerns/mail_template_concern.rb +++ b/app/models/concerns/mail_template_concern.rb @@ -34,6 +34,14 @@ module MailTemplateConcern "refused_mail", "without_continuation_mail" ] + }, + date_de_decision: { + description: "Permet d'afficher la date à laquelle la décision finale (acceptation, refus, classement sans suite) sur le dossier a été prise.", + templates: [ + "closed_mail", + "refused_mail", + "without_continuation_mail" + ] } } @@ -76,6 +84,8 @@ module MailTemplateConcern link_to users_dossier_recapitulatif_url(dossier), users_dossier_recapitulatif_url(dossier), target: '_blank' when :libelle_procedure dossier.procedure.libelle + when :date_de_decision + dossier.processed_at.present? ? dossier.processed_at.strftime("%d/%m/%Y") : "" else '--BALISE_NON_RECONNUE--' end From 849ab5191a547c3088bfcbc23344dc484820ffad Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 3 May 2017 11:52:56 +0200 Subject: [PATCH 21/45] [Fix #204] Add the date_de_decision tag in relevant email templates --- app/views/mails/closed_mail.html.haml | 2 +- app/views/mails/refused_mail.html.haml | 2 +- app/views/mails/without_continuation_mail.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/mails/closed_mail.html.haml b/app/views/mails/closed_mail.html.haml index ac3153c9a..5870fc1cf 100644 --- a/app/views/mails/closed_mail.html.haml +++ b/app/views/mails/closed_mail.html.haml @@ -1,7 +1,7 @@ Bonjour %br %br -Votre dossier nº --numero_dossier-- a été accepté. +Votre dossier nº --numero_dossier-- a été accepté le --date_de_decision--. %br %br A tout moment, vous pouvez consulter le contenu de vos dossiers et les éventuels commentaires de l'administration à cette adresse : --lien_dossier-- diff --git a/app/views/mails/refused_mail.html.haml b/app/views/mails/refused_mail.html.haml index 900942f26..b2796bf3c 100644 --- a/app/views/mails/refused_mail.html.haml +++ b/app/views/mails/refused_mail.html.haml @@ -1,7 +1,7 @@ Bonjour %br %br -Votre dossier nº --numero_dossier-- a été refusé. +Votre dossier nº --numero_dossier-- a été refusé le --date_de_decision--. %br %br Pour en savoir plus sur le motif du refus, vous pouvez consulter le contenu de vos dossiers et les éventuels commentaires de l'administration à cette adresse : --lien_dossier-- diff --git a/app/views/mails/without_continuation_mail.html.haml b/app/views/mails/without_continuation_mail.html.haml index 03ab071cc..ddac75477 100644 --- a/app/views/mails/without_continuation_mail.html.haml +++ b/app/views/mails/without_continuation_mail.html.haml @@ -1,7 +1,7 @@ Bonjour %br %br -Votre dossier nº --numero_dossier-- a été classé sans suite. +Votre dossier nº --numero_dossier-- a été classé sans suite le --date_de_decision--. %br %br Pour en savoir plus sur les raisons de ce classement sans suite, vous pouvez consulter le contenu de vos dossiers et les éventuels commentaires de l'administration à cette adresse : --lien_dossier-- From 250c47e1458eee4a78c3dc54fa549c85d6923b05 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 3 May 2017 14:33:53 +0200 Subject: [PATCH 22/45] [Fix #126] Remove the now useless as_csv gem --- Gemfile | 1 - Gemfile.lock | 5 ----- 2 files changed, 6 deletions(-) diff --git a/Gemfile b/Gemfile index 945efbb3a..246e589dd 100644 --- a/Gemfile +++ b/Gemfile @@ -78,7 +78,6 @@ gem 'smart_listing' gem 'bootstrap-wysihtml5-rails', '~> 0.3.3.8' -gem 'as_csv' gem 'spreadsheet_architect' gem 'apipie-rails' diff --git a/Gemfile.lock b/Gemfile.lock index d2da50210..07225ea01 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -74,10 +74,6 @@ GEM apipie-rails (0.3.7) json arel (7.1.4) - as_csv (2.0.2) - actionpack (>= 3.0) - activemodel (>= 3.0) - responders ast (2.3.0) attr_required (1.0.1) autoprefixer-rails (6.5.4) @@ -669,7 +665,6 @@ DEPENDENCIES actioncable (= 5.0.0.1) active_model_serializers apipie-rails - as_csv bootstrap-datepicker-rails bootstrap-sass (~> 3.3.5) bootstrap-wysihtml5-rails (~> 0.3.3.8) From 9a0df71887460c6d62f881a591a9fca7ff37b95f Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Tue, 2 May 2017 15:32:39 +0200 Subject: [PATCH 23/45] Change the link to a linked dossier depending on the user profile --- app/decorators/champ_decorator.rb | 1 - app/decorators/dossier_decorator.rb | 12 ++++++++ app/views/dossiers/_infos_dossier.html.haml | 2 +- spec/decorators/dossier_decorator_spec.rb | 32 +++++++++++++++++++++ 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/app/decorators/champ_decorator.rb b/app/decorators/champ_decorator.rb index 8c95b8183..1688c5f91 100644 --- a/app/decorators/champ_decorator.rb +++ b/app/decorators/champ_decorator.rb @@ -10,5 +10,4 @@ class ChampDecorator < Draper::Decorator def description_with_links description.gsub(URI.regexp, '\0').html_safe if description end - end diff --git a/app/decorators/dossier_decorator.rb b/app/decorators/dossier_decorator.rb index 8bf76769b..438c67061 100644 --- a/app/decorators/dossier_decorator.rb +++ b/app/decorators/dossier_decorator.rb @@ -1,4 +1,6 @@ class DossierDecorator < Draper::Decorator + include Rails.application.routes.url_helpers + delegate :current_page, :per_page, :offset, :total_entries, :total_pages delegate_all @@ -14,6 +16,16 @@ class DossierDecorator < Draper::Decorator DossierDecorator.case_state_fr state end + def url(gestionnaire_signed_in) + if gestionnaire_signed_in + backoffice_dossier_path(id) + elsif brouillon? + users_dossier_description_path(id) + else + users_dossier_recapitulatif_path(id) + end + end + def self.case_state_fr state=self.state h.t("activerecord.attributes.dossier.state.#{state}") end diff --git a/app/views/dossiers/_infos_dossier.html.haml b/app/views/dossiers/_infos_dossier.html.haml index 959f82c78..7de372ba2 100644 --- a/app/views/dossiers/_infos_dossier.html.haml +++ b/app/views/dossiers/_infos_dossier.html.haml @@ -41,7 +41,7 @@ - if champ.type_champ == 'dossier_link' - dossier = Dossier.includes(:procedure).find_by(id: champ.decorate.value) - if dossier - = link_to("Dossier #{dossier.id}", backoffice_dossier_path(champ.decorate.value), target: '_blank') + = link_to("Dossier #{dossier.id}", dossier.decorate.url(gestionnaire_signed_in?), target: '_blank') %br = dossier.text_summary - else diff --git a/spec/decorators/dossier_decorator_spec.rb b/spec/decorators/dossier_decorator_spec.rb index 31a32b161..9920a89b4 100644 --- a/spec/decorators/dossier_decorator_spec.rb +++ b/spec/decorators/dossier_decorator_spec.rb @@ -57,4 +57,36 @@ describe DossierDecorator do expect(subject).to eq('Refusé') end end + + describe '#url' do + context "when a gestionnaire is signed_in" do + subject { super().url(true) } + + it { is_expected.to eq("/backoffice/dossiers/#{dossier.id}") } + end + + context "when a gestionnaire is not signed_in" do + context "when the dossier is in brouillon state" do + before do + dossier.state = 'draft' + dossier.save + end + + subject { super().url(false) } + + it { is_expected.to eq("/users/dossiers/#{dossier.id}/description") } + end + + context "when the dossier is not in brouillon state" do + before do + dossier.state = 'updated' + dossier.save + end + + subject { super().url(false) } + + it { is_expected.to eq("/users/dossiers/#{dossier.id}/recapitulatif") } + end + end + end end From 4591f2fdbeaf6ac08f7244007c9ece14a8cfdb17 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Thu, 4 May 2017 18:07:55 +0200 Subject: [PATCH 24/45] =?UTF-8?q?T=C3=A9l=C3=A9Proc=C3=A9dure=20Simplifi?= =?UTF-8?q?=C3=A9e=20=3D>=20T=C3=A9l=C3=A9Proc=C3=A9dures=20Simplifi=C3=A9?= =?UTF-8?q?es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eb1164f14..a2a31b699 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# TPS - TéléProcédure Simplifiée +# TPS - TéléProcédures Simplifiées ## Context From 6b25d25a9adc1c94f79d527238d836423eddb3f6 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Thu, 4 May 2017 18:19:13 +0200 Subject: [PATCH 25/45] =?UTF-8?q?The=20correct=20app=20name=20is=20?= =?UTF-8?q?=E2=80=9CT=C3=A9l=C3=A9proc=C3=A9dures=20Simplifi=C3=A9es?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- app/views/cgu/index.html.haml | 2 +- config/newrelic.yml | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a2a31b699..61d22b1c9 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# TPS - TéléProcédures Simplifiées +# TPS - Téléprocédures Simplifiées ## Context -TéléProcédure Simplifiée, ou TPS pour les intimes, est une plateforme 100 % web et 0 % email, conçue afin de répondre au besoin urgent de l'État d'appliquer la directive sur le 100 % démat' à l'horizon 2018 pour les procédures administratives. +Téléprocédures Simplifiées, ou TPS pour les intimes, est une plateforme 100 % web et 0 % email, conçue afin de répondre au besoin urgent de l'État d'appliquer la directive sur le 100 % démat' à l'horizon 2018 pour les procédures administratives. ## Dépendances diff --git a/app/views/cgu/index.html.haml b/app/views/cgu/index.html.haml index 5f52fee6d..9d537bc95 100644 --- a/app/views/cgu/index.html.haml +++ b/app/views/cgu/index.html.haml @@ -1,6 +1,6 @@ #cgu %h2 - Condition d’utilisation du service « TPS » pour téléprocédure simplifiée + Condition d’utilisation du service « TPS » pour téléprocédures simplifiées %br %h3#editeur Editeur diff --git a/config/newrelic.yml b/config/newrelic.yml index be46869da..865ea7e27 100644 --- a/config/newrelic.yml +++ b/config/newrelic.yml @@ -16,7 +16,7 @@ common: &default_settings # Your application name. Renaming here affects where data displays in New # Relic. For more details, see https://docs.newrelic.com/docs/apm/new-relic-apm/maintenance/renaming-applications - app_name: Téléprocédure Simplifiée + app_name: Téléprocédures Simplifiées # To disable the agent regardless of other settings, uncomment the following: # agent_enabled: false @@ -30,7 +30,7 @@ common: &default_settings # If your application has other named environments, configure them here. development: <<: *default_settings - app_name: Téléprocédure Simplifiée (Development) + app_name: Téléprocédures Simplifiées (Development) # NOTE: There is substantial overhead when running in developer mode. # Do not use for production or load testing. @@ -43,7 +43,7 @@ test: staging: <<: *default_settings - app_name: Téléprocédure Simplifiée (Staging) + app_name: Téléprocédures Simplifiées (Staging) production: <<: *default_settings From 38dcf5c74d2d76382aea0418fa44a9ac36b414d2 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Tue, 2 May 2017 18:47:46 +0200 Subject: [PATCH 26/45] Application.scss: replace require_tree by explicit import Change needed for futur new_application.scss and corresponding style --- app/assets/stylesheets/application.scss | 44 ++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index adf15f626..39db474b7 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -12,7 +12,49 @@ // defined in the other CSS/SCSS files in this directory. It is generally better to create a new // file per style scope. // -// = require_tree . +// = require _card +// = require _colors +// = require _constants +// = require _helpers +// = require _mixins +// = require _placeholders +// = require _turbolinks +// = require _typography +// = require admin_procedures_modal +// = require admin_type_de_champ +// = require backoffice +// = require carte +// = require cgu +// = require custom-mails +// = require default_data_block +// = require description +// = require dossier_show +// = require dossiers +// = require etapes +// = require fonts +// = require france_connect_particulier +// = require header +// = require landing +// = require left_panel +// = require login +// = require main_container +// = require navbar +// = require new_footer +// = require notification_alert +// = require pieces_justificatives_fields +// = require pj_modal +// = require pref_list_menu +// = require print +// = require procedure +// = require recapitulatif +// = require search +// = require siret +// = require stats +// = require support_navigator_banner +// = require switch_menu +// = require typeahead +// = require users + // = require_self // = require bootstrap-datepicker3 // = require leaflet From e7383c7c85a05c24d2deef3e0f900b90b2dd5f65 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Wed, 3 May 2017 16:48:23 +0200 Subject: [PATCH 27/45] CSS: add Meyer's reset.scss --- .scss-lint.yml | 2 ++ app/assets/stylesheets/reset.scss | 48 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 app/assets/stylesheets/reset.scss diff --git a/.scss-lint.yml b/.scss-lint.yml index 918c14c70..7ee185bb3 100644 --- a/.scss-lint.yml +++ b/.scss-lint.yml @@ -1,3 +1,5 @@ +exclude: 'app/assets/stylesheets/reset.scss' + linters: BangFormat: enabled: true diff --git a/app/assets/stylesheets/reset.scss b/app/assets/stylesheets/reset.scss new file mode 100644 index 000000000..e29c0f5f4 --- /dev/null +++ b/app/assets/stylesheets/reset.scss @@ -0,0 +1,48 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} From aee17c5b193b87f6cecfd4e52dcfbd058c8e7973 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Thu, 4 May 2017 14:49:18 +0200 Subject: [PATCH 28/45] CSS: CSS filenames should not contain dashes --- app/assets/stylesheets/application.scss | 2 +- app/assets/stylesheets/{custom-mails.scss => custom_mails.scss} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename app/assets/stylesheets/{custom-mails.scss => custom_mails.scss} (100%) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 39db474b7..dd8e19bbe 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -25,7 +25,7 @@ // = require backoffice // = require carte // = require cgu -// = require custom-mails +// = require custom_mails // = require default_data_block // = require description // = require dossier_show diff --git a/app/assets/stylesheets/custom-mails.scss b/app/assets/stylesheets/custom_mails.scss similarity index 100% rename from app/assets/stylesheets/custom-mails.scss rename to app/assets/stylesheets/custom_mails.scss From dc371b83b871f7c9c11aef22159e71e118b0ddcc Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Wed, 3 May 2017 16:50:36 +0200 Subject: [PATCH 29/45] CSS: add new application layout + CSS Without bootstrap! --- app/assets/stylesheets/application.scss | 2 -- app/assets/stylesheets/common.scss | 7 +++++ app/assets/stylesheets/custom_reset.scss | 27 +++++++++++++++++++ app/assets/stylesheets/landing.scss | 2 -- app/assets/stylesheets/new_application.scss | 9 +++++++ app/assets/stylesheets/new_footer.scss | 3 +-- .../{header.scss => new_header.scss} | 4 --- app/assets/stylesheets/utils.scss | 11 ++++++++ app/views/layouts/new_application.html.haml | 2 +- config/initializers/assets.rb | 2 +- 10 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 app/assets/stylesheets/common.scss create mode 100644 app/assets/stylesheets/custom_reset.scss create mode 100644 app/assets/stylesheets/new_application.scss rename app/assets/stylesheets/{header.scss => new_header.scss} (88%) create mode 100644 app/assets/stylesheets/utils.scss diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index dd8e19bbe..33338dbdb 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -33,13 +33,11 @@ // = require etapes // = require fonts // = require france_connect_particulier -// = require header // = require landing // = require left_panel // = require login // = require main_container // = require navbar -// = require new_footer // = require notification_alert // = require pieces_justificatives_fields // = require pj_modal diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss new file mode 100644 index 000000000..bbf87837b --- /dev/null +++ b/app/assets/stylesheets/common.scss @@ -0,0 +1,7 @@ +@import "typography"; + +body { + @extend %new-type; + font-size: 16px; + line-height: 1.42857143; +} diff --git a/app/assets/stylesheets/custom_reset.scss b/app/assets/stylesheets/custom_reset.scss new file mode 100644 index 000000000..009fd7c0d --- /dev/null +++ b/app/assets/stylesheets/custom_reset.scss @@ -0,0 +1,27 @@ +html, +body { + height: 100%; +} + +html { + box-sizing: border-box; +} + +*, +*::before, +*::after { + box-sizing: inherit; +} + +a { + text-decoration: none; +} + +// remove dotted outline on firefox +:focus { + outline: none; +} + +::-moz-focus-inner { + border: none; +} diff --git a/app/assets/stylesheets/landing.scss b/app/assets/stylesheets/landing.scss index bc8481080..e5f6b2251 100644 --- a/app/assets/stylesheets/landing.scss +++ b/app/assets/stylesheets/landing.scss @@ -2,10 +2,8 @@ @import "colors"; @import "mixins"; @import "placeholders"; -@import "typography"; .landing { - @extend %new-type; background-color: #FFFFFF; } diff --git a/app/assets/stylesheets/new_application.scss b/app/assets/stylesheets/new_application.scss new file mode 100644 index 000000000..839ecd613 --- /dev/null +++ b/app/assets/stylesheets/new_application.scss @@ -0,0 +1,9 @@ +// = require reset +// = require custom_reset +// = require common +// = require utils +// = require fonts +// = require new_header +// = require new_footer +// = require landing +// = require navbar diff --git a/app/assets/stylesheets/new_footer.scss b/app/assets/stylesheets/new_footer.scss index ffdaa9e6b..de93cd97d 100644 --- a/app/assets/stylesheets/new_footer.scss +++ b/app/assets/stylesheets/new_footer.scss @@ -1,10 +1,9 @@ +@import "colors"; @import "constants"; @import "mixins"; @import "placeholders"; -@import "typography"; .footer { - @extend %new-type; @include vertical-padding(72px); background-color: $light-grey; } diff --git a/app/assets/stylesheets/header.scss b/app/assets/stylesheets/new_header.scss similarity index 88% rename from app/assets/stylesheets/header.scss rename to app/assets/stylesheets/new_header.scss index fdc9e81c8..3213bb3c1 100644 --- a/app/assets/stylesheets/header.scss +++ b/app/assets/stylesheets/new_header.scss @@ -1,15 +1,11 @@ @import "constants"; @import "colors"; @import "mixins"; -@import "typography"; // FIXME: Rename when the header is generalized .new-header { - @extend %new-type; height: 72px; background-color: #FFFFFF; - // FIXME: Delete when the header is generalized - margin-top: -60px; } .header-inner-content { diff --git a/app/assets/stylesheets/utils.scss b/app/assets/stylesheets/utils.scss new file mode 100644 index 000000000..cb9f55abd --- /dev/null +++ b/app/assets/stylesheets/utils.scss @@ -0,0 +1,11 @@ +.pull-left { + float: left; +} + +.pull-right { + float: right; +} + +.clearfix { + clear: both; +} diff --git a/app/views/layouts/new_application.html.haml b/app/views/layouts/new_application.html.haml index 9908098f3..2c9204012 100644 --- a/app/views/layouts/new_application.html.haml +++ b/app/views/layouts/new_application.html.haml @@ -13,7 +13,7 @@ = favicon_link_tag(image_url("favicons/32x32.png"), type: "image/png", sizes: "32x32") = favicon_link_tag(image_url("favicons/96x96.png"), type: "image/png", sizes: "96x96") - = stylesheet_link_tag "application", :media => "all", "data-turbolinks-track" => true + = stylesheet_link_tag "new_application", :media => "all", "data-turbolinks-track" => true = stylesheet_link_tag "print", :media => "print", "data-turbolinks-track" => true %body diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 76333b2be..882590de7 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -8,4 +8,4 @@ Rails.application.config.assets.version = '1.0' # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -Rails.application.config.assets.precompile += %w(print.css) +Rails.application.config.assets.precompile += %w(print.css new_application.css) From c7999b9691d4714b1467c5e612c78c275ad14d2f Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 26 Apr 2017 14:24:48 +0200 Subject: [PATCH 30/45] Add a date_attribute argument to StatsController#thirty_days_flow --- app/controllers/stats_controller.rb | 6 +-- spec/controllers/stats_controller_spec.rb | 51 +++++++++++++++++------ 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 04a1f303c..cd29b1404 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -16,13 +16,13 @@ class StatsController < ApplicationController private - def thirty_days_flow_hash(association) + def thirty_days_flow_hash(association, date_attribute = :created_at) min_date = 30.days.ago.to_date max_date = Time.now.to_date thirty_days_flow_hash = association - .where(:created_at => min_date..max_date) - .group("date_trunc('day', created_at)") + .where(date_attribute => min_date..max_date) + .group("date_trunc('day', #{date_attribute.to_s})") .count clean_hash(thirty_days_flow_hash, min_date, max_date) diff --git a/spec/controllers/stats_controller_spec.rb b/spec/controllers/stats_controller_spec.rb index 58727e970..584a54cf4 100644 --- a/spec/controllers/stats_controller_spec.rb +++ b/spec/controllers/stats_controller_spec.rb @@ -2,26 +2,51 @@ require 'spec_helper' describe StatsController, type: :controller do describe '#thirty_days_flow_hash' do - before do - FactoryGirl.create(:procedure, :created_at => 45.days.ago) - FactoryGirl.create(:procedure, :created_at => 15.days.ago) - FactoryGirl.create(:procedure, :created_at => 1.day.ago) + context "without a date_attribut" do + before do + FactoryGirl.create(:procedure, :created_at => 45.days.ago) + FactoryGirl.create(:procedure, :created_at => 15.days.ago) + FactoryGirl.create(:procedure, :created_at => 1.day.ago) - @expected_hash = {} - (30.days.ago.to_date..Time.now.to_date).each do |day| - if [15.days.ago.to_date, 1.day.ago.to_date].include?(day) - @expected_hash[day] = 1 - else - @expected_hash[day] = 0 + @expected_hash = {} + (30.days.ago.to_date..Time.now.to_date).each do |day| + if [15.days.ago.to_date, 1.day.ago.to_date].include?(day) + @expected_hash[day] = 1 + else + @expected_hash[day] = 0 + end end end + + let (:association) { Procedure.all } + + subject { StatsController.new.send(:thirty_days_flow_hash, association) } + + it { expect(subject).to eq(@expected_hash) } end - let (:association) { Procedure.all } + context "with a date_attribut" do + before do + FactoryGirl.create(:procedure, :created_at => 45.days.ago, :updated_at => 50.days.ago) + FactoryGirl.create(:procedure, :created_at => 15.days.ago, :updated_at => 10.days.ago) + FactoryGirl.create(:procedure, :created_at => 1.day.ago, :updated_at => 3.days.ago) - subject { StatsController.new.send(:thirty_days_flow_hash, association) } + @expected_hash = {} + (30.days.ago.to_date..Time.now.to_date).each do |day| + if [10.days.ago.to_date, 3.day.ago.to_date].include?(day) + @expected_hash[day] = 1 + else + @expected_hash[day] = 0 + end + end + end - it { expect(subject).to eq(@expected_hash) } + let (:association) { Procedure.all } + + subject { StatsController.new.send(:thirty_days_flow_hash, association, :updated_at) } + + it { expect(subject).to eq(@expected_hash) } + end end describe '#cumulative_hash' do From dbf891b333fda03d08ffd900155743a7a5b139a9 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 26 Apr 2017 14:26:03 +0200 Subject: [PATCH 31/45] Use the initialisation date for the dossiers 30 days flow We want to show when dossiers were published, not created --- app/controllers/stats_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index cd29b1404..b2e22e7cc 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -5,7 +5,7 @@ class StatsController < ApplicationController dossiers = Dossier.where.not(:state => :draft) @procedures_30_days_flow = thirty_days_flow_hash(procedures) - @dossiers_30_days_flow = thirty_days_flow_hash(dossiers) + @dossiers_30_days_flow = thirty_days_flow_hash(dossiers, :initiated_at) @procedures_cumulative = cumulative_hash(procedures) @dossiers_cumulative = cumulative_hash(dossiers) From 06714b5fc346870b0ae4286986cca119ea1e82cc Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 26 Apr 2017 14:28:39 +0200 Subject: [PATCH 32/45] Add a date_attribute argument to StatsController#cumulative_hash --- app/controllers/stats_controller.rb | 4 +-- spec/controllers/stats_controller_spec.rb | 31 ++++++++++++++++++----- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index b2e22e7cc..293e6b46e 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -42,10 +42,10 @@ class StatsController < ApplicationController h end - def cumulative_hash(association) + def cumulative_hash(association, date_attribute = :created_at) sum = 0 association - .group("DATE_TRUNC('month', created_at)") + .group("DATE_TRUNC('month', #{date_attribute.to_s})") .count .to_a .sort{ |x, y| x[0] <=> y[0] } diff --git a/spec/controllers/stats_controller_spec.rb b/spec/controllers/stats_controller_spec.rb index 584a54cf4..6cbaf91bd 100644 --- a/spec/controllers/stats_controller_spec.rb +++ b/spec/controllers/stats_controller_spec.rb @@ -50,19 +50,38 @@ describe StatsController, type: :controller do end describe '#cumulative_hash' do + context "without a date attribute" do + before do + FactoryGirl.create(:procedure, :created_at => 45.days.ago) + FactoryGirl.create(:procedure, :created_at => 15.days.ago) + FactoryGirl.create(:procedure, :created_at => 15.days.ago) + end + + let (:association) { Procedure.all } + + subject { StatsController.new.send(:cumulative_hash, association) } + + it { expect(subject).to eq({ + 45.days.ago.beginning_of_month => 1, + 15.days.ago.beginning_of_month => 3 + }) } + end + end + + context "with a date attribute" do before do - FactoryGirl.create(:procedure, :created_at => 45.days.ago) - FactoryGirl.create(:procedure, :created_at => 15.days.ago) - FactoryGirl.create(:procedure, :created_at => 15.days.ago) + FactoryGirl.create(:procedure, :created_at => 45.days.ago, :updated_at => 20.days.ago) + FactoryGirl.create(:procedure, :created_at => 15.days.ago, :updated_at => 20.days.ago) + FactoryGirl.create(:procedure, :created_at => 15.days.ago, :updated_at => 10.days.ago) end let (:association) { Procedure.all } - subject { StatsController.new.send(:cumulative_hash, association) } + subject { StatsController.new.send(:cumulative_hash, association, :updated_at) } it { expect(subject).to eq({ - 45.days.ago.beginning_of_month => 1, - 15.days.ago.beginning_of_month => 3 + 20.days.ago.beginning_of_month => 2, + 10.days.ago.beginning_of_month => 3 }) } end end From 02a8cf3fe186fd51a4cb85fd82768a935cfb23f0 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 26 Apr 2017 14:29:22 +0200 Subject: [PATCH 33/45] Use the initialisation date for the cumulative dossiers We want to show when dossiers were published, not created --- app/controllers/stats_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 293e6b46e..66d1bf202 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -8,7 +8,7 @@ class StatsController < ApplicationController @dossiers_30_days_flow = thirty_days_flow_hash(dossiers, :initiated_at) @procedures_cumulative = cumulative_hash(procedures) - @dossiers_cumulative = cumulative_hash(dossiers) + @dossiers_cumulative = cumulative_hash(dossiers, :initiated_at) @procedures_count = procedures.count @dossiers_count = dossiers.count From 9d16c0365a7bdd109824163cd92a83695f78e0ae Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Fri, 5 May 2017 14:08:36 +0200 Subject: [PATCH 34/45] Notification: remove useless notification system --- .../javascripts/channels/notifications.js | 23 ------------------- .../layouts/_notifications_alert.html.haml | 1 - app/views/layouts/application.html.haml | 1 - app/views/layouts/new_application.html.haml | 1 - 4 files changed, 26 deletions(-) delete mode 100644 app/assets/javascripts/channels/notifications.js delete mode 100644 app/views/layouts/_notifications_alert.html.haml diff --git a/app/assets/javascripts/channels/notifications.js b/app/assets/javascripts/channels/notifications.js deleted file mode 100644 index f1f2d519d..000000000 --- a/app/assets/javascripts/channels/notifications.js +++ /dev/null @@ -1,23 +0,0 @@ -//App.messages = App.cable.subscriptions.create('NotificationsChannel', { -// received: function (data) { -// if (window.location.href.indexOf('backoffice') !== -1) { -// $("#notification-alert").html(data['message']); -// -// slideIn_notification_alert(); -// } -// } -//}); - -function slideIn_notification_alert (){ - $("#notification-alert").animate({ - right: '20px' - }, 250); - - setTimeout(slideOut_notification_alert, 3500); -} - -function slideOut_notification_alert (){ - $("#notification-alert").animate({ - right: '-250px' - }, 200); -} diff --git a/app/views/layouts/_notifications_alert.html.haml b/app/views/layouts/_notifications_alert.html.haml deleted file mode 100644 index 99c4a4682..000000000 --- a/app/views/layouts/_notifications_alert.html.haml +++ /dev/null @@ -1 +0,0 @@ -#notification-alert.alert.alert-success diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index e6aeea5e5..d4278bc3d 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -54,7 +54,6 @@ %i.fa.fa-times{ style: 'position: fixed; top: 10; right: 30; color: white;' } = render partial: 'layouts/switch_devise_profile_module' - = render partial: 'layouts/notifications_alert' = render partial: 'layouts/footer', locals: { main_container_size: main_container_size } = render partial: 'layouts/google_analytics' diff --git a/app/views/layouts/new_application.html.haml b/app/views/layouts/new_application.html.haml index 2c9204012..5310f24cf 100644 --- a/app/views/layouts/new_application.html.haml +++ b/app/views/layouts/new_application.html.haml @@ -30,7 +30,6 @@ = yield = render :partial => "layouts/switch_devise_profile_module" - = render :partial => "layouts/notifications_alert" = render partial: "layouts/new_footer" = render partial: "layouts/google_analytics" From a26965f41b991d7a27ce1d497c6a583fc66e937d Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Fri, 5 May 2017 14:37:59 +0200 Subject: [PATCH 35/45] Cable: remove useless js logic --- app/assets/javascripts/cable.js | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 app/assets/javascripts/cable.js diff --git a/app/assets/javascripts/cable.js b/app/assets/javascripts/cable.js deleted file mode 100644 index 32eb6c12f..000000000 --- a/app/assets/javascripts/cable.js +++ /dev/null @@ -1,13 +0,0 @@ -// Action Cable provides the framework to deal with WebSockets in Rails. -// You can generate new channels where WebSocket features live using the rails generate channel command. -// -//= require action_cable -//= require_self -//= require_tree ./channels - -//(function() { -// this.App || (this.App = {}); -// -// App.cable = ActionCable.createConsumer(); -// -//}).call(this); From 2668b036b460f596abd9c4670a42a3334ab7d8fd Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Fri, 5 May 2017 14:59:00 +0200 Subject: [PATCH 36/45] Css: add center class in new style --- app/assets/stylesheets/utils.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/utils.scss b/app/assets/stylesheets/utils.scss index cb9f55abd..04a4559bf 100644 --- a/app/assets/stylesheets/utils.scss +++ b/app/assets/stylesheets/utils.scss @@ -9,3 +9,7 @@ .clearfix { clear: both; } + +.center { + text-align: center; +} From bf68814f7a97e6819fdaf9ba66e9a403637a9dd6 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Fri, 5 May 2017 14:55:05 +0200 Subject: [PATCH 37/45] Css: add alert css to new style --- app/assets/stylesheets/_colors.scss | 3 +++ app/assets/stylesheets/new_alert.scss | 10 ++++++++++ app/assets/stylesheets/new_application.scss | 1 + 3 files changed, 14 insertions(+) create mode 100644 app/assets/stylesheets/new_alert.scss diff --git a/app/assets/stylesheets/_colors.scss b/app/assets/stylesheets/_colors.scss index 0d72dde62..c53a09506 100644 --- a/app/assets/stylesheets/_colors.scss +++ b/app/assets/stylesheets/_colors.scss @@ -3,3 +3,6 @@ $light-blue: rgba(61, 149, 236, 0.8); $black: #333333; $grey: #999999; $light-grey: #F8F8F8; +$dark-red: #A94442; +$ligt-red: #EBCCD1; +$lighter-red: #F2DEDE; diff --git a/app/assets/stylesheets/new_alert.scss b/app/assets/stylesheets/new_alert.scss new file mode 100644 index 000000000..bf176c628 --- /dev/null +++ b/app/assets/stylesheets/new_alert.scss @@ -0,0 +1,10 @@ +.alert { + padding: 15px; + border: 1px solid transparent; +} + +.alert-danger { + background-color: $lighter-red; + border-color: $light-red; + color: $dark-red; +} diff --git a/app/assets/stylesheets/new_application.scss b/app/assets/stylesheets/new_application.scss index 839ecd613..db2e8c65c 100644 --- a/app/assets/stylesheets/new_application.scss +++ b/app/assets/stylesheets/new_application.scss @@ -3,6 +3,7 @@ // = require common // = require utils // = require fonts +// = require new_alert // = require new_header // = require new_footer // = require landing From 029186fdf76fd2c41998774bf4e9ff3c64029861 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Tue, 9 May 2017 12:18:52 +0200 Subject: [PATCH 38/45] Css: fix color import --- app/assets/stylesheets/_colors.scss | 2 +- app/assets/stylesheets/new_alert.scss | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/_colors.scss b/app/assets/stylesheets/_colors.scss index c53a09506..8661f29b0 100644 --- a/app/assets/stylesheets/_colors.scss +++ b/app/assets/stylesheets/_colors.scss @@ -4,5 +4,5 @@ $black: #333333; $grey: #999999; $light-grey: #F8F8F8; $dark-red: #A94442; -$ligt-red: #EBCCD1; +$light-red: #EBCCD1; $lighter-red: #F2DEDE; diff --git a/app/assets/stylesheets/new_alert.scss b/app/assets/stylesheets/new_alert.scss index bf176c628..c57594c31 100644 --- a/app/assets/stylesheets/new_alert.scss +++ b/app/assets/stylesheets/new_alert.scss @@ -1,3 +1,5 @@ +@import "colors"; + .alert { padding: 15px; border: 1px solid transparent; From 9f1217c84372dc7da0df4ad88ca7e7a02587a327 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Fri, 5 May 2017 13:59:32 +0200 Subject: [PATCH 39/45] FlashMessage: center flash message otherwise the #flash_message.center is useless --- app/views/layouts/_flash_messages.html.haml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/views/layouts/_flash_messages.html.haml b/app/views/layouts/_flash_messages.html.haml index a661dcdbd..730c11fde 100644 --- a/app/views/layouts/_flash_messages.html.haml +++ b/app/views/layouts/_flash_messages.html.haml @@ -1,7 +1,8 @@ -#flash_message.center -- if flash.notice - .alert.alert-success - = flash.notice -- if flash.alert - .alert.alert-danger - = flash.alert.html_safe +- if flash.notice.present? || flash.alert.present? + #flash_message.center + - if flash.notice.present? + .alert.alert-success + = flash.notice + - if flash.alert.present? + .alert.alert-danger + = flash.alert.html_safe From 5d915ada8897f58ea0dd13c1362ea197abaa17cf Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Fri, 5 May 2017 12:29:19 +0200 Subject: [PATCH 40/45] Css: add border on header and footer Remove headers border on homepage --- app/assets/stylesheets/_colors.scss | 1 + app/assets/stylesheets/new_footer.scss | 1 + app/assets/stylesheets/new_header.scss | 4 ++++ app/views/layouts/_new_header.haml | 2 +- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/_colors.scss b/app/assets/stylesheets/_colors.scss index 8661f29b0..ab61a6c21 100644 --- a/app/assets/stylesheets/_colors.scss +++ b/app/assets/stylesheets/_colors.scss @@ -3,6 +3,7 @@ $light-blue: rgba(61, 149, 236, 0.8); $black: #333333; $grey: #999999; $light-grey: #F8F8F8; +$border-grey: #CCCCCC; $dark-red: #A94442; $light-red: #EBCCD1; $lighter-red: #F2DEDE; diff --git a/app/assets/stylesheets/new_footer.scss b/app/assets/stylesheets/new_footer.scss index de93cd97d..ccfab7146 100644 --- a/app/assets/stylesheets/new_footer.scss +++ b/app/assets/stylesheets/new_footer.scss @@ -6,6 +6,7 @@ .footer { @include vertical-padding(72px); background-color: $light-grey; + border-top: 1px solid $border-grey; } .footer-inner-content { diff --git a/app/assets/stylesheets/new_header.scss b/app/assets/stylesheets/new_header.scss index 3213bb3c1..a76bbf9a1 100644 --- a/app/assets/stylesheets/new_header.scss +++ b/app/assets/stylesheets/new_header.scss @@ -8,6 +8,10 @@ background-color: #FFFFFF; } +.new-header-with-border { + border-bottom: 1px solid $border-grey; +} + .header-inner-content { width: $page-width; margin: 0 auto; diff --git a/app/views/layouts/_new_header.haml b/app/views/layouts/_new_header.haml index 73f1946c6..82554fd60 100644 --- a/app/views/layouts/_new_header.haml +++ b/app/views/layouts/_new_header.haml @@ -1,4 +1,4 @@ -.new-header +.new-header{ class: current_page?(root_path) ? nil : 'new-header-with-border' } .header-inner-content %img.header-logo.pull-left{ src: image_url("header/logo-tps.svg") } From ecca3b3f372f7358b67bba9042af81b83a75ec2f Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Fri, 5 May 2017 12:36:33 +0200 Subject: [PATCH 41/45] Add a missing test for _pieces_justificatives.html.haml --- .../_pieces_justificatives.html.haml_spec.rb | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 spec/views/users/description/_pieces_justificatives.html.haml_spec.rb diff --git a/spec/views/users/description/_pieces_justificatives.html.haml_spec.rb b/spec/views/users/description/_pieces_justificatives.html.haml_spec.rb new file mode 100644 index 000000000..415f3acd6 --- /dev/null +++ b/spec/views/users/description/_pieces_justificatives.html.haml_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe 'users/description/_pieces_justificatives.html.haml', type: :view do + let!(:procedure) { create(:procedure) } + let!(:tpj1) { create(:type_de_piece_justificative, + procedure: procedure, + libelle: "Première pièce jointe", + order_place: 1, + mandatory: true + )} + let!(:tpj2) { create(:type_de_piece_justificative, + procedure: procedure, + libelle: "Seconde pièce jointe", + order_place: 2, + lien_demarche: "https://www.google.fr" + )} + let!(:dossier) { create(:dossier, :procedure => procedure) } + + before do + render 'users/description/pieces_justificatives.html.haml', dossier: dossier + end + + it 'should render two PJ with their title, mandatory status and description' do + expect(rendered).to include("Première pièce jointe *") + expect(rendered).to include("Seconde pièce jointe") + expect(rendered.index("Première pièce jointe")).to be < rendered.index("Seconde pièce jointe") + + expect(rendered).to have_selector("input[type=file]", count: 2) + end +end From 1a5f9fd06778a3f91b0fa755c0f36bf0c421abd7 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Fri, 5 May 2017 12:37:11 +0200 Subject: [PATCH 42/45] =?UTF-8?q?[Fix=20#105]=20Show=20the=20pieces=20just?= =?UTF-8?q?ificative=E2=80=99=20descriptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/stylesheets/description.scss | 8 ++++++++ .../users/description/_pieces_justificatives.html.haml | 2 ++ .../description/_pieces_justificatives.html.haml_spec.rb | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/app/assets/stylesheets/description.scss b/app/assets/stylesheets/description.scss index 6ad2f4339..3efa4d01b 100644 --- a/app/assets/stylesheets/description.scss +++ b/app/assets/stylesheets/description.scss @@ -138,3 +138,11 @@ width: 160px; } } + +.piece-description { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; + font-weight: normal; +} diff --git a/app/views/users/description/_pieces_justificatives.html.haml b/app/views/users/description/_pieces_justificatives.html.haml index d480fdbf8..75e7054e1 100644 --- a/app/views/users/description/_pieces_justificatives.html.haml +++ b/app/views/users/description/_pieces_justificatives.html.haml @@ -22,6 +22,8 @@ %tr %th.piece-libelle = tpj.mandatory ? tpj.libelle + ' *' : tpj.libelle + %br + .piece-description= tpj.description %td - unless tpj.lien_demarche.blank? diff --git a/spec/views/users/description/_pieces_justificatives.html.haml_spec.rb b/spec/views/users/description/_pieces_justificatives.html.haml_spec.rb index 415f3acd6..d0bcacd86 100644 --- a/spec/views/users/description/_pieces_justificatives.html.haml_spec.rb +++ b/spec/views/users/description/_pieces_justificatives.html.haml_spec.rb @@ -5,12 +5,14 @@ describe 'users/description/_pieces_justificatives.html.haml', type: :view do let!(:tpj1) { create(:type_de_piece_justificative, procedure: procedure, libelle: "Première pièce jointe", + description: "Première description", order_place: 1, mandatory: true )} let!(:tpj2) { create(:type_de_piece_justificative, procedure: procedure, libelle: "Seconde pièce jointe", + description: "Seconde description", order_place: 2, lien_demarche: "https://www.google.fr" )} @@ -25,6 +27,9 @@ describe 'users/description/_pieces_justificatives.html.haml', type: :view do expect(rendered).to include("Seconde pièce jointe") expect(rendered.index("Première pièce jointe")).to be < rendered.index("Seconde pièce jointe") + expect(rendered).to include("Première description") + expect(rendered).to include("Seconde description") + expect(rendered).to have_selector("input[type=file]", count: 2) end end From c6d0ea76bbddb90369db0abdf4db73c3a34b638a Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Fri, 5 May 2017 16:45:49 +0200 Subject: [PATCH 43/45] [Fix #174] Make .default-data-block header titles take the full width --- app/assets/stylesheets/default_data_block.scss | 8 ++++++-- .../users/description/champs/_header_section.html.haml | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/default_data_block.scss b/app/assets/stylesheets/default_data_block.scss index 1f37e839f..dbf7c0bd5 100644 --- a/app/assets/stylesheets/default_data_block.scss +++ b/app/assets/stylesheets/default_data_block.scss @@ -33,7 +33,7 @@ .header { background-color: #003C92; - height: 40px; + min-height: 40px; color: #FFFFFF; font-size: 18px; font-weight: bold; @@ -42,7 +42,6 @@ .title-no-expanse, .action, .count { - height: 100%; line-height: 40px; padding: 0px; text-transform: uppercase; @@ -58,6 +57,11 @@ cursor: pointer; } + .title-content { + width: calc(100% - 50px); + float: left; + } + .action { background-color: #E45B51; text-align: center; diff --git a/app/views/users/description/champs/_header_section.html.haml b/app/views/users/description/champs/_header_section.html.haml index b75094c2a..cafbe73ae 100644 --- a/app/views/users/description/champs/_header_section.html.haml +++ b/app/views/users/description/champs/_header_section.html.haml @@ -4,6 +4,8 @@ .col-xs-12.title .carret-right .carret-down - = libelle + .title-content + = libelle + .clearfix .body = render partial: 'users/description/champs/render_list_champs', locals: { champs: champs, order_place: order_place } From 38480ef3edee34bedd12ff86b14e3e1230d95166 Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Tue, 9 May 2017 16:39:39 +0200 Subject: [PATCH 44/45] Remove dead code --- .../backoffice/dossiers_controller_spec.rb | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/spec/controllers/backoffice/dossiers_controller_spec.rb b/spec/controllers/backoffice/dossiers_controller_spec.rb index ea7953672..7ba92db57 100644 --- a/spec/controllers/backoffice/dossiers_controller_spec.rb +++ b/spec/controllers/backoffice/dossiers_controller_spec.rb @@ -129,19 +129,6 @@ describe Backoffice::DossiersController, type: :controller do end end - describe 'GET #fige' do - context 'when gestionnaire is connected' do - before do - sign_in gestionnaire - end - - it 'returns http success' do - get :index, params: {liste: :fige} - expect(response).to have_http_status(302) - end - end - end - describe 'GET #termine' do context 'when gestionnaire is connected' do before do From 054afb40a49b031ae315044a24c8afa584b5e5ab Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Tue, 9 May 2017 23:05:45 +0200 Subject: [PATCH 45/45] [Fix #50, fix #239] Install chartkick the right way --- app/assets/javascripts/application.js | 2 + app/views/admin/procedures/show.html.haml | 1 - app/views/stats/index.html.haml | 2 - vendor/assets/javascripts/highcharts.js | 396 ++++++++++++++++++++++ 4 files changed, 398 insertions(+), 3 deletions(-) create mode 100644 vendor/assets/javascripts/highcharts.js diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 5f6f5aebd..f17bf80df 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -13,6 +13,8 @@ //= require jquery //= require jquery_ujs //= require turbolinks +//= require highcharts +//= require chartkick //= require_tree . //= require bootstrap-sprockets //= require bootstrap-datepicker/core diff --git a/app/views/admin/procedures/show.html.haml b/app/views/admin/procedures/show.html.haml index cce49b7a2..10d45504e 100644 --- a/app/views/admin/procedures/show.html.haml +++ b/app/views/admin/procedures/show.html.haml @@ -125,7 +125,6 @@ .col-xs-5 %h4 Non archivés - = javascript_include_tag "https://code.highcharts.com/highcharts.js", "chartkick" - if @facade.dossiers_for_pie_highchart.blank? Aucune statistique pour le moment - else diff --git a/app/views/stats/index.html.haml b/app/views/stats/index.html.haml index b2e297797..c3d40561a 100644 --- a/app/views/stats/index.html.haml +++ b/app/views/stats/index.html.haml @@ -1,5 +1,3 @@ -= javascript_include_tag 'https://code.highcharts.com/highcharts.js', 'chartkick', "data-turbolinks-track" => true - .statistiques %h1.new-h1 Statistiques diff --git a/vendor/assets/javascripts/highcharts.js b/vendor/assets/javascripts/highcharts.js new file mode 100644 index 000000000..6bd0efc23 --- /dev/null +++ b/vendor/assets/javascripts/highcharts.js @@ -0,0 +1,396 @@ +/* + Highcharts JS v5.0.11 (2017-05-04) + + (c) 2009-2016 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(L,S){"object"===typeof module&&module.exports?module.exports=L.document?S(L):S:L.Highcharts=S(L)})("undefined"!==typeof window?window:this,function(L){L=function(){var a=window,D=a.document,A=a.navigator&&a.navigator.userAgent||"",G=D&&D.createElementNS&&!!D.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,F=/(edge|msie|trident)/i.test(A)&&!window.opera,n=!G,f=/Firefox/.test(A),h=f&&4>parseInt(A.split("Firefox/")[1],10);return a.Highcharts?a.Highcharts.error(16,!0):{product:"Highcharts", +version:"5.0.11",deg2rad:2*Math.PI/360,doc:D,hasBidiBug:h,hasTouch:D&&void 0!==D.documentElement.ontouchstart,isMS:F,isWebKit:/AppleWebKit/.test(A),isFirefox:f,isTouchDevice:/(Mobile|Android|Windows Phone)/.test(A),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:G,vml:n,win:a,marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){},charts:[]}}();(function(a){var D=[],A=a.charts,G=a.doc,F=a.win;a.error=function(n,f){n=a.isNumber(n)?"Highcharts error #"+ +n+": www.highcharts.com/errors/"+n:n;if(f)throw Error(n);F.console&&console.log(n)};a.Fx=function(a,f,h){this.options=f;this.elem=a;this.prop=h};a.Fx.prototype={dSetter:function(){var a=this.paths[0],f=this.paths[1],h=[],l=this.now,w=a.length,t;if(1===l)h=this.toD;else if(w===f.length&&1>l)for(;w--;)t=parseFloat(a[w]),h[w]=isNaN(t)?a[w]:l*parseFloat(f[w]-t)+t;else h=f;this.elem.attr("d",h,null,!0)},update:function(){var a=this.elem,f=this.prop,h=this.now,l=this.options.step;if(this[f+"Setter"])this[f+ +"Setter"]();else a.attr?a.element&&a.attr(f,h,null,!0):a.style[f]=h+this.unit;l&&l.call(a,h,this)},run:function(a,f,h){var n=this,w=function(a){return w.stopped?!1:n.step(a)},t;this.startTime=+new Date;this.start=a;this.end=f;this.unit=h;this.now=this.start;this.pos=0;w.elem=this.elem;w.prop=this.prop;w()&&1===D.push(w)&&(w.timerId=setInterval(function(){for(t=0;t=e+this.startTime?(this.now=this.end,this.pos=1,this.update(),h=d[this.prop]=!0,a.objectEach(d,function(a){!0!==a&&(h=!1)}),h&&t&&t.call(w),n=!1):(this.pos=l.easing((f-this.startTime)/e),this.now=this.start+(this.end-this.start)*this.pos,this.update(),n=!0);return n},initPath:function(n,f,h){function l(a){var b,c;for(u=a.length;u--;)b="M"===a[u]||"L"===a[u],c=/[a-zA-Z]/.test(a[u+3]),b&&c&&a.splice(u+1,0,a[u+1],a[u+2],a[u+1],a[u+2])} +function w(a,c){for(;a.lengtht?"AM":"PM",P:12>t?"am":"pm",S:u(w.getSeconds()),L:u(Math.round(f%1E3),3)},a.dateFormats);a.objectEach(l,function(a,b){for(;-1!==n.indexOf("%"+b);)n=n.replace("%"+b,"function"===typeof a?a(f):a)});return h?n.substr(0,1).toUpperCase()+n.substr(1):n};a.formatSingle=function(n,f){var h=/\.([0-9])/,l=a.defaultOptions.lang;/f$/.test(n)?(h=(h= +n.match(h))?h[1]:-1,null!==f&&(f=a.numberFormat(f,h,l.decimalPoint,-1=h&&(f=[1/h])));for(l=0;l=n||!w&&t<=(f[l]+(f[l+1]||f[l]))/2);l++);return e=a.correctFloat(e*h,-Math.round(Math.log(.001)/Math.LN10))};a.stableSort=function(a,f){var h=a.length,l,n;for(n=0;nh&&(h=a[f]);return h};a.destroyObjectProperties=function(n,f){a.objectEach(n,function(a,l){a&&a!==f&&a.destroy&&a.destroy();delete n[l]})};a.discardElement=function(n){var f=a.garbageBin;f||(f=a.createElement("div"));n&&f.appendChild(n);f.innerHTML=""};a.correctFloat=function(a,f){return parseFloat(a.toPrecision(f|| +14))};a.setAnimation=function(n,f){f.renderer.globalAnimation=a.pick(n,f.options.chart.animation,!0)};a.animObject=function(n){return a.isObject(n)?a.merge(n):{duration:n?500:0}};a.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5};a.numberFormat=function(n,f,h,l){n=+n||0;f=+f;var w=a.defaultOptions.lang,t=(n.toString().split(".")[1]||"").length,e,d;-1===f?f=Math.min(t,20):a.isNumber(f)||(f=2);d=(Math.abs(n)+Math.pow(10,-Math.max(f,t)-1)).toFixed(f); +t=String(a.pInt(d));e=3n?"-":"")+(e?t.substr(0,e)+l:"");n+=t.substr(e).replace(/(\d{3})(?=\d)/g,"$1"+l);f&&(n+=h+d.slice(-f));return n};Math.easeInOutSine=function(a){return-.5*(Math.cos(Math.PI*a)-1)};a.getStyle=function(n,f,h){if("width"===f)return Math.min(n.offsetWidth,n.scrollWidth)-a.getStyle(n,"padding-left")-a.getStyle(n,"padding-right");if("height"===f)return Math.min(n.offsetHeight,n.scrollHeight)-a.getStyle(n, +"padding-top")-a.getStyle(n,"padding-bottom");if(n=F.getComputedStyle(n,void 0))n=n.getPropertyValue(f),a.pick(h,!0)&&(n=a.pInt(n));return n};a.inArray=function(a,f){return f.indexOf?f.indexOf(a):[].indexOf.call(f,a)};a.grep=function(a,f){return[].filter.call(a,f)};a.find=function(a,f){return[].find.call(a,f)};a.map=function(a,f){for(var h=[],l=0,n=a.length;l>16,(f&65280)>>8,f&255,1]:4===h&&(l=[(f&3840)>>4|(f&3840)>>8,(f&240)>>4|f&240,(f&15)<<4|f&15,1])),!l)for(n=this.parsers.length;n--&&!l;)t=this.parsers[n],(h=t.regex.exec(f))&&(l=t.parse(h));this.rgba=l||[]},get:function(a){var f=this.input,l=this.rgba, +n;this.stops?(n=F(f),n.stops=[].concat(n.stops),D(this.stops,function(f,e){n.stops[e]=[n.stops[e][0],f.get(a)]})):n=l&&A(l[0])?"rgb"===a||!a&&1===l[3]?"rgb("+l[0]+","+l[1]+","+l[2]+")":"a"===a?l[3]:"rgba("+l.join(",")+")":f;return n},brighten:function(a){var f,l=this.rgba;if(this.stops)D(this.stops,function(f){f.brighten(a)});else if(A(a)&&0!==a)for(f=0;3>f;f++)l[f]+=n(255*a),0>l[f]&&(l[f]=0),255v.width)v={width:0,height:0}}else v=this.htmlGetBBox();r.isSVG&&(a=v.width,r=v.height,q&&"11px"===q.fontSize&&17===Math.round(r)&&(v.height=r=14),g&&(v.width=Math.abs(r*Math.sin(c))+Math.abs(a*Math.cos(c)),v.height=Math.abs(r*Math.cos(c))+Math.abs(a*Math.sin(c))));if(y&&0]*>/g,"")))},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,g,b){"string"===typeof a?b.setAttribute(g,a):a&&this.colorGradient(a,g,b)},visibilitySetter:function(a,g,b){"inherit"===a?b.removeAttribute(g):b.setAttribute(g,a)},zIndexSetter:function(a,b){var v=this.renderer, +r=this.parentGroup,c=(r||v).element||v.box,k,q=this.element,p;k=this.added;var d;t(a)&&(q.zIndex=a,a=+a,this[b]===a&&(k=!1),this[b]=a);if(k){(a=this.zIndex)&&r&&(r.handleZ=!0);b=c.childNodes;for(d=0;da||!t(a)&&t(k)||0>a&&!t(k)&&c!==v.box)&&(c.insertBefore(q,r),p=!0);p||c.appendChild(q)}return p},_defaultSetter:function(a,g,b){b.setAttribute(g,a)}};D.prototype.yGetter=D.prototype.xGetter;D.prototype.translateXSetter=D.prototype.translateYSetter=D.prototype.rotationSetter= +D.prototype.verticalAlignSetter=D.prototype.scaleXSetter=D.prototype.scaleYSetter=function(a,g){this[g]=a;this.doTransform=!0};D.prototype["stroke-widthSetter"]=D.prototype.strokeSetter=function(a,g,b){this[g]=a;this.stroke&&this["stroke-width"]?(D.prototype.fillSetter.call(this,this.stroke,"stroke",b),b.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0):"stroke-width"===g&&0===a&&this.hasStroke&&(b.removeAttribute("stroke"),this.hasStroke=!1)};A=a.SVGRenderer=function(){this.init.apply(this, +arguments)};A.prototype={Element:D,SVG_NS:N,init:function(a,g,b,r,c,q){var v;r=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"}).css(this.getStyle(r));v=r.element;a.appendChild(v);-1===a.innerHTML.indexOf("xmlns")&&n(v,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=v;this.boxWrapper=r;this.alignedObjects=[];this.url=(k||M)&&m.getElementsByTagName("base").length?P.location.href.replace(/#.*?$/,"").replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(m.createTextNode("Created with Highcharts 5.0.11")); +this.defs=this.createElement("defs").add();this.allowHTML=q;this.forExport=c;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(g,b,!1);var p;k&&a.getBoundingClientRect&&(g=function(){l(a,{left:0,top:0});p=a.getBoundingClientRect();l(a,{left:Math.ceil(p.left)-p.left+"px",top:Math.ceil(p.top)-p.top+"px"})},g(),this.unSubPixelFix=G(P,"resize",g))},getStyle:function(a){return this.style=b({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"}, +a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();d(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy());this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var g=new this.Element;g.init(this,a);return g},draw:y,getRadialAttr:function(a,g){return{cx:a[0]-a[2]/2+g.cx*a[2],cy:a[1]- +a[2]/2+g.cy*a[2],r:g.r*a[2]}},getSpanWidth:function(a,g){var b=a.getBBox(!0).width;!J&&this.forExport&&(b=this.measureSpanWidth(g.firstChild.data,a.styles));return b},applyEllipsis:function(a,g,b,r){var v=this.getSpanWidth(a,g),c=v>r,v=b,k,q=0,p=b.length,d=function(a){g.removeChild(g.firstChild);a&&g.appendChild(m.createTextNode(a))};if(c){for(;q<=p;)k=Math.ceil((q+p)/2),v=b.substring(0,k)+"\u2026",d(v),v=this.getSpanWidth(a,g),q===p?q=p+1:v>r?p=k-1:q=k;0===p&&d("")}return c},buildText:function(a){var b= +a.element,r=this,v=r.forExport,k=K(a.textStr,"").toString(),q=-1!==k.indexOf("\x3c"),p=b.childNodes,d,e,u,y,x=n(b,"x"),E=a.styles,z=a.textWidth,f=E&&E.lineHeight,H=E&&E.textOutline,B=E&&"ellipsis"===E.textOverflow,h=E&&"nowrap"===E.whiteSpace,t=E&&E.fontSize,R,w,M=p.length,E=z&&!a.added&&this.box,I=function(a){var v;v=/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:t||r.style.fontSize||12;return f?g(f):r.fontMetrics(v,a.getAttribute("style")?a:b).h};R=[k,B,h,f,H,t,z].join();if(R!==a.textCache){for(a.textCache= +R;M--;)b.removeChild(p[M]);q||H||B||z||-1!==k.indexOf(" ")?(d=/<.*class="([^"]+)".*>/,e=/<.*style="([^"]+)".*>/,u=/<.*href="(http[^"]+)".*>/,E&&E.appendChild(b),k=q?k.replace(/<(b|strong)>/g,'\x3cspan style\x3d"font-weight:bold"\x3e').replace(/<(i|em)>/g,'\x3cspan style\x3d"font-style:italic"\x3e').replace(//g,"\x3c/span\x3e").split(//g):[k],k=c(k,function(a){return""!==a}),C(k,function(g,c){var k,q=0;g=g.replace(/^\s+|\s+$/g,"").replace(//g,"\x3c/span\x3e|||");k=g.split("|||");C(k,function(g){if(""!==g||1===k.length){var p={},E=m.createElementNS(r.SVG_NS,"tspan"),f,H;d.test(g)&&(f=g.match(d)[1],n(E,"class",f));e.test(g)&&(H=g.match(e)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),n(E,"style",H));u.test(g)&&!v&&(n(E,"onclick",'location.href\x3d"'+g.match(u)[1]+'"'),l(E,{cursor:"pointer"}));g=(g.replace(/<(.|\n)*?>/g,"")||" ").replace(/</g,"\x3c").replace(/>/g,"\x3e");if(" "!==g){E.appendChild(m.createTextNode(g)); +q?p.dx=0:c&&null!==x&&(p.x=x);n(E,p);b.appendChild(E);!q&&w&&(!J&&v&&l(E,{display:"block"}),n(E,"dy",I(E)));if(z){p=g.replace(/([^\^])-/g,"$1- ").split(" ");f=1z,void 0===y&&(y=g),g&&1!==p.length?(E.removeChild(E.firstChild),C.unshift(p.pop())):(p=C,C=[],p.length&&!h&&(E=m.createElementNS(N,"tspan"),n(E,{dy:t,x:x}),H&&n(E,"style",H),b.appendChild(E)), +Q>z&&(z=Q)),p.length&&E.appendChild(m.createTextNode(p.join(" ").replace(/- /g,"-")));a.rotation=R}q++}}});w=w||b.childNodes.length}),y&&a.attr("title",a.textStr),E&&E.removeChild(b),H&&a.applyTextOutline&&a.applyTextOutline(H)):b.appendChild(m.createTextNode(k.replace(/</g,"\x3c").replace(/>/g,"\x3e")))}},getContrast:function(a){a=h(a).rgba;return 510b?c>g+q&&cp?c>g+q&&cr&&p>a+q&&pc&&p>a+q&&pa?a+3:Math.round(1.2*a);return{h:b,b:Math.round(.8*b),f:a}},rotCorr:function(a,g,b){var r=a;g&&b&&(r=Math.max(r*Math.cos(g*e),4));return{x:-a/3*Math.sin(g*e),y:r}},label:function(g,c,k,p,d,e,E,u,m){var v=this,y=v.g("button"!==m&&"label"),x=y.text=v.text("",0,0,E).attr({zIndex:1}),z,J,f=0,H=3,l=0,B,h,n,R,w,M={},I,N,K=/^url\((.*?)\)$/.test(p),Q=K,U,T,O,P;m&&y.addClass("highcharts-"+m);Q=K;U=function(){return(I|| +0)%2/2};T=function(){var a=x.element.style,g={};J=(void 0===B||void 0===h||w)&&t(x.textStr)&&x.getBBox();y.width=(B||J.width||0)+2*H+l;y.height=(h||J.height||0)+2*H;N=H+v.fontMetrics(a&&a.fontSize,x).b;Q&&(z||(y.box=z=v.symbols[p]||K?v.symbol(p):v.rect(),z.addClass(("button"===m?"":"highcharts-label-box")+(m?" highcharts-"+m+"-box":"")),z.add(y),a=U(),g.x=a,g.y=(u?-N:0)+a),g.width=Math.round(y.width),g.height=Math.round(y.height),z.attr(b(g,M)),M={})};O=function(){var a=l+H,g;g=u?0:N;t(B)&&J&&("center"=== +w||"right"===w)&&(a+={center:.5,right:1}[w]*(B-J.width));if(a!==x.x||g!==x.y)x.attr("x",a),void 0!==g&&x.attr("y",g);x.x=a;x.y=g};P=function(a,g){z?z.attr(a,g):M[a]=g};y.onAdd=function(){x.add(y);y.attr({text:g||0===g?g:"",x:c,y:k});z&&t(d)&&y.attr({anchorX:d,anchorY:e})};y.widthSetter=function(g){B=a.isNumber(g)?g:null};y.heightSetter=function(a){h=a};y["text-alignSetter"]=function(a){w=a};y.paddingSetter=function(a){t(a)&&a!==H&&(H=y.padding=a,O())};y.paddingLeftSetter=function(a){t(a)&&a!==l&& +(l=a,O())};y.alignSetter=function(a){a={left:0,center:.5,right:1}[a];a!==f&&(f=a,J&&y.attr({x:n}))};y.textSetter=function(a){void 0!==a&&x.textSetter(a);T();O()};y["stroke-widthSetter"]=function(a,g){a&&(Q=!0);I=this["stroke-width"]=a;P(g,a)};y.strokeSetter=y.fillSetter=y.rSetter=function(a,g){"fill"===g&&a&&(Q=!0);P(g,a)};y.anchorXSetter=function(a,g){d=y.anchorX=a;P(g,Math.round(a)-U()-n)};y.anchorYSetter=function(a,g){e=y.anchorY=a;P(g,a-R)};y.xSetter=function(a){y.x=a;f&&(a-=f*((B||J.width)+2* +H));n=Math.round(a);y.attr("translateX",n)};y.ySetter=function(a){R=y.y=Math.round(a);y.attr("translateY",R)};var V=y.css;return b(y,{css:function(a){if(a){var g={};a=q(a);C(y.textProps,function(b){void 0!==a[b]&&(g[b]=a[b],delete a[b])});x.css(g)}return V.call(y,a)},getBBox:function(){return{width:J.width+2*H,height:J.height+2*H,x:J.x-H,y:J.y-H}},shadow:function(a){a&&(T(),z&&z.shadow(a));return y},destroy:function(){r(y.element,"mouseenter");r(y.element,"mouseleave");x&&(x=x.destroy());z&&(z=z.destroy()); +D.prototype.destroy.call(y);y=v=T=O=P=null}})}};a.Renderer=A})(L);(function(a){var D=a.attr,A=a.createElement,G=a.css,F=a.defined,n=a.each,f=a.extend,h=a.isFirefox,l=a.isMS,w=a.isWebKit,t=a.pInt,e=a.SVGRenderer,d=a.win,m=a.wrap;f(a.SVGElement.prototype,{htmlCss:function(a){var b=this.element;if(b=a&&"SPAN"===b.tagName&&a.width)delete a.width,this.textWidth=b,this.updateTransform();a&&"ellipsis"===a.textOverflow&&(a.whiteSpace="nowrap",a.overflow="hidden");this.styles=f(this.styles,a);G(this.element, +a);return this},htmlGetBBox:function(){var a=this.element;"text"===a.nodeName&&(a.style.position="absolute");return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}},htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,d=this.translateX||0,c=this.translateY||0,e=this.x||0,m=this.y||0,f=this.textAlign||"left",k={left:0,center:.5,right:1}[f],E=this.styles;G(b,{marginLeft:d,marginTop:c});this.shadows&&n(this.shadows,function(a){G(a,{marginLeft:d+1,marginTop:c+ +1})});this.inverted&&n(b.childNodes,function(c){a.invertChild(c,b)});if("SPAN"===b.tagName){var p=this.rotation,z=t(this.textWidth),l=E&&E.whiteSpace,q=[p,f,b.innerHTML,this.textWidth,this.textAlign].join();q!==this.cTT&&(E=a.fontMetrics(b.style.fontSize).b,F(p)&&this.setSpanRotation(p,k,E),G(b,{width:"",whiteSpace:l||"nowrap"}),b.offsetWidth>z&&/[ \-]/.test(b.textContent||b.innerText)&&G(b,{width:z+"px",display:"block",whiteSpace:l||"normal"}),this.getSpanCorrection(b.offsetWidth,E,k,p,f));G(b,{left:e+ +(this.xCorr||0)+"px",top:m+(this.yCorr||0)+"px"});w&&(E=b.offsetHeight);this.cTT=q}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,e){var c={},u=l?"-ms-transform":w?"-webkit-transform":h?"MozTransform":d.opera?"-o-transform":"";c[u]=c.transform="rotate("+a+"deg)";c[u+(h?"Origin":"-origin")]=c.transformOrigin=100*b+"% "+e+"px";G(this.element,c)},getSpanCorrection:function(a,b,d){this.xCorr=-a*d;this.yCorr=-b}});f(e.prototype,{html:function(a,b,d){var c=this.createElement("span"),e=c.element, +x=c.renderer,l=x.isSVG,k=function(a,b){n(["opacity","visibility"],function(c){m(a,c+"Setter",function(a,c,k,p){a.call(this,c,k,p);b[k]=c})})};c.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;e.innerHTML=this.textStr=a;c.htmlUpdateTransform()};l&&k(c,c.element.style);c.xSetter=c.ySetter=c.alignSetter=c.rotationSetter=function(a,b){"align"===b&&(b="textAlign");c[b]=a;c.htmlUpdateTransform()};c.attr({text:a,x:Math.round(b),y:Math.round(d)}).css({fontFamily:this.style.fontFamily,fontSize:this.style.fontSize, +position:"absolute"});e.style.whiteSpace="nowrap";c.css=c.htmlCss;l&&(c.add=function(a){var b,d=x.box.parentNode,m=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)m.push(a),a=a.parentGroup;n(m.reverse(),function(a){var p,q=D(a.element,"class");q&&(q={className:q});b=a.div=a.div||A("div",q,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",display:a.display,opacity:a.opacity,pointerEvents:a.styles&&a.styles.pointerEvents},b||d);p=b.style;f(a,{on:function(){c.on.apply({element:m[0].div}, +arguments);return a},translateXSetter:function(b,g){p.left=b+"px";a[g]=b;a.doTransform=!0},translateYSetter:function(b,g){p.top=b+"px";a[g]=b;a.doTransform=!0}});k(a,p)})}}else b=d;b.appendChild(e);c.added=!0;c.alignOnAdd&&c.htmlUpdateTransform();return c});return c}})})(L);(function(a){var D,A,G=a.createElement,F=a.css,n=a.defined,f=a.deg2rad,h=a.discardElement,l=a.doc,w=a.each,t=a.erase,e=a.extend;D=a.extendClass;var d=a.isArray,m=a.isNumber,C=a.isObject,b=a.merge;A=a.noop;var x=a.pick,c=a.pInt, +u=a.SVGElement,B=a.SVGRenderer,I=a.win;a.svg||(A={docMode8:l&&8===l.documentMode,init:function(a,b){var c=["\x3c",b,' filled\x3d"f" stroked\x3d"f"'],k=["position: ","absolute",";"],d="div"===b;("shape"===b||d)&&k.push("left:0;top:0;width:1px;height:1px;");k.push("visibility: ",d?"hidden":"visible");c.push(' style\x3d"',k.join(""),'"/\x3e');b&&(c=d||"span"===b||"img"===b?c.join(""):a.prepVML(c),this.element=G(c));this.renderer=a},add:function(a){var b=this.renderer,c=this.element,k=b.box,d=a&&a.inverted, +k=a?a.element||a:k;a&&(this.parentGroup=a);d&&b.invertChild(c,k);k.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();if(this.onAdd)this.onAdd();this.className&&this.attr("class",this.className);return this},updateTransform:u.prototype.htmlUpdateTransform,setSpanRotation:function(){var a=this.rotation,b=Math.cos(a*f),c=Math.sin(a*f);F(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11\x3d",b,", M12\x3d",-c,", M21\x3d",c,", M22\x3d", +b,", sizingMethod\x3d'auto expand')"].join(""):"none"})},getSpanCorrection:function(a,b,c,d,e){var k=d?Math.cos(d*f):1,p=d?Math.sin(d*f):0,m=x(this.elemHeight,this.element.offsetHeight),u;this.xCorr=0>k&&-a;this.yCorr=0>p&&-m;u=0>k*p;this.xCorr+=p*b*(u?1-c:c);this.yCorr-=k*b*(d?u?c:1-c:1);e&&"left"!==e&&(this.xCorr-=a*c*(0>k?-1:1),d&&(this.yCorr-=m*c*(0>p?-1:1)),F(this.element,{textAlign:e}))},pathToVML:function(a){for(var b=a.length,c=[];b--;)m(a[b])?c[b]=Math.round(10*a[b])-5:"Z"===a[b]?c[b]="x": +(c[b]=a[b],!a.isArc||"wa"!==a[b]&&"at"!==a[b]||(c[b+5]===c[b+7]&&(c[b+7]+=a[b+7]>a[b+5]?1:-1),c[b+6]===c[b+8]&&(c[b+8]+=a[b+8]>a[b+6]?1:-1)));return c.join(" ")||"x"},clip:function(a){var b=this,c;a?(c=a.members,t(c,b),c.push(b),b.destroyClip=function(){t(c,b)},a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:b.docMode8?"inherit":"rect(auto)"});return b.css(a)},css:u.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&h(a)},destroy:function(){this.destroyClip&&this.destroyClip();return u.prototype.destroy.apply(this)}, +on:function(a,b){this.element["on"+a]=function(){var a=I.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,b){var k;a=a.split(/[ ,]/);k=a.length;if(9===k||11===k)a[k-4]=a[k-2]=c(a[k-2])-10*b;return a.join(" ")},shadow:function(a,b,d){var k=[],p,q=this.element,e=this.renderer,m,u=q.style,g,r=q.path,f,J,E,l;r&&"string"!==typeof r.value&&(r="x");J=r;if(a){E=x(a.width,3);l=(a.opacity||.15)/E;for(p=1;3>=p;p++)f=2*E+1-2*p,d&&(J=this.cutOffPath(r.value,f+.5)),g=['\x3cshape isShadow\x3d"true" strokeweight\x3d"', +f,'" filled\x3d"false" path\x3d"',J,'" coordsize\x3d"10 10" style\x3d"',q.style.cssText,'" /\x3e'],m=G(e.prepVML(g),null,{left:c(u.left)+x(a.offsetX,1),top:c(u.top)+x(a.offsetY,1)}),d&&(m.cutOff=f+1),g=['\x3cstroke color\x3d"',a.color||"#000000",'" opacity\x3d"',l*p,'"/\x3e'],G(e.prepVML(g),null,null,m),b?b.element.appendChild(m):q.parentNode.insertBefore(m,q),k.push(m);this.shadows=k}return this},updateShadows:A,setAttr:function(a,b){this.docMode8?this.element[a]=b:this.element.setAttribute(a,b)}, +classSetter:function(a){(this.added?this.element:this).className=a},dashstyleSetter:function(a,b,c){(c.getElementsByTagName("stroke")[0]||G(this.renderer.prepVML(["\x3cstroke/\x3e"]),null,null,c))[b]=a||"solid";this[b]=a},dSetter:function(a,b,c){var k=this.shadows;a=a||[];this.d=a.join&&a.join(" ");c.path=a=this.pathToVML(a);if(k)for(c=k.length;c--;)k[c].path=k[c].cutOff?this.cutOffPath(a,k[c].cutOff):a;this.setAttr(b,a)},fillSetter:function(a,b,c){var k=c.nodeName;"SPAN"===k?c.style.color=a:"IMG"!== +k&&(c.filled="none"!==a,this.setAttr("fillcolor",this.renderer.color(a,c,b,this)))},"fill-opacitySetter":function(a,b,c){G(this.renderer.prepVML(["\x3c",b.split("-")[0],' opacity\x3d"',a,'"/\x3e']),null,null,c)},opacitySetter:A,rotationSetter:function(a,b,c){c=c.style;this[b]=c[b]=a;c.left=-Math.round(Math.sin(a*f)+1)+"px";c.top=Math.round(Math.cos(a*f))+"px"},strokeSetter:function(a,b,c){this.setAttr("strokecolor",this.renderer.color(a,c,b,this))},"stroke-widthSetter":function(a,b,c){c.stroked=!!a; +this[b]=a;m(a)&&(a+="px");this.setAttr("strokeweight",a)},titleSetter:function(a,b){this.setAttr(b,a)},visibilitySetter:function(a,b,c){"inherit"===a&&(a="visible");this.shadows&&w(this.shadows,function(c){c.style[b]=a});"DIV"===c.nodeName&&(a="hidden"===a?"-999em":0,this.docMode8||(c.style[b]=a?"visible":"hidden"),b="top");c.style[b]=a},xSetter:function(a,b,c){this[b]=a;"x"===b?b="left":"y"===b&&(b="top");this.updateClipping?(this[b]=a,this.updateClipping()):c.style[b]=a},zIndexSetter:function(a, +b,c){c.style[b]=a}},A["stroke-opacitySetter"]=A["fill-opacitySetter"],a.VMLElement=A=D(u,A),A.prototype.ySetter=A.prototype.widthSetter=A.prototype.heightSetter=A.prototype.xSetter,A={Element:A,isIE8:-1C[0]&&b.push([1,C[1]]);w(b,function(g,b){p.test(g[1])?(q=a.color(g[1]), +r=q.get("rgb"),x=q.get("a")):(r=g[1],x=1);h.push(100*g[0]+"% "+r);b?(l=x,v=r):(z=x,B=r)});if("fill"===d)if("gradient"===u)d=J.x1||J[0]||0,b=J.y1||J[1]||0,f=J.x2||J[2]||0,J=J.y2||J[3]||0,E='angle\x3d"'+(90-180*Math.atan((J-b)/(f-d))/Math.PI)+'"',t();else{var g=J.r,n=2*g,I=2*g,A=J.cx,D=J.cy,F=c.radialReference,L,g=function(){F&&(L=e.getBBox(),A+=(F[0]-L.x)/L.width-.5,D+=(F[1]-L.y)/L.height-.5,n*=F[2]/L.width,I*=F[2]/L.height);E='src\x3d"'+a.getOptions().global.VMLRadialGradientURL+'" size\x3d"'+n+","+ +I+'" origin\x3d"0.5,0.5" position\x3d"'+A+","+D+'" color2\x3d"'+B+'" ';t()};e.added?g():e.onAdd=g;g=v}else g=r}else p.test(b)&&"IMG"!==c.tagName?(q=a.color(b),e[d+"-opacitySetter"](q.get("a"),d,c),g=q.get("rgb")):(g=c.getElementsByTagName(d),g.length&&(g[0].opacity=1,g[0].type="solid"),g=b);return g},prepVML:function(a){var b=this.isIE8;a=a.join("");b?(a=a.replace("/\x3e",' xmlns\x3d"urn:schemas-microsoft-com:vml" /\x3e'),a=-1===a.indexOf('style\x3d"')?a.replace("/\x3e",' style\x3d"display:inline-block;behavior:url(#default#VML);" /\x3e'): +a.replace('style\x3d"','style\x3d"display:inline-block;behavior:url(#default#VML);')):a=a.replace("\x3c","\x3chcv:");return a},text:B.prototype.html,path:function(a){var b={coordsize:"10 10"};d(a)?b.d=a:C(a)&&e(b,a);return this.createElement("shape").attr(b)},circle:function(a,b,c){var d=this.symbol("circle");C(a)&&(c=a.r,b=a.y,a=a.x);d.isCircle=!0;d.r=c;return d.attr({x:a,y:b})},g:function(a){var b;a&&(b={className:"highcharts-"+a,"class":"highcharts-"+a});return this.createElement("div").attr(b)}, +image:function(a,b,c,d,e){var q=this.createElement("img").attr({src:a});1b&&t-x*cd&&(k=Math.round((e-t)/Math.cos(b*h)));else if(e=t+(1-x)*c,t-x*cd&&(B=d-a.x+B*x,n=-1),B=Math.min(u,B),BB||l.autoRotation&&(C.styles||{}).width)k=B;k&&(E.width=k,(l.options.labels.style||{}).textOverflow||(E.textOverflow="ellipsis"),C.css(E))},getPosition:function(a,f,h,e){var d=this.axis,m=d.chart, +l=e&&m.oldChartHeight||m.chartHeight;return{x:a?d.translate(f+h,null,null,e)+d.transB:d.left+d.offset+(d.opposite?(e&&m.oldChartWidth||m.chartWidth)-d.right-d.left:0),y:a?l-d.bottom+d.offset-(d.opposite?d.height:0):l-d.translate(f+h,null,null,e)-d.transB}},getLabelPosition:function(a,f,n,e,d,m,C,b){var x=this.axis,c=x.transA,u=x.reversed,l=x.staggerLines,t=x.tickRotCorr||{x:0,y:0},k=d.y;A(k)||(k=0===x.side?n.rotation?-8:-n.getBBox().height:2===x.side?t.y+8:Math.cos(n.rotation*h)*(t.y-n.getBBox(!1, +0).height/2));a=a+d.x+t.x-(m&&e?m*c*(u?-1:1):0);f=f+k-(m&&!e?m*c*(u?1:-1):0);l&&(n=C/(b||1)%l,x.opposite&&(n=l-n-1),f+=x.labelOffset/l*n);return{x:a,y:Math.round(f)}},getMarkPath:function(a,f,h,e,d,m){return m.crispLine(["M",a,f,"L",a+(d?0:-h),f+(d?h:0)],e)},renderGridLine:function(a,f,h){var e=this.axis,d=e.options,m=this.gridLine,l={},b=this.pos,x=this.type,c=e.tickmarkOffset,u=e.chart.renderer,B=x?x+"Grid":"grid",n=d[B+"LineWidth"],k=d[B+"LineColor"],d=d[B+"LineDashStyle"];m||(l.stroke=k,l["stroke-width"]= +n,d&&(l.dashstyle=d),x||(l.zIndex=1),a&&(l.opacity=0),this.gridLine=m=u.path().attr(l).addClass("highcharts-"+(x?x+"-":"")+"grid-line").add(e.gridGroup));if(!a&&m&&(a=e.getPlotLinePath(b+c,m.strokeWidth()*h,a,!0)))m[this.isNew?"attr":"animate"]({d:a,opacity:f})},renderMark:function(a,h,n){var e=this.axis,d=e.options,m=e.chart.renderer,l=this.type,b=l?l+"Tick":"tick",x=e.tickSize(b),c=this.mark,u=!c,B=a.x;a=a.y;var t=f(d[b+"Width"],!l&&e.isXAxis?1:0),d=d[b+"Color"];x&&(e.opposite&&(x[0]=-x[0]),u&& +(this.mark=c=m.path().addClass("highcharts-"+(l?l+"-":"")+"tick").add(e.axisGroup),c.attr({stroke:d,"stroke-width":t})),c[u?"attr":"animate"]({d:this.getMarkPath(B,a,x[0],c.strokeWidth()*n,e.horiz,m),opacity:h}))},renderLabel:function(a,h,n,e){var d=this.axis,m=d.horiz,l=d.options,b=this.label,x=l.labels,c=x.step,u=d.tickmarkOffset,B=!0,t=a.x;a=a.y;b&&F(t)&&(b.xy=a=this.getLabelPosition(t,a,b,m,x,u,e,c),this.isFirst&&!this.isLast&&!f(l.showFirstLabel,1)||this.isLast&&!this.isFirst&&!f(l.showLastLabel, +1)?B=!1:!m||d.isRadial||x.step||x.rotation||h||0===n||this.handleOverflow(a),c&&e%c&&(B=!1),B&&F(a.y)?(a.opacity=n,b[this.isNew?"attr":"animate"](a)):b.attr("y",-9999),this.isNew=!1)},render:function(a,h,n){var e=this.axis,d=e.horiz,m=this.getPosition(d,this.pos,e.tickmarkOffset,h),l=m.x,b=m.y,e=d&&l===e.pos+e.len||!d&&b===e.pos?-1:1;n=f(n,1);this.isActive=!0;this.renderGridLine(h,n,e);this.renderMark(m,n,e);this.renderLabel(m,h,n,a)},destroy:function(){G(this,this.axis)}}})(L);var S=function(a){var D= +a.addEvent,A=a.animObject,G=a.arrayMax,F=a.arrayMin,n=a.color,f=a.correctFloat,h=a.defaultOptions,l=a.defined,w=a.deg2rad,t=a.destroyObjectProperties,e=a.each,d=a.extend,m=a.fireEvent,C=a.format,b=a.getMagnitude,x=a.grep,c=a.inArray,u=a.isArray,B=a.isNumber,I=a.isString,k=a.merge,E=a.normalizeTickInterval,p=a.objectEach,z=a.pick,M=a.removeEvent,q=a.splat,y=a.syncTimeout,H=a.Tick,K=function(){this.init.apply(this,arguments)};a.extend(K.prototype,{defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L", +second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,labels:{enabled:!0,style:{color:"#666666",cursor:"default",fontSize:"11px"},x:0},minPadding:.01,maxPadding:.01,minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",style:{color:"#666666"}},type:"linear",minorGridLineColor:"#f2f2f2",minorGridLineWidth:1,minorTickColor:"#999999", +lineColor:"#ccd6eb",lineWidth:1,gridLineColor:"#e6e6e6",tickColor:"#ccd6eb"},defaultYAxisOptions:{endOnTick:!0,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},maxPadding:.05,minPadding:.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return a.numberFormat(this.total,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"#000000",textOutline:"1px contrast"}},gridLineWidth:1,lineWidth:0},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}}, +defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},init:function(a,b){var g=b.isX,r=this;r.chart=a;r.horiz=a.inverted?!g:g;r.isXAxis=g;r.coll=r.coll||(g?"xAxis":"yAxis");r.opposite=b.opposite;r.side=b.side||(r.horiz?r.opposite?0:2:r.opposite?1:3);r.setOptions(b);var d=this.options,k=d.type;r.labelFormatter=d.labels.formatter||r.defaultLabelFormatter; +r.userOptions=b;r.minPixelPadding=0;r.reversed=d.reversed;r.visible=!1!==d.visible;r.zoomEnabled=!1!==d.zoomEnabled;r.hasNames="category"===k||!0===d.categories;r.categories=d.categories||r.hasNames;r.names=r.names||[];r.plotLinesAndBandsGroups={};r.isLog="logarithmic"===k;r.isDatetimeAxis="datetime"===k;r.positiveValuesOnly=r.isLog&&!r.allowNegativeLog;r.isLinked=l(d.linkedTo);r.ticks={};r.labelEdge=[];r.minorTicks={};r.plotLinesAndBands=[];r.alternateBands={};r.len=0;r.minRange=r.userMinRange=d.minRange|| +d.maxZoom;r.range=d.range;r.offset=d.offset||0;r.stacks={};r.oldStacks={};r.stacksTouched=0;r.max=null;r.min=null;r.crosshair=z(d.crosshair,q(a.options.tooltip.crosshairs)[g?0:1],!1);b=r.options.events;-1===c(r,a.axes)&&(g?a.axes.splice(a.xAxis.length,0,r):a.axes.push(r),a[r.coll].push(r));r.series=r.series||[];a.inverted&&g&&void 0===r.reversed&&(r.reversed=!0);p(b,function(a,b){D(r,b,a)});r.lin2log=d.linearToLogConverter||r.lin2log;r.isLog&&(r.val2lin=r.log2lin,r.lin2val=r.lin2log)},setOptions:function(a){this.options= +k(this.defaultOptions,"yAxis"===this.coll&&this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],k(h[this.coll],a))},defaultLabelFormatter:function(){var b=this.axis,c=this.value,d=b.categories,q=this.dateTimeLabelFormat,k=h.lang,e=k.numericSymbols,k=k.numericSymbolMagnitude||1E3,p=e&&e.length,v,m=b.options.labels.format,b=b.isLog?Math.abs(c):b.tickInterval;if(m)v=C(m,this);else if(d)v=c;else if(q)v= +a.dateFormat(q,c);else if(p&&1E3<=b)for(;p--&&void 0===v;)d=Math.pow(k,p+1),b>=d&&0===10*c%d&&null!==e[p]&&0!==c&&(v=a.numberFormat(c/d,-1)+e[p]);void 0===v&&(v=1E4<=Math.abs(c)?a.numberFormat(c,-1):a.numberFormat(c,-1,void 0,""));return v},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks();e(a.series,function(g){if(g.visible||!b.options.chart.ignoreHiddenSeries){var c=g.options,r=c.threshold, +d;a.hasVisibleSeries=!0;a.positiveValuesOnly&&0>=r&&(r=null);if(a.isXAxis)c=g.xData,c.length&&(g=F(c),B(g)||g instanceof Date||(c=x(c,function(a){return B(a)}),g=F(c)),a.dataMin=Math.min(z(a.dataMin,c[0]),g),a.dataMax=Math.max(z(a.dataMax,c[0]),G(c)));else if(g.getExtremes(),d=g.dataMax,g=g.dataMin,l(g)&&l(d)&&(a.dataMin=Math.min(z(a.dataMin,g),g),a.dataMax=Math.max(z(a.dataMax,d),d)),l(r)&&(a.threshold=r),!c.softThreshold||a.positiveValuesOnly)a.softThreshold=!1}})},translate:function(a,b,c,d,q, +k){var g=this.linkedParent||this,r=1,e=0,p=d?g.oldTransA:g.transA;d=d?g.oldMin:g.min;var m=g.minPixelPadding;q=(g.isOrdinal||g.isBroken||g.isLog&&q)&&g.lin2val;p||(p=g.transA);c&&(r*=-1,e=g.len);g.reversed&&(r*=-1,e-=r*(g.sector||g.len));b?(a=(a*r+e-m)/p+d,q&&(a=g.lin2val(a))):(q&&(a=g.val2lin(a)),a=r*(a-d)*p+e+r*m+(B(k)?p*k:0));return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz, +null,!0)},getPlotLinePath:function(a,b,c,d,q){var g=this.chart,r=this.left,k=this.top,e,p,m=c&&g.oldChartHeight||g.chartHeight,u=c&&g.oldChartWidth||g.chartWidth,y;e=this.transB;var x=function(a,b,g){if(ag)d?a=Math.min(Math.max(b,a),g):y=!0;return a};q=z(q,this.translate(a,null,null,c));a=c=Math.round(q+e);e=p=Math.round(m-q-e);B(q)?this.horiz?(e=k,p=m-this.bottom,a=c=x(a,r,r+this.width)):(a=r,c=u-this.right,e=p=x(e,k,k+this.height)):y=!0;return y&&!d?null:g.renderer.crispLine(["M",a,e,"L", +c,p],b||1)},getLinearTickPositions:function(a,b,c){var g,r=f(Math.floor(b/a)*a);c=f(Math.ceil(c/a)*a);var d=[];if(this.single)return[b];for(b=r;b<=c;){d.push(b);b=f(b+a);if(b===g)break;g=b}return d},getMinorTickPositions:function(){var a=this,b=a.options,c=a.tickPositions,d=a.minorTickInterval,q=[],k=a.pointRangePadding||0,p=a.min-k,k=a.max+k,v=k-p;if(v&&v/d=this.minRange,k,p,v,m,u,y;this.isXAxis&&void 0===this.minRange&&!this.isLog&&(l(a.min)||l(a.max)?this.minRange=null:(e(this.series,function(a){m=a.xData;for(p=u=a.xIncrement?1:m.length-1;0=t?(K=t,H=0):c.dataMax<=t&&(w=t,x=0)),c.min=z(M,K,c.dataMin),c.max=z(A,w,c.dataMax));k&&(c.positiveValuesOnly&&!g&&0>=Math.min(c.min, +z(c.dataMin,c.min))&&a.error(10,1),c.min=f(p(c.min),15),c.max=f(p(c.max),15));c.range&&l(c.max)&&(c.userMin=c.min=M=Math.max(c.min,c.minFromRange()),c.userMax=A=c.max,c.range=null);m(c,"foundExtremes");c.beforePadding&&c.beforePadding();c.adjustForMinRange();!(C||c.axisPointRange||c.usePercentage||y)&&l(c.min)&&l(c.max)&&(p=c.max-c.min)&&(!l(M)&&H&&(c.min-=p*H),!l(A)&&x&&(c.max+=p*x));B(q.softMin)&&(c.min=Math.min(c.min,q.softMin));B(q.softMax)&&(c.max=Math.max(c.max,q.softMax));B(q.floor)&&(c.min= +Math.max(c.min,q.floor));B(q.ceiling)&&(c.max=Math.min(c.max,q.ceiling));I&&l(c.dataMin)&&(t=t||0,!l(M)&&c.min=t?c.min=t:!l(A)&&c.max>t&&c.dataMax<=t&&(c.max=t));c.tickInterval=c.min===c.max||void 0===c.min||void 0===c.max?1:y&&!h&&n===c.linkedParent.options.tickPixelInterval?h=c.linkedParent.tickInterval:z(h,this.tickAmount?(c.max-c.min)/Math.max(this.tickAmount-1,1):void 0,C?1:(c.max-c.min)*n/Math.max(c.len,n));v&&!g&&e(c.series,function(a){a.processData(c.min!==c.oldMin||c.max!== +c.oldMax)});c.setAxisTranslation(!0);c.beforeSetTickPositions&&c.beforeSetTickPositions();c.postProcessTickInterval&&(c.tickInterval=c.postProcessTickInterval(c.tickInterval));c.pointRange&&!h&&(c.tickInterval=Math.max(c.pointRange,c.tickInterval));g=z(q.minTickInterval,c.isDatetimeAxis&&c.closestPointRange);!h&&c.tickIntervalc.tickInterval&&1E3c.max)),!!this.tickAmount)); +this.tickAmount||(c.tickInterval=c.unsquish());this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions,d=a.tickPositioner,q=a.startOnTick,k=a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===a.minorTickInterval&&this.tickInterval?this.tickInterval/5:a.minorTickInterval;this.single=this.min===this.max&&l(this.min)&&!this.tickAmount&&(parseInt(this.min,10)===this.min||!1!==a.allowDecimals); +this.tickPositions=b=c&&c.slice();!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b=[b[0],b.pop()]),this.tickPositions=b,d&&(d=d.apply(this,[this.min,this.max])))&&(this.tickPositions=b=d);this.paddedTicks=b.slice(0); +this.trimTicks(b,q,k);this.isLinked||(this.single&&(this.min-=.5,this.max+=.5),c||d||this.adjustTickAmount())},trimTicks:function(a,b,c){var g=a[0],d=a[a.length-1],q=this.minPointOffset||0;if(!this.isLinked){if(b&&-Infinity!==g)this.min=g;else for(;this.min-q>a[0];)a.shift();if(c)this.max=d;else for(;this.max+qb&&(this.finalTickAmt=b,b=5);this.tickAmount=b},adjustTickAmount:function(){var a=this.tickInterval,b=this.tickPositions,c=this.tickAmount, +d=this.finalTickAmt,q=b&&b.length;if(qc&&(this.tickInterval*=2,this.setTickPositions());if(l(d)){for(a=c=b.length;a--;)(3===d&&1===a%2||2>=d&&0d&&(a=d)),l(g)&&(bd&&(b=d))),this.displayBtn=void 0!==a||void 0!==b,this.setExtremes(a,b,!1,void 0,{trigger:"zoom"});return!0},setAxisSize:function(){var a=this.chart, +b=this.options,c=b.offsets||[0,0,0,0],d=this.horiz,q=z(b.width,a.plotWidth-c[3]+c[1]),k=z(b.height,a.plotHeight-c[0]+c[2]),p=z(b.top,a.plotTop+c[0]),b=z(b.left,a.plotLeft+c[3]),c=/%$/;c.test(k)&&(k=Math.round(parseFloat(k)/100*a.plotHeight));c.test(p)&&(p=Math.round(parseFloat(p)/100*a.plotHeight+a.plotTop));this.left=b;this.top=p;this.width=q;this.height=k;this.bottom=a.chartHeight-k-p;this.right=a.chartWidth-q-b;this.len=Math.max(d?q:k,0);this.pos=d?b:p},getExtremes:function(){var a=this.isLog, +b=this.lin2log;return{min:a?f(b(this.min)):this.min,max:a?f(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=this.lin2log,g=b?c(this.min):this.min,b=b?c(this.max):this.max;null===a?a=g:g>a?a=g:ba?"right":195a?"left":"center"},tickSize:function(a){var b=this.options,c=b[a+ +"Length"],g=z(b[a+"Width"],"tick"===a&&this.isXAxis?1:0);if(g&&c)return"inside"===b[a+"Position"]&&(c=-c),[c,g]},labelMetrics:function(){return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize,this.ticks[0]&&this.ticks[0].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,c=this.tickInterval,d=c,q=this.len/(((this.categories?1:0)+this.max-this.min)/c),k,p=a.rotation,v=this.labelMetrics(),m,u=Number.MAX_VALUE,y,x=function(a){a/=q||1;a=1< +a?Math.ceil(a):1;return a*c};b?(y=!a.staggerLines&&!a.step&&(l(p)?[p]:q=a)m=x(Math.abs(v.h/Math.sin(w*a))),b=m+Math.abs(a/360),b(c.step||0)&&!c.rotation&& +(this.staggerLines||1)*this.len/d||!b&&(q&&q-a.spacing[3]||.33*a.chartWidth)},renderUnsquish:function(){var a=this.chart,b=a.renderer,c=this.tickPositions,d=this.ticks,q=this.options.labels,p=this.horiz,m=this.getSlotWidth(),v=Math.max(1,Math.round(m-2*(q.padding||5))),u={},y=this.labelMetrics(),x=q.style&&q.style.textOverflow,f,H=0,h,l;I(q.rotation)||(u.rotation=q.rotation||0);e(c,function(a){(a=d[a])&&a.labelLength>H&&(H=a.labelLength)});this.maxLabelLength=H;if(this.autoRotation)H>v&&H>y.h?u.rotation= +this.labelRotation:this.labelRotation=0;else if(m&&(f={width:v+"px"},!x))for(f.textOverflow="clip",h=c.length;!p&&h--;)if(l=c[h],v=d[l].label)v.styles&&"ellipsis"===v.styles.textOverflow?v.css({textOverflow:"clip"}):d[l].labelLength>m&&v.css({width:m+"px"}),v.getBBox().height>this.len/c.length-(y.h-y.f)&&(v.specCss={textOverflow:"ellipsis"});u.rotation&&(f={width:(H>.5*a.chartHeight?.33*a.chartHeight:a.chartHeight)+"px"},x||(f.textOverflow="ellipsis"));if(this.labelAlign=q.align||this.autoLabelAlign(this.labelRotation))u.align= +this.labelAlign;e(c,function(a){var b=(a=d[a])&&a.label;b&&(b.attr(u),f&&b.css(k(f,b.specCss)),delete b.specCss,a.rotation=u.rotation)});this.tickRotCorr=b.rotCorr(y.b,this.labelRotation||0,0!==this.side)},hasData:function(){return this.hasVisibleSeries||l(this.min)&&l(this.max)&&!!this.tickPositions},addTitle:function(a){var b=this.chart.renderer,c=this.horiz,g=this.opposite,d=this.options.title,q;this.axisTitle||((q=d.textAlign)||(q=(c?{low:"left",middle:"center",high:"right"}:{low:g?"right":"left", +middle:"center",high:g?"left":"right"})[d.align]),this.axisTitle=b.text(d.text,0,0,d.useHTML).attr({zIndex:7,rotation:d.rotation||0,align:q}).addClass("highcharts-axis-title").css(d.style).add(this.axisGroup),this.axisTitle.isNew=!0);this.axisTitle[a?"show":"hide"](!0)},generateTick:function(a){var b=this.ticks;b[a]?b[a].addLabel():b[a]=new H(this,a)},getOffset:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,q=a.tickPositions,k=a.ticks,m=a.horiz,v=a.side,u=b.inverted?[1,0,3,2][v]:v,y,x,f= +0,H,h=0,B=d.title,n=d.labels,E=0,C=b.axisOffset,b=b.clipOffset,t=[-1,1,1,-1][v],I=d.className,K=a.axisParent,w=this.tickSize("tick");y=a.hasData();a.showAxis=x=y||z(d.showEmpty,!0);a.staggerLines=a.horiz&&n.staggerLines;a.axisGroup||(a.gridGroup=c.g("grid").attr({zIndex:d.gridZIndex||1}).addClass("highcharts-"+this.coll.toLowerCase()+"-grid "+(I||"")).add(K),a.axisGroup=c.g("axis").attr({zIndex:d.zIndex||2}).addClass("highcharts-"+this.coll.toLowerCase()+" "+(I||"")).add(K),a.labelGroup=c.g("axis-labels").attr({zIndex:n.zIndex|| +7}).addClass("highcharts-"+a.coll.toLowerCase()+"-labels "+(I||"")).add(K));y||a.isLinked?(e(q,function(b,c){a.generateTick(b,c)}),a.renderUnsquish(),!1===n.reserveSpace||0!==v&&2!==v&&{1:"left",3:"right"}[v]!==a.labelAlign&&"center"!==a.labelAlign||e(q,function(a){E=Math.max(k[a].getLabelSize(),E)}),a.staggerLines&&(E*=a.staggerLines,a.labelOffset=E*(a.opposite?-1:1))):p(k,function(a,b){a.destroy();delete k[b]});B&&B.text&&!1!==B.enabled&&(a.addTitle(x),x&&!1!==B.reserveSpace&&(a.titleOffset=f=a.axisTitle.getBBox()[m? +"height":"width"],H=B.offset,h=l(H)?0:z(B.margin,m?5:10)));a.renderLine();a.offset=t*z(d.offset,C[v]);a.tickRotCorr=a.tickRotCorr||{x:0,y:0};c=0===v?-a.labelMetrics().h:2===v?a.tickRotCorr.y:0;h=Math.abs(E)+h;E&&(h=h-c+t*(m?z(n.y,a.tickRotCorr.y+8*t):n.x));a.axisTitleMargin=z(H,h);C[v]=Math.max(C[v],a.axisTitleMargin+f+t*a.offset,h,y&&q.length&&w?w[0]+t*a.offset:0);d=d.offset?0:2*Math.floor(a.axisLine.strokeWidth()/2);b[u]=Math.max(b[u],d)},getLinePath:function(a){var b=this.chart,c=this.opposite, +g=this.offset,d=this.horiz,q=this.left+(c?this.width:0)+g,g=b.chartHeight-this.bottom-(c?this.height:0)+g;c&&(a*=-1);return b.renderer.crispLine(["M",d?this.left:q,d?g:this.top,"L",d?b.chartWidth-this.right:q,d?g:b.chartHeight-this.bottom],a)},renderLine:function(){this.axisLine||(this.axisLine=this.chart.renderer.path().addClass("highcharts-axis-line").add(this.axisGroup),this.axisLine.attr({stroke:this.options.lineColor,"stroke-width":this.options.lineWidth,zIndex:7}))},getTitlePosition:function(){var a= +this.horiz,b=this.left,c=this.top,d=this.len,q=this.options.title,k=a?b:c,p=this.opposite,e=this.offset,m=q.x||0,u=q.y||0,y=this.chart.renderer.fontMetrics(q.style&&q.style.fontSize,this.axisTitle).f,d={low:k+(a?0:d),middle:k+d/2,high:k+(a?d:0)}[q.align],b=(a?c+this.height:b)+(a?1:-1)*(p?-1:1)*this.axisTitleMargin+(2===this.side?y:0);return{x:a?d+m:b+(p?this.width:0)+e+m,y:a?b+u-(p?this.height:0)+e:d+u}},renderMinorTick:function(a){var b=this.chart.hasRendered&&B(this.oldMin),c=this.minorTicks;c[a]|| +(c[a]=new H(this,a,"minor"));b&&c[a].isNew&&c[a].render(null,!0);c[a].render(null,!1,1)},renderTick:function(a,b){var c=this.isLinked,g=this.ticks,d=this.chart.hasRendered&&B(this.oldMin);if(!c||a>=this.min&&a<=this.max)g[a]||(g[a]=new H(this,a)),d&&g[a].isNew&&g[a].render(b,!0,.1),g[a].render(b)},render:function(){var b=this,c=b.chart,d=b.options,q=b.isLog,k=b.lin2log,m=b.isLinked,u=b.tickPositions,v=b.axisTitle,x=b.ticks,f=b.minorTicks,h=b.alternateBands,l=d.stackLabels,B=d.alternateGridColor,z= +b.tickmarkOffset,n=b.axisLine,E=b.showAxis,C=A(c.renderer.globalAnimation),t,I;b.labelEdge.length=0;b.overlap=!1;e([x,f,h],function(a){p(a,function(a){a.isActive=!1})});if(b.hasData()||m)b.minorTickInterval&&!b.categories&&e(b.getMinorTickPositions(),function(a){b.renderMinorTick(a)}),u.length&&(e(u,function(a,c){b.renderTick(a,c)}),z&&(0===b.min||b.single)&&(x[-1]||(x[-1]=new H(b,-1,null,!0)),x[-1].render(-1))),B&&e(u,function(g,d){I=void 0!==u[d+1]?u[d+1]+z:b.max-z;0===d%2&&g=d.second?0:z*Math.floor(k.getMilliseconds()/z));if(p>=d.second)k[A.hcSetSeconds](p>=d.minute?0:z*Math.floor(k.getSeconds()/z));if(p>=d.minute)k[A.hcSetMinutes](p>=d.hour?0:z*Math.floor(k[A.hcGetMinutes]()/z));if(p>=d.hour)k[A.hcSetHours](p>=d.day?0:z*Math.floor(k[A.hcGetHours]()/z));if(p>=d.day)k[A.hcSetDate](p>= +d.month?1:z*Math.floor(k[A.hcGetDate]()/z));p>=d.month&&(k[A.hcSetMonth](p>=d.year?0:z*Math.floor(k[A.hcGetMonth]()/z)),t=k[A.hcGetFullYear]());if(p>=d.year)k[A.hcSetFullYear](t-t%z);if(p===d.week)k[A.hcSetDate](k[A.hcGetDate]()-k[A.hcGetDay]()+e(x,1));t=k[A.hcGetFullYear]();x=k[A.hcGetMonth]();var q=k[A.hcGetDate](),y=k[A.hcGetHours]();if(A.hcTimezoneOffset||A.hcGetTimezoneOffset)C=(!B||!!A.hcGetTimezoneOffset)&&(b-l>4*d.month||w(l)!==w(b)),k=k.getTime(),k=new A(k+w(k));B=k.getTime();for(l=1;Bc.length&&f(c,function(a){0===a%18E5&&"000000000"===G("%H%M%S%L",a)&&(m[a]="day")})}c.info=h(a,{higherRanks:m,totalRange:p*z});return c};D.prototype.normalizeTimeTickInterval=function(a,e){var b=e||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day", +[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]];e=b[b.length-1];var m=d[e[0]],c=e[1],u;for(u=0;uh&&(!w||u<=l)&&void 0!==u&&C.push(u),u>l&&(B=!0),u=c;else h=d(h),l=d(l),a=f[w?"minorTickInterval":"tickInterval"],a=n("auto"===a?null:a,this._minorAutoInterval,f.tickPixelInterval/(w?5:1)*(l-h)/((w?e/this.tickPositions.length: +e)||1)),a=F(a,null,A(a)),C=G(this.getLinearTickPositions(a,h,l),m),w||(this._minorAutoInterval=a/5);w||(this.tickInterval=a);return C};D.prototype.log2lin=function(a){return Math.log(a)/Math.LN10};D.prototype.lin2log=function(a){return Math.pow(10,a)}})(L);(function(a,D){var A=a.arrayMax,G=a.arrayMin,F=a.defined,n=a.destroyObjectProperties,f=a.each,h=a.erase,l=a.merge,w=a.pick;a.PlotLineOrBand=function(a,e){this.axis=a;e&&(this.options=e,this.id=e.id)};a.PlotLineOrBand.prototype={render:function(){var f= +this,e=f.axis,d=e.horiz,m=f.options,h=m.label,b=f.label,x=m.to,c=m.from,u=m.value,B=F(c)&&F(x),n=F(u),k=f.svgElem,E=!k,p=[],z=m.color,M=w(m.zIndex,0),q=m.events,p={"class":"highcharts-plot-"+(B?"band ":"line ")+(m.className||"")},y={},H=e.chart.renderer,K=B?"bands":"lines",g=e.log2lin;e.isLog&&(c=g(c),x=g(x),u=g(u));n?(p={stroke:z,"stroke-width":m.width},m.dashStyle&&(p.dashstyle=m.dashStyle)):B&&(z&&(p.fill=z),m.borderWidth&&(p.stroke=m.borderColor,p["stroke-width"]=m.borderWidth));y.zIndex=M;K+= +"-"+M;(z=e.plotLinesAndBandsGroups[K])||(e.plotLinesAndBandsGroups[K]=z=H.g("plot-"+K).attr(y).add());E&&(f.svgElem=k=H.path().attr(p).add(z));if(n)p=e.getPlotLinePath(u,k.strokeWidth());else if(B)p=e.getPlotBandPath(c,x,m);else return;E&&p&&p.length?(k.attr({d:p}),q&&a.objectEach(q,function(a,b){k.on(b,function(a){q[b].apply(f,[a])})})):k&&(p?(k.show(),k.animate({d:p})):(k.hide(),b&&(f.label=b=b.destroy())));h&&F(h.text)&&p&&p.length&&0this.max&&e>this.max;m&&d?(a&&(m.flat=m.toString()===d.toString(),b=0),m.push(f&&d[4]===m[4]?d[4]+b:d[4],f||d[5]!==m[5]?d[5]:d[5]+b,f&&d[1]===m[1]?d[1]+b:d[1],f||d[2]!==m[2]?d[2]:d[2]+b)):m=null;return m}, +addPlotBand:function(a){return this.addPlotBandOrLine(a,"plotBands")},addPlotLine:function(a){return this.addPlotBandOrLine(a,"plotLines")},addPlotBandOrLine:function(f,e){var d=(new a.PlotLineOrBand(this,f)).render(),m=this.userOptions;d&&(e&&(m[e]=m[e]||[],m[e].push(f)),this.plotLinesAndBands.push(d));return d},removePlotBandOrLine:function(a){for(var e=this.plotLinesAndBands,d=this.options,m=this.userOptions,l=e.length;l--;)e[l].id===a&&e[l].destroy();f([d.plotLines||[],m.plotLines||[],d.plotBands|| +[],m.plotBands||[]],function(b){for(l=b.length;l--;)b[l].id===a&&h(b,b[l])})},removePlotBand:function(a){this.removePlotBandOrLine(a)},removePlotLine:function(a){this.removePlotBandOrLine(a)}})})(L,S);(function(a){var D=a.dateFormat,A=a.each,G=a.extend,F=a.format,n=a.isNumber,f=a.map,h=a.merge,l=a.pick,w=a.splat,t=a.syncTimeout,e=a.timeUnits;a.Tooltip=function(){this.init.apply(this,arguments)};a.Tooltip.prototype={init:function(a,e){this.chart=a;this.options=e;this.crosshairs=[];this.now={x:0,y:0}; +this.isHidden=!0;this.split=e.split&&!a.inverted;this.shared=e.shared||this.split},cleanSplit:function(a){A(this.chart.series,function(d){var e=d&&d.tt;e&&(!e.isActive||a?d.tt=e.destroy():e.isActive=!1)})},getLabel:function(){var a=this.chart.renderer,e=this.options;this.label||(this.split?this.label=a.g("tooltip"):(this.label=a.label("",0,0,e.shape||"callout",null,null,e.useHTML,null,"tooltip").attr({padding:e.padding,r:e.borderRadius}),this.label.attr({fill:e.backgroundColor,"stroke-width":e.borderWidth}).css(e.style).shadow(e.shadow)), +this.label.attr({zIndex:8}).add());return this.label},update:function(a){this.destroy();h(!0,this.chart.options.tooltip.userOptions,a);this.init(this.chart,h(!0,this.options,a))},destroy:function(){this.label&&(this.label=this.label.destroy());this.split&&this.tt&&(this.cleanSplit(this.chart,!0),this.tt=this.tt.destroy());clearTimeout(this.hideTimer);clearTimeout(this.tooltipTimeout)},move:function(a,e,f,b){var d=this,c=d.now,u=!1!==d.options.animation&&!d.isHidden&&(1y-u?y:y-u);else if(m)c[a]=Math.max(k,g+u+q>b?g:g+u);else return!1},z=function(a,b,q,g){var k;gb-d?k=!1:c[a]=gb-q/2? +b-q-2:g-q/2;return k},t=function(a){var b=h;h=k;k=b;m=a},q=function(){!1!==p.apply(0,h)?!1!==z.apply(0,k)||m||(t(!0),q()):m?c.x=c.y=0:(t(!0),q())};(b.inverted||1q&&(u= +!1);a=(d.series&&d.series.yAxis&&d.series.yAxis.pos)+(d.plotY||0);a-=m.plotTop;b.push({target:d.isHeader?m.plotHeight+n:a,rank:d.isHeader?1:0,size:p.tt.getBBox().height+1,point:d,x:q,tt:x})});this.cleanSplit();a.distribute(b,m.plotHeight+n);A(b,function(a){var b=a.point,c=b.series;a.tt.attr({visibility:void 0===a.pos?"hidden":"inherit",x:u||b.isHeader?a.x:b.plotX+m.plotLeft+l(h.distance,16),y:a.pos+m.plotTop,anchorX:b.isHeader?b.plotX+m.plotLeft:b.plotX+c.xAxis.pos,anchorY:b.isHeader?a.pos+m.plotTop- +15:b.plotY+c.yAxis.pos})})},updatePosition:function(a){var d=this.chart,e=this.getLabel(),e=(this.options.positioner||this.getPosition).call(this,e.width,e.height,a);this.move(Math.round(e.x),Math.round(e.y||0),a.plotX+d.plotLeft,a.plotY+d.plotTop)},getDateFormat:function(a,f,h,b){var d=D("%m-%d %H:%M:%S.%L",f),c,u,m={millisecond:15,second:12,minute:9,hour:6,day:3},l="millisecond";for(u in e){if(a===e.week&&+D("%w",f)===h&&"00:00:00.000"===d.substr(6)){u="week";break}if(e[u]>a){u=l;break}if(m[u]&& +d.substr(m[u])!=="01-01 00:00:00.000".substr(m[u]))break;"week"!==u&&(l=u)}u&&(c=b[u]);return c},getXDateFormat:function(a,e,f){e=e.dateTimeLabelFormats;var b=f&&f.closestPointRange;return(b?this.getDateFormat(b,a.x,f.options.startOfWeek,e):e.day)||e.year},tooltipFooterHeaderFormatter:function(a,e){var d=e?"footer":"header";e=a.series;var b=e.tooltipOptions,f=b.xDateFormat,c=e.xAxis,u=c&&"datetime"===c.options.type&&n(a.key),d=b[d+"Format"];u&&!f&&(f=this.getXDateFormat(a,b,c));u&&f&&(d=d.replace("{point.key}", +"{point.key:"+f+"}"));return F(d,{point:a,series:e})},bodyFormatter:function(a){return f(a,function(a){var d=a.series.tooltipOptions;return(d.pointFormatter||a.point.tooltipFormatter).call(a.point,d.pointFormat)})}}})(L);(function(a){var D=a.addEvent,A=a.attr,G=a.charts,F=a.color,n=a.css,f=a.defined,h=a.doc,l=a.each,w=a.extend,t=a.fireEvent,e=a.offset,d=a.pick,m=a.removeEvent,C=a.splat,b=a.Tooltip,x=a.win;a.Pointer=function(a,b){this.init(a,b)};a.Pointer.prototype={init:function(a,e){this.options= +e;this.chart=a;this.runChartClick=e.chart.events&&!!e.chart.events.click;this.pinchDown=[];this.lastValidTouch={};b&&e.tooltip.enabled&&(a.tooltip=new b(a,e.tooltip),this.followTouchMove=d(e.tooltip.followTouchMove,!0));this.setDOMEvents()},zoomOption:function(a){var b=this.chart,c=b.options.chart,e=c.zoomType||"",b=b.inverted;/touch/.test(a.type)&&(e=d(c.pinchType,e));this.zoomX=a=/x/.test(e);this.zoomY=e=/y/.test(e);this.zoomHor=a&&!b||e&&b;this.zoomVert=e&&!b||a&&b;this.hasZoom=a||e},normalize:function(a, +b){var c,d;a=a||x.event;a.target||(a.target=a.srcElement);d=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a;b||(this.chartPosition=b=e(this.chart.container));void 0===d.pageX?(c=Math.max(a.x,a.clientX-b.left),b=a.y):(c=d.pageX-b.left,b=d.pageY-b.top);return w(a,{chartX:Math.round(c),chartY:Math.round(b)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};l(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})}); +return b},getKDPoints:function(a,b,e){var c=[],k,f,p;l(a,function(a){k=a.noSharedTooltip&&b;f=!b&&a.directTouch;a.visible&&!f&&d(a.options.enableMouseTracking,!0)&&(p=a.searchPoint(e,!k&&0>a.options.findNearestPointBy.indexOf("y")))&&p.series&&c.push(p)});c.sort(function(a,c){var d=a.distX-c.distX,e=a.dist-c.dist,k=(c.series.group&&c.series.group.zIndex)-(a.series.group&&a.series.group.zIndex);return 0!==d&&b?d:0!==e?e:0!==k?k:a.series.index>c.series.index?-1:1});if(b&&c[0]&&!c[0].series.noSharedTooltip)for(a= +c.length;a--;)(c[a].x!==c[0].x||c[a].series.noSharedTooltip)&&c.splice(a,1);return c},getPointFromEvent:function(a){a=a.target;for(var b;a&&!b;)b=a.point,a=a.parentNode;return b},getHoverData:function(b,e,f,m,k,x){var c=b,u=e,h;m?k?(h=[],l(f,function(a){var b=a.noSharedTooltip&&k,q=!k&&a.directTouch;a.visible&&!b&&!q&&d(a.options.enableMouseTracking,!0)&&(a=a.searchKDTree({clientX:c.clientX,plotY:c.plotY},!b&&1===a.kdDimensions))&&a.series&&h.push(a)}),0===h.length&&(h=[c])):h=[c]:u&&!u.stickyTracking? +(k||(f=[u]),h=this.getKDPoints(f,k,x),c=a.find(h,function(a){return a.series===u})):(b=a.grep(f,function(a){return a.stickyTracking}),h=this.getKDPoints(b,k,x),u=(c=h[0])&&c.series,k&&(h=this.getKDPoints(f,k,x)));h.sort(function(a,b){return a.series.index-b.series.index});return{hoverPoint:c,hoverSeries:u,hoverPoints:h}},runPointActions:function(b,e){var c=this.chart,f=c.tooltip,k=f?f.shared:!1,m=e||c.hoverPoint,p=m&&m.series||c.hoverSeries;e=this.getHoverData(m,p,c.series,!!e||p&&p.directTouch,k, +b);var u,x,m=e.hoverPoint;u=(p=e.hoverSeries)&&p.tooltipOptions.followPointer;x=(k=k&&m&&!m.series.noSharedTooltip)?e.hoverPoints:m?[m]:[];if(m&&(m!==c.hoverPoint||f&&f.isHidden)){l(c.hoverPoints||[],function(b){-1===a.inArray(b,x)&&b.setState()});l(x||[],function(a){a.setState("hover")});if(c.hoverSeries!==p)p.onMouseOver();p&&!p.directTouch&&(c.hoverPoint&&c.hoverPoint.firePointEvent("mouseOut"),m.firePointEvent("mouseOver"));c.hoverPoints=x;c.hoverPoint=m;f&&f.refresh(k?x:m,b)}else u&&f&&!f.isHidden&& +(p=f.getAnchor([{}],b),f.updatePosition({plotX:p[0],plotY:p[1]}));this.unDocMouseMove||(this.unDocMouseMove=D(h,"mousemove",function(b){var c=G[a.hoverChartIndex];if(c)c.pointer.onDocumentMouseMove(b)}));l(c.axes,function(c){d(c.crosshair.snap,!0)?a.find(x,function(a){return a.series[c.coll]===c})?c.drawCrosshair(b,m):c.hideCrosshair():c.drawCrosshair(b)})},reset:function(a,b){var c=this.chart,d=c.hoverSeries,e=c.hoverPoint,f=c.hoverPoints,p=c.tooltip,m=p&&p.shared?f:e;a&&m&&l(C(m),function(b){b.series.isCartesian&& +void 0===b.plotX&&(a=!1)});if(a)p&&m&&(p.refresh(m),e&&(e.setState(e.state,!0),l(c.axes,function(a){a.crosshair&&a.drawCrosshair(null,e)})));else{if(e)e.onMouseOut();f&&l(f,function(a){a.setState()});if(d)d.onMouseOut();p&&p.hide(b);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());l(c.axes,function(a){a.hideCrosshair()});this.hoverX=c.hoverPoints=c.hoverPoint=null}},scaleGroups:function(a,b){var c=this.chart,d;l(c.series,function(e){d=a||e.getPlotBox();e.xAxis&&e.xAxis.zoomEnabled&& +e.group&&(e.group.attr(d),e.markerGroup&&(e.markerGroup.attr(d),e.markerGroup.clip(b?c.clipRect:null)),e.dataLabelsGroup&&e.dataLabelsGroup.attr(d))});c.clipRect.attr(b||c.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,f=this.zoomHor,p=this.zoomVert,m=b.plotLeft,x=b.plotTop,q=b.plotWidth,y=b.plotHeight,h,l=this.selectionMarker, +g=this.mouseDownX,r=this.mouseDownY,n=c.panKey&&a[c.panKey+"Key"];l&&l.touch||(dm+q&&(d=m+q),ex+y&&(e=x+y),this.hasDragged=Math.sqrt(Math.pow(g-d,2)+Math.pow(r-e,2)),10M.max&&(f= +M.max-k,r=!0);r?(H-=.8*(H-m[x][0]),q||(g-=.8*(g-m[x][1])),n()):m[x]=[H,g];z||(d[x]=E-w,d[l]=k);d=z?1/p:p;e[l]=k;e[x]=f;t[z?a?"scaleY":"scaleX":"scale"+c]=p;t["translate"+c]=d*w+(H-d*y)},pinch:function(a){var h=this,w=h.chart,t=h.pinchDown,e=a.touches,d=e.length,m=h.lastValidTouch,C=h.hasZoom,b=h.selectionMarker,x={},c=1===d&&(h.inClass(a.target,"highcharts-tracker")&&w.runTrackerClick||h.runChartClick),u={};1c-6&&m(y||b.spacingBox.width-2*h-d.x)&&(this.itemX=h,this.itemY+=K+this.lastLineHeight+l,this.lastLineHeight=0);this.maxItemWidth=Math.max(this.maxItemWidth,f);this.lastItemY=K+this.itemY+l;this.lastLineHeight= +Math.max(k,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=f:(this.itemY+=K+k+l,this.lastLineHeight=k);this.offsetWidth=y||Math.max((e?this.itemX-h-n:f)+h,this.offsetWidth)},getAllItems:function(){var a=[];f(this.chart.series,function(b){var c=b&&b.options;b&&t(c.showInLegend,n(c.linkedTo)?!1:void 0,!0)&&(a=a.concat(b.legendItems||("point"===c.legendType?b.data:b)))});return a},adjustMargins:function(a,d){var b=this.chart,e=this.options,m=e.align.charAt(0)+e.verticalAlign.charAt(0)+ +e.layout.charAt(0);e.floating||f([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(c,k){c.test(m)&&!n(a[k])&&(b[l[k]]=Math.max(b[l[k]],b.legend[(k+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][k]*e[k%2?"x":"y"]+t(e.margin,12)+d[k]))})},render:function(){var a=this,e=a.chart,c=e.renderer,m=a.group,h,n,k,l,p=a.box,z=a.options,t=a.padding;a.itemX=t;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;m||(a.group=m=c.g("legend").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(m), +a.scrollGroup=c.g().add(a.contentGroup));a.renderTitle();h=a.getAllItems();d(h,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});z.reversed&&h.reverse();a.allItems=h;a.display=n=!!h.length;a.lastLineHeight=0;f(h,function(b){a.renderItem(b)});k=(z.width||a.offsetWidth)+t;l=a.lastItemY+a.lastLineHeight+a.titleHeight;l=a.handleOverflow(l);l+=t;p||(a.box=p=c.rect().addClass("highcharts-legend-box").attr({r:z.borderRadius}).add(m),p.isNew=!0);p.attr({stroke:z.borderColor, +"stroke-width":z.borderWidth||0,fill:z.backgroundColor||"none"}).shadow(z.shadow);0c&&!1!==l.enabled?(this.clipHeight=h=Math.max(c-20-this.titleHeight- +k,0),this.currentPage=t(this.currentPage,1),this.fullHeight=a,f(g,function(a,b){var c=a._legendItemPos[1];a=Math.round(a.legendItem.getBBox().height);var d=H.length;if(!d||c-H[d-1]>h&&(K||c)!==H[d-1])H.push(K||c),d++;b===g.length-1&&c+a-H[d-1]>h&&H.push(c);c!==K&&(K=c)}),p||(p=b.clipRect=d.clipRect(0,k,9999,0),b.contentGroup.clip(p)),r(h),y||(this.nav=y=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle",0,0,q,q).on("click",function(){b.scroll(-1,n)}).add(y),this.pager=d.text("",15, +10).addClass("highcharts-legend-navigation").css(l.style).add(y),this.down=d.symbol("triangle-down",0,0,q,q).on("click",function(){b.scroll(1,n)}).add(y)),b.scroll(0),a=c):y&&(r(),this.nav=y.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a},scroll:function(a,d){var b=this.pages,f=b.length;a=this.currentPage+a;var m=this.clipHeight,h=this.options.navigation,k=this.pager,l=this.padding;a>f&&(a=f);0n&&(e=typeof a[0],"string"===e?d.name= +a[0]:"number"===e&&(d.x=a[0]),c++);u=h.value;)h=d[++f];h&&h.color&&!this.options.color&&(this.color=h.color);return h},destroy:function(){var a=this.series.chart,d=a.hoverPoints,f;a.pointCount--;d&&(this.setState(),F(d,this),d.length||(a.hoverPoints=null));if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)t(this),this.destroyElements();this.legendItem&& +a.legend.destroyItem(this);for(f in this)this[f]=null},destroyElements:function(){for(var a=["graphic","dataLabel","dataLabelUpper","connector","shadowGroup"],d,f=6;f--;)d=a[f],this[d]&&(this[d]=this[d].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,color:this.color,colorIndex:this.colorIndex,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var d=this.series,e=d.tooltipOptions, +h=w(e.valueDecimals,""),b=e.valuePrefix||"",l=e.valueSuffix||"";A(d.pointArrayMap||["y"],function(c){c="{point."+c;if(b||l)a=a.replace(c+"}",b+c+"}"+l);a=a.replace(c+"}",c+":,."+h+"f}")});return f(a,{point:this,series:this.series})},firePointEvent:function(a,d,f){var e=this,b=this.series.options;(b.point.events[a]||e.options&&e.options.events&&e.options.events[a])&&this.importEvents();"click"===a&&b.allowPointSelect&&(f=function(a){e.select&&e.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});n(this, +a,d,f)},visible:!0}})(L);(function(a){var D=a.addEvent,A=a.animObject,G=a.arrayMax,F=a.arrayMin,n=a.correctFloat,f=a.Date,h=a.defaultOptions,l=a.defaultPlotOptions,w=a.defined,t=a.each,e=a.erase,d=a.extend,m=a.fireEvent,C=a.grep,b=a.isArray,x=a.isNumber,c=a.isString,u=a.merge,B=a.objectEach,I=a.pick,k=a.removeEvent,E=a.splat,p=a.SVGElement,z=a.syncTimeout,M=a.win;a.Series=a.seriesType("line",null,{lineWidth:2,allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},marker:{lineWidth:0, +lineColor:"#ffffff",radius:4,states:{hover:{animation:{duration:50},enabled:!0,radiusPlus:2,lineWidthPlus:1},select:{fillColor:"#cccccc",lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return null===this.y?"":a.numberFormat(this.y,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"contrast",textOutline:"1px contrast"},verticalAlign:"bottom",x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{animation:{duration:50}, +lineWidthPlus:1,marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3,findNearestPointBy:"x"},{isCartesian:!0,pointClass:a.Point,sorted:!0,requireSorting:!0,directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],coll:"series",init:function(a,b){var c=this,e,g=a.series,q;c.chart=a;c.options=b=c.setOptions(b);c.linkedSeries=[];c.bindAxes();d(c,{name:b.name,state:"",visible:!1!==b.visible,selected:!0===b.selected});e=b.events;B(e,function(a, +b){D(c,b,a)});if(e&&e.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;c.getColor();c.getSymbol();t(c.parallelArrays,function(a){c[a+"Data"]=[]});c.setData(b.data,!1);c.isCartesian&&(a.hasCartesianSeries=!0);g.length&&(q=g[g.length-1]);c._i=I(q&&q._i,-1)+1;a.orderSeries(this.insert(g))},insert:function(a){var b=this.options.index,c;if(x(b)){for(c=a.length;c--;)if(b>=I(a[c].options.index,a[c]._i)){a.splice(c+1,0,this);break}-1===c&&a.unshift(this);c+=1}else a.push(this); +return I(c,a.length-1)},bindAxes:function(){var b=this,c=b.options,d=b.chart,e;t(b.axisTypes||[],function(g){t(d[g],function(a){e=a.options;if(c[g]===e.index||void 0!==c[g]&&c[g]===e.id||void 0===c[g]&&0===e.index)b.insert(a.series),b[g]=a,a.isDirty=!0});b[g]||b.optionalAxis===g||a.error(18,!0)})},updateParallelArrays:function(a,b){var c=a.series,d=arguments,g=x(b)?function(d){var g="y"===d&&c.toYData?c.toYData(a):a[d];c[d+"Data"][b]=g}:function(a){Array.prototype[b].apply(c[a+"Data"],Array.prototype.slice.call(d, +2))};t(c.parallelArrays,g)},autoIncrement:function(){var a=this.options,b=this.xIncrement,c,d=a.pointIntervalUnit,b=I(b,a.pointStart,0);this.pointInterval=c=I(this.pointInterval,a.pointInterval,1);d&&(a=new f(b),"day"===d?a=+a[f.hcSetDate](a[f.hcGetDate]()+c):"month"===d?a=+a[f.hcSetMonth](a[f.hcGetMonth]()+c):"year"===d&&(a=+a[f.hcSetFullYear](a[f.hcGetFullYear]()+c)),c=a-b);this.xIncrement=b+c;return b},setOptions:function(a){var b=this.chart,c=b.options,d=c.plotOptions,g=(b.userOptions||{}).plotOptions|| +{},e=d[this.type];this.userOptions=a;b=u(e,d.series,a);this.tooltipOptions=u(h.tooltip,h.plotOptions.series&&h.plotOptions.series.tooltip,h.plotOptions[this.type].tooltip,c.tooltip.userOptions,d.series&&d.series.tooltip,d[this.type].tooltip,a.tooltip);this.stickyTracking=I(a.stickyTracking,g[this.type]&&g[this.type].stickyTracking,g.series&&g.series.stickyTracking,this.tooltipOptions.shared&&!this.noSharedTooltip?!0:b.stickyTracking);null===e.marker&&delete b.marker;this.zoneAxis=b.zoneAxis;a=this.zones= +(b.zones||[]).slice();!b.negativeColor&&!b.negativeFillColor||b.zones||a.push({value:b[this.zoneAxis+"Threshold"]||b.threshold||0,className:"highcharts-negative",color:b.negativeColor,fillColor:b.negativeFillColor});a.length&&w(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return b},getCyclic:function(a,b,c){var d,g=this.chart,e=this.userOptions,q=a+"Index",f=a+"Counter",k=c?c.length:I(g.options.chart[a+"Count"],g[a+"Count"]);b||(d=I(e[q],e["_"+q]),w(d)||(g.series.length|| +(g[f]=0),e["_"+q]=d=g[f]%k,g[f]+=1),c&&(b=c[d]));void 0!==d&&(this[q]=d);this[a]=b},getColor:function(){this.options.colorByPoint?this.options.color=null:this.getCyclic("color",this.options.color||l[this.type].color,this.chart.options.colors)},getSymbol:function(){this.getCyclic("symbol",this.options.marker.symbol,this.chart.options.symbols)},drawLegendSymbol:a.LegendSymbolMixin.drawLineMarker,setData:function(d,e,f,k){var g=this,q=g.points,m=q&&q.length||0,p,h=g.options,y=g.chart,l=null,n=g.xAxis, +u=h.turboThreshold,z=this.xData,H=this.yData,w=(p=g.pointArrayMap)&&p.length;d=d||[];p=d.length;e=I(e,!0);if(!1!==k&&p&&m===p&&!g.cropped&&!g.hasGroupedData&&g.visible)t(d,function(a,b){q[b].update&&a!==h.data[b]&&q[b].update(a,!1,null,!1)});else{g.xIncrement=null;g.colorCounter=0;t(this.parallelArrays,function(a){g[a+"Data"].length=0});if(u&&p>u){for(f=0;null===l&&fm||this.forceCrop))if(c[e-1]x)c=[],d=[];else if(c[0]x)g=this.cropData(this.xData,this.yData,u,x),c=g.xData,d=g.yData,g=g.start,f=!0;for(m=c.length|| +1;--m;)e=n?p(c[m])-p(c[m-1]):c[m]-c[m-1],0e&&this.requireSorting&&a.error(15);this.cropped=f;this.cropStart=g;this.processedXData=c;this.processedYData=d;this.closestPointRange=q},cropData:function(a,b,c,d){var g=a.length,e=0,f=g,q=I(this.cropShoulder,1),k;for(k=0;k=c){e=Math.max(0,k-q);break}for(c=k;cd){f=c+q;break}return{xData:a.slice(e,f),yData:b.slice(e,f),start:e,end:f}},generatePoints:function(){var a=this.options,b=a.data,c=this.data, +d,g=this.processedXData,e=this.processedYData,f=this.pointClass,k=g.length,m=this.cropStart||0,p,h=this.hasGroupedData,a=a.keys,l,n=[],u;c||h||(c=[],c.length=b.length,c=this.data=c);a&&h&&(this.options.keys=!1);for(u=0;u=q&&(d[l]||p)<=k,m&&p)if(m=h.length)for(;m--;)null!==h[m]&&(g[f++]=h[m]);else g[f++]=h;this.dataMin= +F(g);this.dataMax=G(g)},translate:function(){this.processedXData||this.processData();this.generatePoints();var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,g=this.yAxis,e=this.points,f=e.length,k=!!this.modifyValue,m=a.pointPlacement,p="between"===m||x(m),h=a.threshold,l=a.startFromThreshold?h:0,u,z,t,E,C=Number.MAX_VALUE;"between"===m&&(m=.5);x(m)&&(m*=I(a.pointRange||c.pointRange));for(a=0;a=A&&(B.isNull=!0);B.plotX=u=n(Math.min(Math.max(-1E5,c.translate(M,0,0,0,1,m,"flags"===this.type)),1E5));b&&this.visible&&!B.isNull&&D&&D[M]&&(E=this.getStackIndicator(E,M,this.index),F=D[M],A=F.points[E.key],z=A[0],A=A[1],z===l&&E.key===D[M].base&&(z=I(h,g.min)),g.positiveValuesOnly&&0>=z&&(z=null),B.total=B.stackTotal=F.total,B.percentage=F.total&&B.y/F.total*100,B.stackY=A,F.setOffset(this.pointXOffset||0,this.barW||0));B.yBottom=w(z)?g.translate(z,0,1,0,1): +null;k&&(A=this.modifyValue(A,B));B.plotY=z="number"===typeof A&&Infinity!==A?Math.min(Math.max(-1E5,g.translate(A,0,1,0,1)),1E5):void 0;B.isInside=void 0!==z&&0<=z&&z<=g.len&&0<=u&&u<=c.len;B.clientX=p?n(c.translate(M,0,0,0,1,m)):u;B.negative=B.y<(h||0);B.category=d&&void 0!==d[B.x]?d[B.x]:B.x;B.isNull||(void 0!==t&&(C=Math.min(C,Math.abs(u-t))),t=u);B.zone=this.zones.length&&B.getZone()}this.closestPointRangePx=C},getValidPoints:function(a,b){var c=this.chart;return C(a||this.points||[],function(a){return b&& +!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,g=b.inverted,e=this.clipBox,f=e||b.clipBox,q=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,f.height,c.xAxis,c.yAxis].join(),k=b[q],m=b[q+"m"];k||(a&&(f.width=0,b[q+"m"]=m=d.clipRect(-99,g?-b.plotLeft:-b.plotTop,99,g?b.chartWidth:b.chartHeight)),b[q]=k=d.clipRect(f),k.count={length:0});a&&!k.count[this.index]&&(k.count[this.index]=!0,k.count.length+=1);!1!==c.clip&& +(this.group.clip(a||e?k:b.clipRect),this.markerGroup.clip(m),this.sharedClipKey=q);a||(k.count[this.index]&&(delete k.count[this.index],--k.count.length),0===k.count.length&&q&&b[q]&&(e||(b[q]=b[q].destroy()),b[q+"m"]&&(b[q+"m"]=b[q+"m"].destroy())))},animate:function(a){var b=this.chart,c=A(this.options.animation),d;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99},c),this.animate=null)},afterAnimate:function(){this.setClip(); +m(this,"afterAnimate")},drawPoints:function(){var a=this.points,b=this.chart,c,d,g,e,f=this.options.marker,k,m,p,h,l=this[this.specialGroup]||this.markerGroup,n=I(f.enabled,this.xAxis.isRadial?!0:null,this.closestPointRangePx>=2*f.radius);if(!1!==f.enabled||this._hasPointMarkers)for(d=0;de&&b.shadow));f&&(f.startX=c.xMap,f.isArea=c.isArea)})},applyZones:function(){var a=this,b=this.chart,c=b.renderer, +d=this.zones,g,e,f=this.clips||[],k,m=this.graph,p=this.area,h=Math.max(b.chartWidth,b.chartHeight),l=this[(this.zoneAxis||"y")+"Axis"],n,u,x=b.inverted,z,E,w,B,C=!1;d.length&&(m||p)&&l&&void 0!==l.min&&(u=l.reversed,z=l.horiz,m&&m.hide(),p&&p.hide(),n=l.getExtremes(),t(d,function(d,q){g=u?z?b.plotWidth:0:z?0:l.toPixels(n.min);g=Math.min(Math.max(I(e,g),0),h);e=Math.min(Math.max(Math.round(l.toPixels(I(d.value,n.max),!0)),0),h);C&&(g=e=l.toPixels(n.max));E=Math.abs(g-e);w=Math.min(g,e);B=Math.max(g, +e);l.isXAxis?(k={x:x?B:w,y:0,width:E,height:h},z||(k.x=b.plotHeight-k.x)):(k={x:0,y:x?B:w,width:h,height:E},z&&(k.y=b.plotWidth-k.y));x&&c.isVML&&(k=l.isXAxis?{x:0,y:u?w:B,height:k.width,width:b.chartWidth}:{x:k.y-b.plotLeft-b.spacingBox.x,y:0,width:k.height,height:b.chartHeight});f[q]?f[q].animate(k):(f[q]=c.clipRect(k),m&&a["zone-graph-"+q].clip(f[q]),p&&a["zone-area-"+q].clip(f[q]));C=d.value>n.max}),this.clips=f)},invertGroups:function(a){function b(){t(["group","markerGroup"],function(b){c[b]&& +(d.renderer.isVML&&c[b].attr({width:c.yAxis.len,height:c.xAxis.len}),c[b].width=c.yAxis.len,c[b].height=c.xAxis.len,c[b].invert(a))})}var c=this,d=c.chart,g;c.xAxis&&(g=D(d,"resize",b),D(c,"destroy",g),b(a),c.invertGroups=b)},plotGroup:function(a,b,c,d,g){var e=this[a],f=!e;f&&(this[a]=e=this.chart.renderer.g().attr({zIndex:d||.1}).add(g));e.addClass("highcharts-"+b+" highcharts-series-"+this.index+" highcharts-"+this.type+"-series highcharts-color-"+this.colorIndex+" "+(this.options.className||""), +!0);e.attr({visibility:c})[f?"attr":"animate"](this.getPlotBox());return e},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,g=!!a.animate&&b.renderer.isSVG&&A(d.animation).duration,e=a.visible?"inherit":"hidden",f=d.zIndex,k=a.hasRendered,m=b.seriesGroup,p=b.inverted;c=a.plotGroup("group","series",e,f,m);a.markerGroup= +a.plotGroup("markerGroup","markers",e,f,m);g&&a.animate(!0);c.inverted=a.isCartesian?p:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(p);!1===d.clip||a.sharedClipKey||k||c.clip(b.clipRect);g&&a.animate();k||(a.animationTimeout=z(function(){a.afterAnimate()},g));a.isDirty=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData, +c=this.group,d=this.xAxis,g=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:I(d&&d.left,a.plotLeft),translateY:I(g&&g.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdAxisArray:["clientX","plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,g=this.chart.inverted;return this.searchKDTree({clientX:g?c.len-a.chartY+c.pos:a.chartX-c.pos,plotY:g?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c, +d,e){var g,f;if(f=c&&c.length)return g=b.kdAxisArray[d%e],c.sort(function(a,b){return a[g]-b[g]}),f=Math.floor(f/2),{point:c[f],left:a(c.slice(0,f),d+1,e),right:a(c.slice(f+1),d+1,e)}}this.buildingKdTree=!0;var b=this,c=-1q?"left":"right";l=0>q?"right":"left";b[h]&&(h=c(a,b[h],g+1,m),n=h[k]u;)n--;this.updateParallelArrays(m,"splice",n,0,0);this.updateParallelArrays(m,n);g&&m.name&&(g[u]=m.name);h.splice(n,0,a);q&&(this.data.splice(n,0,null),this.processData());"point"===f.legendType&&this.generatePoints();d&&(k[0]&&k[0].remove?k[0].remove(!1):(k.shift(),this.updateParallelArrays(m,"shift"),h.shift()));this.isDirtyData=this.isDirty=!0;b&&p.redraw(e)},removePoint:function(a,b,d){var e=this,f=e.data,p=f[a],h=e.points, +g=e.chart,m=function(){h&&h.length===f.length&&h.splice(a,1);f.splice(a,1);e.options.data.splice(a,1);e.updateParallelArrays(p||{series:e},"splice",a,1);p&&p.destroy();e.isDirty=!0;e.isDirtyData=!0;b&&g.redraw()};k(d,g);b=c(b,!0);p?p.firePointEvent("remove",null,m):m()},remove:function(a,b,d){function e(){f.destroy();k.isDirtyLegend=k.isDirtyBox=!0;k.linkSeries();c(a,!0)&&k.redraw(b)}var f=this,k=f.chart;!1!==d?t(f,"remove",null,e):e()},update:function(a,d){var e=this,f=e.chart,k=e.userOptions,p= +e.oldType||e.type,m=a.type||k.type||f.options.chart.type,g=I[p].prototype,l=["group","markerGroup","dataLabelsGroup"],n;if(m&&m!==p||void 0!==a.zIndex)l.length=0;h(l,function(a){l[a]=e[a];delete e[a]});a=b(k,{animation:!1,index:e.index,pointStart:e.xData[0]},{data:e.options.data},a);e.remove(!1,null,!1);for(n in g)e[n]=void 0;w(e,I[m||p].prototype);h(l,function(a){e[a]=l[a]});e.init(f,a);e.oldType=p;f.linkSeries();c(d,!0)&&f.redraw(!1)}});w(G.prototype,{update:function(a,d){var e=this.chart;a=e.options[this.coll][this.options.index]= +b(this.userOptions,a);this.destroy(!0);this.init(e,w(a,{events:void 0}));e.isDirtyBox=!0;c(d,!0)&&e.redraw()},remove:function(a){for(var b=this.chart,d=this.coll,e=this.series,f=e.length;f--;)e[f]&&e[f].remove(!1);l(b.axes,this);l(b[d],this);C(b.options[d])?b.options[d].splice(this.options.index,1):delete b.options[d];h(b[d],function(a,b){a.options.index=b});this.destroy();b.isDirtyBox=!0;c(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a}, +b)}})})(L);(function(a){var D=a.color,A=a.each,G=a.map,F=a.pick,n=a.Series,f=a.seriesType;f("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(){var f=[],l=[],n=this.xAxis,t=this.yAxis,e=t.stacks[this.stackKey],d={},m=this.points,C=this.index,b=t.series,x=b.length,c,u=F(t.options.reversedStacks,!0)?1:-1,B;if(this.options.stacking){for(B=0;Ba&&w>f?(w=Math.max(a,f),e=2*f-w):wF&&e>f?(e=Math.max(F,f),w=2*f-e):e=Math.abs(d)&&.5a.closestPointRange*a.xAxis.transA,n=a.borderWidth=h(f.borderWidth,n?0:1),b=a.yAxis,x=a.translatedThreshold=b.getThreshold(f.threshold),c=h(f.minPointLength,5),u=a.getColumnMetrics(),t=u.width,w=a.barW=Math.max(t,1+2*n),k=a.pointXOffset=u.offset; +d.inverted&&(x-=.5);f.pointPadding&&(w=Math.ceil(w));l.prototype.translate.apply(a);G(a.points,function(e){var f=h(e.yBottom,x),m=999+Math.abs(f),m=Math.min(Math.max(-m,e.plotY),b.len+m),l=e.plotX+k,q=w,n=Math.min(m,f),u,E=Math.max(m,f)-n;Math.abs(E)c?f-c:x-(u?c:0));e.barX=l;e.pointWidth=t;e.tooltipPos=d.inverted?[b.len+b.pos-d.plotLeft-m,a.xAxis.len-l-q/2,E]:[l+q/2,m+b.pos-d.plotTop,E];e.shapeType="rect";e.shapeArgs=a.crispCol.apply(a, +e.isNull?[l,x,q,0]:[l,n,q,E])})},getSymbol:a.noop,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")},pointAttribs:function(a,d){var e=this.options,h,b=this.pointAttrToOptions||{};h=b.stroke||"borderColor";var l=b["stroke-width"]||"borderWidth",c=a&&a.color||this.color,n=a[h]||e[h]||this.color||c,t=a[l]||e[l]||this[l]||0,b=e.dashStyle;a&&this.zones.length&&(c=a.getZone(),c=a.options.color||c&&c.color||this.color); +d&&(a=f(e.states[d],a.options.states&&a.options.states[d]||{}),d=a.brightness,c=a.color||void 0!==d&&A(c).brighten(a.brightness).get()||c,n=a[h]||n,t=a[l]||t,b=a.dashStyle||b);h={fill:c,stroke:n,"stroke-width":t};e.borderRadius&&(h.r=e.borderRadius);b&&(h.dashstyle=b);return h},drawPoints:function(){var a=this,d=this.chart,h=a.options,l=d.renderer,b=h.animationLimit||250,t;G(a.points,function(c){var e=c.graphic;if(n(c.plotY)&&null!==c.y){t=c.shapeArgs;if(e)e[d.pointCountw;++w)t=h[w],a=2>w||2===w&&/%$/.test(t),h[w]=A(t,[f,F,l,h[2]][w])+(a?n:0);h[3]>h[2]&&(h[3]=h[2]);return h}}})(L);(function(a){var D=a.addEvent,A=a.defined,G=a.each,F=a.extend,n=a.inArray,f=a.noop,h=a.pick,l=a.Point,w=a.Series,t=a.seriesType,e=a.setAnimation;t("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.isNull?void 0:this.point.name}, +x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",borderWidth:1,states:{hover:{brightness:.1,shadow:!1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:a.seriesTypes.column.prototype.pointAttribs,animate:function(a){var d=this,e=d.points,b=d.startAngleRad;a||(G(e,function(a){var c=a.graphic,e=a.shapeArgs; +c&&(c.attr({r:a.startR||d.center[3]/2,start:b,end:b}),c.animate({r:e.r,start:e.start,end:e.end},d.options.animation))}),d.animate=null)},updateTotals:function(){var a,e=0,f=this.points,b=f.length,h,c=this.options.ignoreHiddenPoint;for(a=0;a1.5*Math.PI?n-=2*Math.PI:n<-Math.PI/2&&(n+=2*Math.PI);y.slicedTranslation={translateX:Math.round(Math.cos(n)*b),translateY:Math.round(Math.sin(n)*b)};l=Math.cos(n)*a[2]/2;p=Math.sin(n)*a[2]/2;y.tooltipPos=[a[0]+ +.7*l,a[1]+.7*p];y.half=n<-Math.PI/2||n>Math.PI/2?1:0;y.angle=n;c=Math.min(f,y.labelDistance/5);y.labelPos=[a[0]+l+Math.cos(n)*y.labelDistance,a[1]+p+Math.sin(n)*y.labelDistance,a[0]+l+Math.cos(n)*c,a[1]+p+Math.sin(n)*c,a[0]+l,a[1]+p,0>y.labelDistance?"center":y.half?"right":"left",n]}},drawGraph:null,drawPoints:function(){var a=this,e=a.chart.renderer,f,b,h,c,l=a.options.shadow;l&&!a.shadowGroup&&(a.shadowGroup=e.g("shadow").add(a.group));G(a.points,function(d){if(!d.isNull){b=d.graphic;c=d.shapeArgs; +f=d.getTranslate();var m=d.shadowGroup;l&&!m&&(m=d.shadowGroup=e.g("shadow").add(a.shadowGroup));m&&m.attr(f);h=a.pointAttribs(d,d.selected&&"select");b?b.setRadialReference(a.center).attr(h).animate(F(c,f)):(d.graphic=b=e[d.shapeType](c).setRadialReference(a.center).attr(f).add(a.group),d.visible||b.attr({visibility:"hidden"}),b.attr(h).attr({"stroke-linejoin":"round"}).shadow(l,m));b.addClass(d.getClassName())}})},searchPoint:f,sortByAngle:function(a,e){a.sort(function(a,b){return void 0!==a.angle&& +(b.angle-a.angle)*e})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,getCenter:a.CenteredSeriesMixin.getCenter,getSymbol:f},{init:function(){l.prototype.init.apply(this,arguments);var a=this,e;a.name=h(a.name,"Slice");e=function(d){a.slice("select"===d.type)};D(a,"select",e);D(a,"unselect",e);return a},isValid:function(){return a.isNumber(this.y,!0)&&0<=this.y},setVisible:function(a,e){var d=this,b=d.series,f=b.chart,c=b.options.ignoreHiddenPoint;e=h(e,c);a!==d.visible&&(d.visible=d.options.visible= +a=void 0===a?!d.visible:a,b.options.data[n(d,b.data)]=d.options,G(["graphic","dataLabel","connector","shadowGroup"],function(b){if(d[b])d[b][a?"show":"hide"](!0)}),d.legendItem&&f.legend.colorizeItem(d,a),a||"hover"!==d.state||d.setState(""),c&&(b.isDirty=!0),e&&f.redraw())},slice:function(a,f,l){var b=this.series;e(l,b.chart);h(f,!0);this.sliced=this.options.sliced=A(a)?a:!this.sliced;b.options.data[n(this,b.data)]=this.options;this.graphic.animate(this.getTranslate());this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())}, +getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(a){var d=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(d.x,d.y,d.r+a,d.r+a,{innerR:this.shapeArgs.r,start:d.start,end:d.end})}})})(L);(function(a){var D=a.addEvent,A=a.arrayMax,G=a.defined,F=a.each,n=a.extend,f=a.format,h=a.map,l=a.merge,w=a.noop,t=a.pick,e=a.relativeLength,d=a.Series,m=a.seriesTypes,C=a.stableSort;a.distribute=function(a,d){function b(a, +b){return a.target-b.target}var e,f=!0,l=a,k=[],n;n=0;for(e=a.length;e--;)n+=a[e].size;if(n>d){C(a,function(a,b){return(b.rank||0)-(a.rank||0)});for(n=e=0;n<=d;)n+=a[e].size,e++;k=a.splice(e-1,a.length)}C(a,b);for(a=h(a,function(a){return{size:a.size,targets:[a.target]}});f;){for(e=a.length;e--;)f=a[e],n=(Math.min.apply(0,f.targets)+Math.max.apply(0,f.targets))/2,f.pos=Math.min(Math.max(0,n-f.size/2),d-f.size);e=a.length;for(f=!1;e--;)0a[e].pos&&(a[e-1].size+=a[e].size, +a[e-1].targets=a[e-1].targets.concat(a[e].targets),a[e-1].pos+a[e-1].size>d&&(a[e-1].pos=d-a[e-1].size),a.splice(e,1),f=!0)}e=0;F(a,function(a){var b=0;F(a.targets,function(){l[e].pos=a.pos+b;b+=l[e].size;e++})});l.push.apply(l,k);C(l,b)};d.prototype.drawDataLabels=function(){var b=this,d=b.options,c=d.dataLabels,e=b.points,h,n,k=b.hasRendered||0,m,p,z=t(c.defer,!0),w=b.chart.renderer;if(c.enabled||b._hasPointLabels)b.dlProcessOptions&&b.dlProcessOptions(c),p=b.plotGroup("dataLabelsGroup","data-labels", +z&&!k?"hidden":"visible",c.zIndex||6),z&&(p.attr({opacity:+k}),k||D(b,"afterAnimate",function(){b.visible&&p.show(!0);p[d.animation?"animate":"attr"]({opacity:1},{duration:200})})),n=c,F(e,function(e){var k,q=e.dataLabel,u,g,r=e.connector,x=!q,z;h=e.dlOptions||e.options&&e.options.dataLabels;if(k=t(h&&h.enabled,n.enabled)&&null!==e.y)c=l(n,h),u=e.getLabelConfig(),m=c.format?f(c.format,u):c.formatter.call(u,c),z=c.style,u=c.rotation,z.color=t(c.color,z.color,b.color,"#000000"),"contrast"===z.color&& +(e.contrastColor=w.getContrast(e.color||b.color),z.color=c.inside||0>t(e.labelDistance,c.distance)||d.stacking?e.contrastColor:"#000000"),d.cursor&&(z.cursor=d.cursor),g={fill:c.backgroundColor,stroke:c.borderColor,"stroke-width":c.borderWidth,r:c.borderRadius||0,rotation:u,padding:c.padding,zIndex:1},a.objectEach(g,function(a,b){void 0===a&&delete g[b]});!q||k&&G(m)?k&&G(m)&&(q?g.text=m:(q=e.dataLabel=w[u?"text":"label"](m,0,-9999,c.shape,null,null,c.useHTML,null,"data-label"),q.addClass("highcharts-data-label-color-"+ +e.colorIndex+" "+(c.className||"")+(c.useHTML?"highcharts-tracker":""))),q.attr(g),q.css(z).shadow(c.shadow),q.added||q.add(p),b.alignDataLabel(e,q,c,null,x)):(e.dataLabel=q=q.destroy(),r&&(e.connector=r.destroy()))})};d.prototype.alignDataLabel=function(a,d,c,e,f){var b=this.chart,k=b.inverted,h=t(a.plotX,-9999),p=t(a.plotY,-9999),l=d.getBBox(),m,q=c.rotation,u=c.align,x=this.visible&&(a.series.forceDL||b.isInsidePlot(h,Math.round(p),k)||e&&b.isInsidePlot(h,k?e.x+1:e.y+e.height-1,k)),w="justify"=== +t(c.overflow,"justify");if(x&&(m=c.style.fontSize,m=b.renderer.fontMetrics(m,d).b,e=n({x:k?b.plotWidth-p:h,y:Math.round(k?b.plotHeight-h:p),width:0,height:0},e),n(c,{width:l.width,height:l.height}),q?(w=!1,h=b.renderer.rotCorr(m,q),h={x:e.x+c.x+e.width/2+h.x,y:e.y+c.y+{top:0,middle:.5,bottom:1}[c.verticalAlign]*e.height},d[f?"attr":"animate"](h).attr({align:u}),p=(q+720)%360,p=180p,"left"===u?h.y-=p?l.height:0:"center"===u?(h.x-=l.width/2,h.y-=l.height/2):"right"===u&&(h.x-=l.width,h.y-=p? +0:l.height)):(d.align(c,null,e),h=d.alignAttr),w?a.isLabelJustified=this.justifyDataLabel(d,c,h,l,e,f):t(c.crop,!0)&&(x=b.isInsidePlot(h.x,h.y)&&b.isInsidePlot(h.x+l.width,h.y+l.height)),c.shape&&!q))d[f?"attr":"animate"]({anchorX:k?b.plotWidth-a.plotY:a.plotX,anchorY:k?b.plotHeight-a.plotX:a.plotY});x||(d.attr({y:-9999}),d.placed=!1)};d.prototype.justifyDataLabel=function(a,d,c,e,f,h){var b=this.chart,l=d.align,p=d.verticalAlign,n,m,q=a.box?0:a.padding||0;n=c.x+q;0>n&&("right"===l?d.align="left": +d.x=-n,m=!0);n=c.x+e.width-q;n>b.plotWidth&&("left"===l?d.align="right":d.x=b.plotWidth-n,m=!0);n=c.y+q;0>n&&("bottom"===p?d.verticalAlign="top":d.y=-n,m=!0);n=c.y+e.height-q;n>b.plotHeight&&("top"===p?d.verticalAlign="bottom":d.y=b.plotHeight-n,m=!0);m&&(a.placed=!h,a.align(d,null,f));return m};m.pie&&(m.pie.prototype.drawDataLabels=function(){var b=this,e=b.data,c,f=b.chart,h=b.options.dataLabels,l=t(h.connectorPadding,10),k=t(h.connectorWidth,1),n=f.plotWidth,p=f.plotHeight,m,w=b.center,q=w[2]/ +2,y=w[1],C,D,g,r,L=[[],[]],J,N,O,P,v=[0,0,0,0];b.visible&&(h.enabled||b._hasPointLabels)&&(F(e,function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),d.prototype.drawDataLabels.apply(b),F(e,function(a){a.dataLabel&&a.visible&&(L[a.half].push(a),a.dataLabel._pos=null)}),F(L,function(d,e){var k,m,t=d.length,u=[],x;if(t)for(b.sortByAngle(d,e-.5),0c.bottom-2?k:N,e,c),C._attr={visibility:O,align:g[6]},C._pos={x:J+h.x+({left:l,right:-l}[g[6]]||0),y:N+h.y-10},g.x=J,g.y=N,null===b.options.size&&(D=C.getBBox().width,k=null,J-Dn-l&&(k=Math.round(J+D-n+l),v[1]=Math.max(k,v[1])),0>N-r/2?v[0]=Math.max(Math.round(-N+r/2),v[0]):N+r/2>p&&(v[2]=Math.max(Math.round(N+r/2-p),v[2])),C.sideOverflow=k)}),0===A(v)||this.verifyDataLabelOverflow(v))&& +(this.placeDataLabels(),k&&F(this.points,function(a){var c;m=a.connector;if((C=a.dataLabel)&&C._pos&&a.visible&&0t(this.translatedThreshold,k.yAxis.len)),n=t(c.inside,!!this.options.stacking);m&&(f=l(m),0>f.y&&(f.height+=f.y,f.y=0),m=f.y+f.height-k.yAxis.len,0a+d||f+lb+e||h+mthis.pointCount))}, +pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&h(d,function(a){a.setState()});h("xy"===b?[1,0]:[1],function(b){b=c[b?"xAxis":"yAxis"][0];var d=b.horiz,f=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",h=c[d],g=(b.pointRange||0)/2,k=b.getExtremes(),l=b.toValue(h-f,!0)+g,g=b.toValue(h+b.len-f,!0)-g,m=g=f(l.minWidth,0)&&this.chartHeight>=f(l.minHeight,0)}).call(this)&&h.push(a._id)};D.prototype.currentOptions=function(f){function l(e,d,f,t){var b;a.objectEach(e,function(a,c){if(!t&&-1