Merge branch 'dev'

This commit is contained in:
gregoirenovel 2018-08-27 17:20:04 +02:00
commit cf68d612e1
21 changed files with 186 additions and 54 deletions

View file

@ -84,6 +84,8 @@ gem "premailer-rails"
gem 'smart_listing' gem 'smart_listing'
gem 'groupdate'
gem 'bootstrap-wysihtml5-rails', '~> 0.3.3.8' gem 'bootstrap-wysihtml5-rails', '~> 0.3.3.8'
gem 'spreadsheet_architect', '~> 1.4.8' # https://github.com/westonganger/spreadsheet_architect/issues/14 gem 'spreadsheet_architect', '~> 1.4.8' # https://github.com/westonganger/spreadsheet_architect/issues/14

View file

@ -369,6 +369,8 @@ GEM
formatador (0.2.5) formatador (0.2.5)
globalid (0.4.1) globalid (0.4.1)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
groupdate (4.0.1)
activesupport (>= 4.2)
guard (2.14.2) guard (2.14.2)
formatador (>= 0.2.4) formatador (>= 0.2.4)
listen (>= 2.7, < 4.0) listen (>= 2.7, < 4.0)
@ -834,6 +836,7 @@ DEPENDENCIES
fog fog
fog-openstack fog-openstack
font-awesome-rails font-awesome-rails
groupdate
guard guard
guard-livereload guard-livereload
guard-rspec guard-rspec

View file

@ -325,7 +325,7 @@ $users-breakpoint: 950px;
$cta-panel-button-border-size: 2px; $cta-panel-button-border-size: 2px;
.cta-panel-button-white { @mixin cta-panel-button {
@include horizontal-padding(40px); @include horizontal-padding(40px);
@include vertical-padding(15px); @include vertical-padding(15px);
display: block; display: block;
@ -334,6 +334,10 @@ $cta-panel-button-border-size: 2px;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
margin-top: 20px; margin-top: 20px;
}
.cta-panel-button-white {
@include cta-panel-button;
border: $cta-panel-button-border-size solid #FFFFFF; border: $cta-panel-button-border-size solid #FFFFFF;
color: #FFFFFF; color: #FFFFFF;
@ -349,45 +353,24 @@ $cta-panel-button-border-size: 2px;
} }
} }
.cta-panel-button { .cta-panel-button-blue {
@include horizontal-padding(40px); @include cta-panel-button;
@include vertical-padding(15px); border: $cta-panel-button-border-size solid $light-blue;
display: block; color: $light-blue;
border-radius: 100px;
font-size: 24px;
text-align: center;
cursor: pointer;
margin-top: 20px;
&.black { &:hover {
border: $cta-panel-button-border-size solid #000000; color: #FFFFFF;
color: #000000; background-color: $light-blue;
text-decoration: none;
&:hover {
text-decoration: none;
background-color: #F8F8F8;
}
&:focus { &:focus {
color: #F8F8F8; color: #FFFFFF;
text-decoration: none;
} }
} }
&.white { &:focus {
border: $cta-panel-button-border-size solid #FFFFFF; color: $light-blue;
color: #FFFFFF; text-decoration: none;
&:hover {
color: #FFFFFF;
text-decoration: none;
background-color: rgba(255, 255, 255, 0.2);
}
&:focus {
color: #FFFFFF;
text-decoration: none;
}
} }
} }

View file

@ -18,7 +18,7 @@ class DemandesController < ApplicationController
demande_params[:deadline] demande_params[:deadline]
) )
flash.notice = 'Votre demande a bien été enregistrée, nous vous contacterons rapidement.' flash.notice = 'Votre demande a bien été enregistrée, nous vous contacterons rapidement.'
redirect_to root_path redirect_to administration_path
end end
private private

View file

@ -1,6 +1,6 @@
class NewUser::FeedbacksController < ApplicationController class NewUser::FeedbacksController < ApplicationController
def create def create
current_user.feedbacks.create!(mark: params[:mark]) current_user.feedbacks.create!(rating: params[:rating])
flash.notice = "Merci de votre retour" flash.notice = "Merci de votre retour, si vous souhaitez nous en dire plus, n'hésitez pas à <a href='mailto:#{CONTACT_EMAIL}' target='_blank'>nous contacter par email</a>."
end end
end end

