feat(announces): anyone can read announces
This commit is contained in:
parent
ff8ed6016e
commit
e4c37758d4
11 changed files with 189 additions and 0 deletions
45
app/controllers/release_notes_controller.rb
Normal file
45
app/controllers/release_notes_controller.rb
Normal file
|
@ -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)
|
||||
|
||||
@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
|
18
app/helpers/release_notes_helper.rb
Normal file
18
app/helpers/release_notes_helper.rb
Normal file
|
@ -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
|
|
@ -11,4 +11,7 @@ class ReleaseNote < ApplicationRecord
|
|||
|
||||
validates :categories, presence: true, inclusion: { in: CATEGORIES }
|
||||
validates :body, presence: true
|
||||
|
||||
scope :published, -> { where(published: true, released_on: ..Date.current) }
|
||||
scope :for_categories, -> (categories) { where("categories && ARRAY[?]::varchar[]", categories) }
|
||||
end
|
||||
|
|
10
app/views/release_notes/_announce.html.haml
Normal file
10
app/views/release_notes/_announce.html.haml
Normal file
|
@ -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
app/views/release_notes/_page.html.haml
Normal file
5
app/views/release_notes/_page.html.haml
Normal file
|
@ -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
app/views/release_notes/index.html.haml
Normal file
27
app/views/release_notes/index.html.haml
Normal file
|
@ -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
app/views/release_notes/scrollable_list.html.haml
Normal file
2
app/views/release_notes/scrollable_list.html.haml
Normal file
|
@ -0,0 +1,2 @@
|
|||
= turbo_frame_tag "announces-page-#{@paginated_groups.current_page}" do
|
||||
= render 'page', announces: @announces, paginated_groups: @paginated_groups
|
|
@ -1,5 +1,12 @@
|
|||
---
|
||||
en:
|
||||
release_notes:
|
||||
index:
|
||||
title: What’s new on %{app_name} ? 🚀
|
||||
forbidden: You are not authorized to view the News page.
|
||||
no_content: No announcement here.
|
||||
page:
|
||||
previous_page: Previous announcements
|
||||
super_admins:
|
||||
release_notes:
|
||||
create: &save
|
||||
|
@ -13,4 +20,10 @@ en:
|
|||
body: Announce
|
||||
categories: Categories
|
||||
released_on: Publication date
|
||||
release_note/categories:
|
||||
administrateur: Administrator
|
||||
instructeur: Instructor
|
||||
expert: Expert
|
||||
api: API
|
||||
usager: User
|
||||
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
---
|
||||
fr:
|
||||
release_notes:
|
||||
index:
|
||||
title: Quoi de neuf sur %{app_name} ? 🚀
|
||||
forbidden: Vous n’êtes pas autorisé(e) à consulter la page des Nouveautés.
|
||||
no_content: Aucune nouveauté annoncée de ce côté là.
|
||||
page:
|
||||
previous_page: Annonces précédentes
|
||||
super_admins:
|
||||
release_notes:
|
||||
create: &save
|
||||
|
@ -13,4 +20,10 @@ fr:
|
|||
body: Annonce
|
||||
categories: Catégories
|
||||
released_on: Date de publication
|
||||
release_note/categories:
|
||||
administrateur: Administrateur
|
||||
instructeur: Instructeur
|
||||
expert: Expert
|
||||
api: API
|
||||
usager: Usager
|
||||
|
||||
|
|
|
@ -634,6 +634,8 @@ Rails.application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
resources :release_notes, only: [:index]
|
||||
|
||||
if Rails.env.test?
|
||||
scope 'test/api_geo' do
|
||||
get 'regions' => 'api_geo_test#regions'
|
||||
|
|
51
spec/controllers/release_notes_controller_spec.rb
Normal file
51
spec/controllers/release_notes_controller_spec.rb
Normal file
|
@ -0,0 +1,51 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ReleaseNotesController, type: :controller do
|
||||
let!(:note_admin) { create(:release_note, categories: ['administrateur'], body: "Pour l'admin", released_on: Date.new(2023, 10, 15)) }
|
||||
let!(:note_instructeur) { create(:release_note, categories: ['instructeur'], body: "Pour l'instructeur", released_on: Date.new(2023, 10, 13)) }
|
||||
|
||||
let(:user) { nil }
|
||||
let(:admin) { create(:user, administrateur: build(:administrateur)) }
|
||||
let(:instructeur) { create(:user, instructeur: build(:instructeur)) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:current_user).and_return(user)
|
||||
end
|
||||
|
||||
describe 'GET index' do
|
||||
subject { get :index }
|
||||
|
||||
describe 'filtering' do
|
||||
before { subject }
|
||||
context 'user is admininistrateur' do
|
||||
let(:user) { admin }
|
||||
it { is_expected.to have_http_status(:ok) }
|
||||
it { expect(assigns(:announces)).to eq([note_admin]) }
|
||||
end
|
||||
|
||||
context 'user is instructeur' do
|
||||
let(:user) { instructeur }
|
||||
it { is_expected.to have_http_status(:ok) }
|
||||
it { expect(assigns(:announces)).to eq([note_instructeur]) }
|
||||
end
|
||||
|
||||
context 'user is expert' do
|
||||
let(:user) { create(:user, expert: build(:expert)) }
|
||||
it { expect(assigns(:announces)).to eq([]) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'acl' do
|
||||
before { subject }
|
||||
context 'user is normal' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it { is_expected.to be_redirection }
|
||||
end
|
||||
|
||||
context 'no user' do
|
||||
it { is_expected.to be_redirection }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue