feat(announces): anyone can read announces

This commit is contained in:
Colin Darie 2023-10-04 14:57:32 +02:00
parent ff8ed6016e
commit e4c37758d4
No known key found for this signature in database
GPG key ID: 8C76CADD40253590
11 changed files with 189 additions and 0 deletions

View 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

View 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

View file

@ -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

View 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

View 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"

View 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')

View file

@ -0,0 +1,2 @@
= turbo_frame_tag "announces-page-#{@paginated_groups.current_page}" do
= render 'page', announces: @announces, paginated_groups: @paginated_groups

View file

@ -1,5 +1,12 @@
---
en:
release_notes:
index:
title: Whats 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

View file

@ -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

View file

@ -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'

View 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