View file

@ -1,6 +1,8 @@
class StatsController < ApplicationController class StatsController < ApplicationController
layout "new_application" layout "new_application"
before_action :authenticate_administration!, only: [:download]
MEAN_NUMBER_OF_CHAMPS_IN_A_FORM = 24.0 MEAN_NUMBER_OF_CHAMPS_IN_A_FORM = 24.0
def index def index
@ -10,6 +12,9 @@ class StatsController < ApplicationController
@procedures_count = procedures.count @procedures_count = procedures.count
@dossiers_count = dossiers.count @dossiers_count = dossiers.count
@satisfaction_usagers = satisfaction_usagers
@dossiers_states = dossiers_states
@procedures_cumulative = cumulative_hash(procedures, :published_at) @procedures_cumulative = cumulative_hash(procedures, :published_at)
@procedures_in_the_last_4_months = last_four_months_hash(procedures, :published_at) @procedures_in_the_last_4_months = last_four_months_hash(procedures, :published_at)
@ -36,8 +41,83 @@ class StatsController < ApplicationController
@cloned_from_library_procedures_ratio = cloned_from_library_procedures_ratio @cloned_from_library_procedures_ratio = cloned_from_library_procedures_ratio
end end
def download
headers = [
'ID du dossier',
'ID de la procédure',
'Nom de la procédure',
'ID utilisateur',
'Etat du fichier',
'Durée en brouillon',
'Durée en construction',
'Durée en instruction'
]
data = Dossier
.includes(:procedure, :user)
.in_batches
.flat_map do |dossiers|
dossiers
.pluck(
"dossiers.id",
"procedures.id",
"procedures.libelle",
"users.id",
"dossiers.state",
"dossiers.en_construction_at - dossiers.created_at",
"dossiers.en_instruction_at - dossiers.en_construction_at",
"dossiers.processed_at - dossiers.en_instruction_at"
)
end
respond_to do |format|
format.csv { send_data(SpreadsheetArchitect.to_xlsx(headers: headers, data: data), filename: "statistiques.csv") }
end
end
private private
def dossiers_states
{
'Brouilllon' => Dossier.state_brouillon.count,
'En construction' => Dossier.state_en_construction.count,
'En instruction' => Dossier.state_en_instruction.count,
'Terminé' => Dossier.state_termine.count
}
end
def satisfaction_usagers
legend = {
Feedback.ratings.fetch(:unhappy) => "Mécontents",
Feedback.ratings.fetch(:neutral) => "Neutres",
Feedback.ratings.fetch(:happy) => "Satisfaits"
}
totals = Feedback.where(created_at: 5.weeks.ago..Time.now).group_by_week(:created_at).count
Feedback::rating.values.map do |rating|
data = Feedback
.where(created_at: 5.weeks.ago..Time.now, rating: rating)
.group_by_week(:created_at)
.count
.map do |week, count|
total = totals[week]
if total > 0
[week, (count.to_f / total).round(2)]
else
0
end
end.to_h
{
name: legend[rating],
data: data
}
end
end
def cloned_from_library_procedures_ratio def cloned_from_library_procedures_ratio
[3.weeks.ago, 2.weeks.ago, 1.week.ago].map do |date| [3.weeks.ago, 2.weeks.ago, 1.week.ago].map do |date|
min_date = date.beginning_of_week min_date = date.beginning_of_week

View file

@ -1,3 +1,9 @@
class Feedback < ApplicationRecord class Feedback < ApplicationRecord
belongs_to :user belongs_to :user
enum rating: {
happy: 'happy',
neutral: 'neutral',
unhappy: 'unhappy'
}
end end

View file

