Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ETQ super-admin je peux informer les administrateurs, instructeurs et experts des évolutions du site #9638

Merged
merged 10 commits into from
Nov 9, 2023
2 changes: 2 additions & 0 deletions app/components/application_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ class ApplicationComponent < ViewComponent::Base
include ViewComponent::Translatable
include FlipperHelper

delegate :rich_text_area_tag, to: :helpers

def current_user
controller.current_user
end
Expand Down
31 changes: 31 additions & 0 deletions app/components/release_note/form_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

class ReleaseNote::FormComponent < ApplicationComponent
attr_reader :release_note

def initialize(release_note:)
@release_note = release_note
end

private

def categories_fieldset_class
class_names(
"fr-fieldset--error": categories_error?
)
end

def categories_error?
release_note.errors.key?(:categories)
end

def categories_errors_describedby_id
return nil if !categories_error?

dom_id(release_note, "categories_errors")
end

def categories_full_messages_errors
release_note.errors.full_messages_for(:categories)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
en:
delete: Delete this note
new: New note
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
fr:
delete: Supprimer cette note
new: Ajouter une note
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
= form_for [:super_admins, release_note] do |f|
%fieldset#release_notes_fieldset.fr-fieldset{ 'data-controller': 'trix' }
.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :released_on, input_type: :date_field) do |c|
- c.with_label { ReleaseNote.human_attribute_name(:released_on) }

.fr-fieldset__element
.fr-toggle
= f.check_box :published, class: "fr-toggle-input", id: dom_id(release_note, :published)
%label.fr-toggle__label{ for: dom_id(release_note, :published), data: { fr_checked_label: "Publié", fr_unchecked_label: "Brouillon" } }
Publier

.fr-fieldset__element
%fieldset.fr-fieldset{ "aria-labelledby": token_list(dom_id(release_note, "category_legend"), categories_errors_describedby_id), class: categories_fieldset_class, role: categories_error? ? "group" : nil }
%legend.fr-fieldset__legend.fr-fieldset__legend--regular{ id: dom_id(release_note, :category_legend) }
= ReleaseNote.human_attribute_name(:categories)
= render EditableChamp::AsteriskMandatoryComponent.new

- ReleaseNote::CATEGORIES.each do |category|
.fr-fieldset__element.fr-fieldset__element--inline
.fr-checkbox-group
= f.check_box :categories, { multiple: true, include_hidden: false, id: dom_id(release_note, "category_#{category}"), "aria-describedby" => "#{dom_id(release_note, "category_#{category}_messages")}" }, category, nil
%label.fr-label{ for: dom_id(release_note, "category_#{category}") }
= category.humanize

- if categories_error?
.fr-messages-group{ id: "checkboxes-error-messages", aria_live: "assertive" }
- if categories_full_messages_errors.one?
%p.fr-message.fr-message--error{ id: categories_errors_describedby_id }= categories_full_messages_errors.first
- else
.fr-error-text{ id: categories_errors_describedby_id }
%ul.list-style-type-none.fr-pl-0
- categories_full_messages_errors.map do |error_message|
%li= error_message


.fr-fieldset__element
.fr-input-group
= render Dsfr::InputComponent.new(form: f, attribute: :body, input_type: :rich_text_area)


.fr-fieldset__element
%ul.fr-btns-group.fr-btns-group--inline.fr-btns-group--icon-left
%li= f.button "Valider", class: "fr-btn fr-icon-check-line"

- if release_note.persisted?
%li= link_to t(".new"), new_super_admins_release_note_path(date: release_note.released_on), class: "fr-btn fr-btn--secondary fr-icon-add-line"

- if release_note.persisted?
%li
= link_to t('.delete'), super_admins_release_note_path(release_note),
class: "fr-btn fr-btn--secondary fr-icon-delete-line",
data: { method: :delete, confirm: "Supprimer cette note ?" }
45 changes: 45 additions & 0 deletions app/controllers/release_notes_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
class ReleaseNotesController < ApplicationController
before_action :ensure_access_allowed!

def index
@categories = params[:categories].presence || infer_default_categories

# Paginate per group of dates, then show all announces for theses dates
@paginated_groups = ReleaseNote.published
.for_categories(@categories)
.select(:released_on)
.group(:released_on)
.order(released_on: :desc)
.page(params[:page]).per(5)
Comment on lines +8 to +13
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@paginated_groups = ReleaseNote.published
.for_categories(@categories)
.select(:released_on)
.group(:released_on)
.order(released_on: :desc)
.page(params[:page]).per(5)
@paginated_release_dates = ReleaseNote.published
.for_categories(@categories)
.order(released_on: :desc)
.page(params[:page]).per(5)
.pluck(:released_on)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ce n'est pas équivalent: on a besoin d'une object paginé pour gérer la pagination avec les next_page etc… dans app/views/release_notes/_page.html.haml Ou alors tu avais autre chose en tête ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah oui bien vu. En fait mon point était de faire sauter le group(:released_on), j'ai l'impression qu'il n'est pas nécessaire.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, je groupe car je veux que toutes les annonces d'une même date soient affichées dans la même "page". (s'il y a 10 annonces le même jour, je veux qu'elles apparaissent en même temps)


@announces = ReleaseNote.where(released_on: @paginated_groups.map(&:released_on))
.with_rich_text_body
.for_categories(@categories)
.order(released_on: :desc, id: :asc)

render "scrollable_list" if params[:page].present?
end

private

def infer_default_categories
if administrateur_signed_in?
['administrateur', 'usager', current_administrateur.api_tokens.exists? ? 'api' : nil]
elsif instructeur_signed_in?
['instructeur', 'expert']
elsif expert_signed_in?
['expert']
else
['usager']
end
end

def ensure_access_allowed!
return if administrateur_signed_in?
return if instructeur_signed_in?
return if expert_signed_in?

flash[:alert] = t('release_notes.index.forbidden')
redirect_to root_path
end
end
62 changes: 62 additions & 0 deletions app/controllers/super_admins/release_notes_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
class SuperAdmins::ReleaseNotesController < ApplicationController
before_action :authenticate_super_admin!
before_action :set_note, only: [:edit, :update, :destroy]

def nav_bar_profile
:superadmin
end

def index
@release_notes = ReleaseNote
.order(released_on: :desc, id: :asc)
.with_rich_text_body
end

def show
# allows refreshing a submitted page in error
redirect_to edit_super_admins_release_note_path(params[:id])
end

def new
@release_note = ReleaseNote.new(released_on: params[:date].presence || Date.current, published: true)
end

def create
@release_note = ReleaseNote.new(release_note_params)
if @release_note.save
redirect_to edit_super_admins_release_note_path(@release_note), notice: t('.success')
else
flash.now[:alert] = [t('.error'), @release_note.errors.full_messages].flatten
render :new
end
end

def edit
@release_note = ReleaseNote.find(params[:id])
end

def update
if @release_note.update(release_note_params)
redirect_to edit_super_admins_release_note_path(@release_note), notice: t('.success')
else
flash.now[:alert] = [t('.error'), @release_note.errors.full_messages].flatten
render :edit
end
end

def destroy
@release_note.destroy!

redirect_to super_admins_release_notes_path, notice: t('.success')
end

private

def release_note_params
params.require(:release_note).permit(:released_on, :published, :body, categories: [])
end

def set_note
@release_note = ReleaseNote.find(params[:id])
end
end
18 changes: 18 additions & 0 deletions app/helpers/release_notes_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module ReleaseNotesHelper
def announce_category_badge(category)
color_class = case category.to_sym
when :administrateur
'fr-background-flat--blue-france fr-text-inverted--blue-france'
when :instructeur
'fr-background-contrast--yellow-tournesol'
when :expert
'fr-background-contrast--purple-glycine'
when :usager
'fr-background-contrast--green-emeraude'
when :api
'fr-background-contrast--blue-ecume'
end

content_tag(:span, ReleaseNote.human_attribute_name("categories.#{category}"), class: "fr-badge #{color_class}")
end
end
17 changes: 17 additions & 0 deletions app/models/release_note.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class ReleaseNote < ApplicationRecord
has_rich_text :body

CATEGORIES = [
'administrateur',
'instructeur',
'expert',
'usager',
'api'
]

validates :categories, presence: true, inclusion: { in: CATEGORIES }
validates :body, presence: true

scope :published, -> { where(published: true, released_on: ..Date.current) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super classe la combinaison des deux 😍

scope :for_categories, -> (categories) { where("categories && ARRAY[?]::varchar[]", categories) }
end
2 changes: 1 addition & 1 deletion app/views/layouts/_account_dropdown.haml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
%span.fr-icon-refresh-line.fr-icon--sm
= t('go_gestionnaire', scope: [:layouts])

- if super_admin_signed_in?
- if super_admin_signed_in? && nav_bar_profile != :superadmin
%li
= link_to manager_root_path, class: "fr-nav__link" do
%span.fr-icon-shield-line.fr-icon--sm
Expand Down
4 changes: 4 additions & 0 deletions app/views/layouts/_header.haml
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,8 @@
- if current_user.expert && current_expert.avis_summary[:total] > 0
= render partial: 'layouts/header/avis_tab', locals: { current_expert: current_expert }

- if content_for?(:navigation_principale)
.fr-container
= yield(:navigation_principale)

= yield(:notice_info)
3 changes: 2 additions & 1 deletion app/views/manager/application/_navigation.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ as defined by the routes in the `admin/` namespace
<hr />

<%= link_to "Delayed Jobs", manager_delayed_job_path, class: "navigation__link" %>
<%= link_to "Features", manager_flipper_path, class: "navigation__link" %>
<%= link_to "Maintenance Tasks", manager_maintenance_tasks_path, class: "navigation__link" %>
<%= link_to "Features", manager_flipper_path, class: "navigation__link" %>
<%= link_to "Annonces", super_admins_release_notes_path, class: "navigation__link" %>
<%= link_to "Import data via CSV", manager_import_procedure_tags_path, class: "navigation__link" %>
<% if Rails.application.secrets.sendinblue[:enabled] && ENV["SAML_IDP_ENABLED"] == "enabled" %>
<%= link_to "Sendinblue", ENV.fetch("SENDINBLUE_LOGIN_URL"), class: "navigation__link", target: '_blank' %>
Expand Down
10 changes: 10 additions & 0 deletions app/views/release_notes/_announce.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.fr-mb-4w
%h3= l(notes[0].released_on, format: :long)

- notes.each do |note|
.fr-mb-4w.fr-px-2w.fr-py-2w.fr-background-alt--grey
%p
- note.categories.each do |category|
= announce_category_badge(category)

= note.body
5 changes: 5 additions & 0 deletions app/views/release_notes/_page.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
= render partial: 'announce', collection: announces.group_by(&:released_on).values, as: :notes

- if !paginated_groups.last_page?
= turbo_frame_tag "announces-page-#{paginated_groups.next_page}", loading: :lazy, src: next_page_path(paginated_groups) do
= link_to t('.previous_page'), next_page_path(paginated_groups), class: "fr-btn fr-btn--secondary"
27 changes: 27 additions & 0 deletions app/views/release_notes/index.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.fr-container.fr-my-5w
%h2.fr-mb-5w= t('.title', app_name: APPLICATION_NAME)

.fr-grid-row.fr-grid-row--gutters{ data: { turbo: 'true' } }
.fr-col-md-3
= form_with(url: release_notes_path, method: :get, data: { turbo_frame: 'announces', controller: 'autosubmit' }, html: { role: 'search' }) do |f|
%fieldset.sidebar-filter
%legend
%ul
%li.fr-py-2w.fr-pl-2w
%fieldset.fr-fieldset{ "aria-labelledby": "sidebar_category_legend" }
%legend.fr-fieldset__legend{ id: "sidebar_category_legend" }
= ReleaseNote.human_attribute_name(:categories)

- ReleaseNote::CATEGORIES.each do |category|
.fr-fieldset__element
.fr-checkbox-group
= f.check_box :categories, { multiple: true, include_hidden: false, id: "filter_category_#{category}", checked: @categories.include?(category) }, category, nil
%label.fr-label{ for: "filter_category_#{category}" }
= ReleaseNote.human_attribute_name("categories.#{category}")

.fr-col-md-9
= turbo_frame_tag "announces", data: { turbo_action: :advance } do
- if @announces.any?
= render "page", announces: @announces, paginated_groups: @paginated_groups
- else
%p.fr-my-4w.text-center= t('.no_content')
2 changes: 2 additions & 0 deletions app/views/release_notes/scrollable_list.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
= turbo_frame_tag "announces-page-#{@paginated_groups.current_page}" do
= render 'page', announces: @announces, paginated_groups: @paginated_groups
17 changes: 17 additions & 0 deletions app/views/super_admins/release_notes/_main_navigation.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
- content_for(:navigation_principale) do
.fr-container
%nav.fr-nav#header-navigation{ role: "navigation", aria: { label: 'Menu principal annonces' } }
%ul.fr-nav__list
%li.fr-nav__item
= link_to "Toutes les annonces", super_admins_release_notes_path, class: "fr-nav__link", target: "_self", aria: { current: action == :index ? "page" : nil }

%li.fr-nav__item
= link_to("Nouvelle annonce", new_super_admins_release_note_path(date: @release_note&.released_on), class: "fr-nav__link", target: "_self", aria: { current: action == :new ? "page" : nil })

- if action == :edit
%li.fr-nav__item
= link_to "Annonce", '', class: "fr-nav__link", target: "_self", aria: { current: "page" }

%li.fr-nav__item
= link_to "Annonces publiées", release_notes_path, class: "fr-nav__link", target: "_self"

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
= turbo_stream.append 'release_notes_fieldset', render(ReleaseNote::NoteFormComponent.new(note: @release_note))
8 changes: 8 additions & 0 deletions app/views/super_admins/release_notes/edit.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
= render "main_navigation", action: :edit

.fr-container.fr-my-5w
.fr-grid-row.fr-grid-row--center
.fr-col-lg-10
%h1.fr-h2 Annonce
= render ReleaseNote::FormComponent.new(release_note: @release_note)

31 changes: 31 additions & 0 deletions app/views/super_admins/release_notes/index.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
= render "main_navigation", action: :index

.fr-container.fr-my-5w
.fr-grid-row.fr-grid-row--center
.fr-col-lg-10

%h1.fr-h2 Liste des annonces

-# haml-lint:disable ApplicationNameLinter
= link_to "Releases sur GitHub", "https://github.com/demarches-simplifiees/demarches-simplifiees.fr/releases", **external_link_attributes
-# haml-lint:enable ApplicationNameLinter

.fr-table
%table
%thead
%th Annoncé le
%th Publié ?
%th Notes
%th Actions
%tbody
- @release_notes.each do |note|
%tr
%td= l(note.released_on) if note.released_on
%td
- if note.published?
%span.fr-badge.fr-badge--success.fr-badge--no-icon Publié
- else
%span.fr-badge.fr-badge--warning.fr-badge--no-icon Brouillon
%td= note.body.to_plain_text.truncate_words(12)
%td
= link_to 'Modifier', edit_super_admins_release_note_path(note), class: 'fr-btn fr-btn--secondary'
7 changes: 7 additions & 0 deletions app/views/super_admins/release_notes/new.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
= render "main_navigation", action: :new

.fr-container.fr-my-5w
.fr-grid-row.fr-grid-row--center
.fr-col-lg-10
%h1.fr-h2 Nouvelle Annonce
= render ReleaseNote::FormComponent.new(release_note: @release_note)
Loading