@ -54,15 +54,15 @@
= dossier.updated_at.localtime.strftime("%d/%m/%Y") = dossier.updated_at.localtime.strftime("%d/%m/%Y")
= paginate(@dossiers) = paginate(@dossiers)
- if current_user.feedbacks.empty? - if current_user.feedbacks.empty? || current_user.feedbacks.last.created_at < 1.month.ago
#user-satisfaction #user-satisfaction
%h3 Que pensez-vous de ce service ? %h3 Que pensez-vous de la facilité d'utilisation de ce service ?
.icons .icons
= link_to feedback_path(mark: 0), data: { remote: true, method: :post } do = link_to feedback_path(rating: Feedback.ratings.fetch(:unhappy)), data: { remote: true, method: :post } do
%span.icon.frown %span.icon.frown
= link_to feedback_path(mark: 1), data: { remote: true, method: :post } do = link_to feedback_path(rating: Feedback.ratings.fetch(:neutral)), data: { remote: true, method: :post } do
%span.icon.meh %span.icon.meh
= link_to feedback_path(mark: 2), data: { remote: true, method: :post } do = link_to feedback_path(rating: Feedback.ratings.fetch(:happy)), data: { remote: true, method: :post } do
%span.icon.smile %span.icon.smile
- else - else

View file

@ -1,2 +1,3 @@
window.scroll({ top: 0, left: 0, behavior: 'smooth' });
<%= remove_element('#user-satisfaction') %> <%= remove_element('#user-satisfaction') %>
<%= render_flash %> <%= render_flash %>

View file

@ -5,7 +5,7 @@
Votre dossier nº --numéro du dossier-- a été refusé le --date de décision--. Votre dossier nº --numéro du dossier-- a été refusé le --date de décision--.
%p %p
Le motif de refus est le suivant : --motivation-- Le motif de refus est le suivant : --motivation--.
%p %p
Pour en savoir plus sur le motif du refus, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier-- Pour en savoir plus sur le motif du refus, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier--

View file

@ -5,7 +5,7 @@
Votre dossier nº --numéro du dossier-- a été classé sans suite le --date de décision--. Votre dossier nº --numéro du dossier-- a été classé sans suite le --date de décision--.
%p %p
Le motif est le suivant : --motivation-- Le motif est le suivant : --motivation--.
%p %p
Pour en savoir plus sur les raisons de ce classement sans suite, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier-- Pour en savoir plus sur les raisons de ce classement sans suite, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier--

View file

@ -26,9 +26,7 @@
= link_to "Demander un compte administrateur", = link_to "Demander un compte administrateur",
new_demande_path, new_demande_path,
class: "role-panel-button-primary", class: "role-panel-button-primary",
target: "_blank", rel: "noopener noreferrer"
rel: "noopener noreferrer",
onclick: "javascript: ga('send', 'pageview', '/demander-une-demo')"
= link_to "Voir la documentation", = link_to "Voir la documentation",
DOC_URL, DOC_URL,
@ -189,3 +187,14 @@
class: "cta-panel-button-white", class: "cta-panel-button-white",
target: "_blank", target: "_blank",
rel: "noopener noreferrer" rel: "noopener noreferrer"
.landing-panel
.container
.cta-panel-wrapper
%div
%h1.cta-panel-title Vous êtes prêt pour dématérialiser ?
%p.cta-panel-explanation Réduisez vos temps d'instruction de 50 %
%div
= link_to "Demander un compte administrateur",
new_demande_path,
class: "cta-panel-button-blue"

View file

@ -72,7 +72,7 @@
%div %div
= link_to "Contactez-nous", = link_to "Contactez-nous",
"mailto:#{CONTACT_EMAIL}?subject=Question%20à%20propos%20de%20demarches-simplifiees.fr", "mailto:#{CONTACT_EMAIL}?subject=Question%20à%20propos%20de%20demarches-simplifiees.fr",
class: "cta-panel-button white", class: "cta-panel-button-white",
target: "_blank", target: "_blank",
rel: "noopener noreferrer" rel: "noopener noreferrer"
@ -85,4 +85,4 @@
%div %div
= link_to "Découvrez notre outil", = link_to "Découvrez notre outil",
administration_path, administration_path,
class: "cta-panel-button black" class: "cta-panel-button-blue"

View file

@ -15,6 +15,24 @@
%span.big-number-card-number %span.big-number-card-number
= number_with_delimiter(@dossiers_count) = number_with_delimiter(@dossiers_count)
.stat-card.stat-card-half.pull-left
%span.stat-card-title
Satisfaction usager
.chart-container
.chart
= line_chart @satisfaction_usagers,
colors: ["#F28900", "rgba(161, 0, 5, 0.9)", "#15AD70"]
.stat-card.stat-card-half.pull-left
%span.stat-card-title
Répartition des dossiers
.chart-container
.chart
= pie_chart @dossiers_states,
colors: ["rgba(222, 238, 265, 1)", "rgba(191, 220, 249, 1)", "rgba(113, 176, 239, 1)", "rgba(61, 149, 236, 1)"]
.stat-card.stat-card-half.pull-left .stat-card.stat-card-half.pull-left
%ul.segmented-control.pull-right %ul.segmented-control.pull-right
%li.segmented-control-item.segmented-control-item-active{ :onclick => "DS.toggleChart(event, '.monthly-procedures-chart');" } %li.segmented-control-item.segmented-control-item-active{ :onclick => "DS.toggleChart(event, '.monthly-procedures-chart');" }
@ -112,3 +130,7 @@
= column_chart @cloned_from_library_procedures_ratio, ytitle: 'procédures clonées / total procédure', xtitle: 'semaines' = column_chart @cloned_from_library_procedures_ratio, ytitle: 'procédures clonées / total procédure', xtitle: 'semaines'
.clearfix .clearfix
%h2.new-h2 Téléchargement
= link_to "Télécharger les statistiques (CSV)", stats_download_path(format: :csv), class: 'button secondary'

View file

@ -33,6 +33,6 @@ Rails.application.configure do
config.lograge.logger = ActiveSupport::Logger.new Rails.root.join('log', "logstash_#{Rails.env}.log") config.lograge.logger = ActiveSupport::Logger.new Rails.root.join('log', "logstash_#{Rails.env}.log")
if config.lograge.enabled if config.lograge.enabled
ActiveJobLogSubscriber.attach_to :active_job ActiveJobLogSubscriber.attach_to(:active_job)
end end
end end

View file

@ -99,7 +99,8 @@ Rails.application.routes.draw do
get 'users' => 'users#index' get 'users' => 'users#index'
get 'admin' => 'admin#index' get 'admin' => 'admin#index'
resources :stats, only: [:index] get '/stats' => 'stats#index'
get '/stats/download' => 'stats#download'
resources :accessibilite, only: [:index] resources :accessibilite, only: [:index]
resources :demandes, only: [:new, :create] resources :demandes, only: [:new, :create]

View file

@ -0,0 +1,5 @@
class AddRatingToFeedbacks < ActiveRecord::Migration[5.2]
def change
add_column :feedbacks, :rating, :string
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_08_22_162952) do ActiveRecord::Schema.define(version: 2018_08_27_102828) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -323,6 +323,7 @@ ActiveRecord::Schema.define(version: 2018_08_22_162952) do
t.integer "mark" t.integer "mark"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "rating"
t.index ["user_id"], name: "index_feedbacks_on_user_id" t.index ["user_id"], name: "index_feedbacks_on_user_id"
end end

View file

@ -0,0 +1,19 @@
require Rails.root.join("lib", "tasks", "task_helper")
namespace :'2018_08_27_migrate_feedbacks' do
task run: :environment do
MAPPING = {
0 => Feedback.ratings.fetch(:unhappy),
1 => Feedback.ratings.fetch(:neutral),
2 => Feedback.ratings.fetch(:happy)
}
MAPPING.keys.each do |mark|
rating = MAPPING[mark]
Feedback
.where(mark: mark)
.update_all(rating: rating)
end
end
end

View file

@ -1,5 +1,5 @@
FactoryBot.define do FactoryBot.define do
factory :feedback do factory :feedback do
mark 3 rating Feedback.ratings.fetch(:happy)
end end
end end

View file

@ -74,7 +74,7 @@ describe 'new_user/dossiers/index.html.haml', type: :view do
context "quand le user n'a aucun feedback" do context "quand le user n'a aucun feedback" do
it "affiche le formulaire de satisfaction" do it "affiche le formulaire de satisfaction" do
expect(rendered).to have_selector('#user-satisfaction', text: 'Que pensez-vous de ce service ?') expect(rendered).to have_selector('#user-satisfaction', text: 'Que pensez-vous de la facilité d\'utilisation de ce service ?')
end end
end end