feat(announce): super admin can create announce
This commit is contained in:
parent
0d626f1811
commit
ff8ed6016e
12 changed files with 234 additions and 2 deletions
52
app/controllers/super_admins/release_notes_controller.rb
Normal file
52
app/controllers/super_admins/release_notes_controller.rb
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
class SuperAdmins::ReleaseNotesController < ApplicationController
|
||||||
|
before_action :authenticate_super_admin!
|
||||||
|
before_action :set_note, only: [:edit, :update]
|
||||||
|
|
||||||
|
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: Date.current)
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
|
@ -1,2 +1,14 @@
|
||||||
class ReleaseNote < ApplicationRecord
|
class ReleaseNote < ApplicationRecord
|
||||||
|
has_rich_text :body
|
||||||
|
|
||||||
|
CATEGORIES = [
|
||||||
|
'administrateur',
|
||||||
|
'instructeur',
|
||||||
|
'expert',
|
||||||
|
'usager',
|
||||||
|
'api'
|
||||||
|
]
|
||||||
|
|
||||||
|
validates :categories, presence: true, inclusion: { in: CATEGORIES }
|
||||||
|
validates :body, presence: true
|
||||||
end
|
end
|
||||||
|
|
30
app/views/super_admins/release_notes/_form.html.haml
Normal file
30
app/views/super_admins/release_notes/_form.html.haml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
= 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)
|
||||||
|
|
||||||
|
.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": dom_id(release_note, :category_legend) }
|
||||||
|
%legend.fr-fieldset__legend.fr-fieldset__legend--regular{ id: dom_id(release_note, :category_legend) }
|
||||||
|
Catégories
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|
||||||
|
.fr-fieldset__element
|
||||||
|
.fr-input-group
|
||||||
|
= render Dsfr::InputComponent.new(form: f, attribute: :body, input_type: :rich_text_area)
|
||||||
|
|
||||||
|
|
||||||
|
.fr-fieldset__element
|
||||||
|
= f.submit "Valider", class: "fr-btn fr-btn--lg"
|
6
app/views/super_admins/release_notes/edit.html.haml
Normal file
6
app/views/super_admins/release_notes/edit.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
.fr-container.fr-my-5w
|
||||||
|
.fr-grid-row.fr-grid-row--center
|
||||||
|
.fr-col-lg-10
|
||||||
|
%h1.fr-h2 Annonce
|
||||||
|
= render partial: 'form', object: @release_note, as: :release_note
|
||||||
|
|
24
app/views/super_admins/release_notes/index.html.haml
Normal file
24
app/views/super_admins/release_notes/index.html.haml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
.fr-container.fr-my-5w
|
||||||
|
.fr-grid-row.fr-grid-row--center
|
||||||
|
.fr-col-lg-10
|
||||||
|
%h1.fr-h2 Liste des annonces
|
||||||
|
|
||||||
|
= link_to("Créer une annonce", new_super_admins_release_note_path, class: "fr-btn")
|
||||||
|
|
||||||
|
%table.fr-table
|
||||||
|
%thead
|
||||||
|
%th Annoncé le
|
||||||
|
%th Publié?
|
||||||
|
%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
|
||||||
|
= link_to 'Modifier', edit_super_admins_release_note_path(note), class: 'fr-btn fr-btn--secondary'
|
||||||
|
|
5
app/views/super_admins/release_notes/new.html.haml
Normal file
5
app/views/super_admins/release_notes/new.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.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)
|
16
config/locales/release_notes.en.yml
Normal file
16
config/locales/release_notes.en.yml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
en:
|
||||||
|
super_admins:
|
||||||
|
release_notes:
|
||||||
|
create: &save
|
||||||
|
success: Release note was successfully saved.
|
||||||
|
error: Release note was not saved.
|
||||||
|
update:
|
||||||
|
<<: *save
|
||||||
|
activerecord:
|
||||||
|
attributes:
|
||||||
|
release_note:
|
||||||
|
body: Announce
|
||||||
|
categories: Categories
|
||||||
|
released_on: Publication date
|
||||||
|
|
16
config/locales/release_notes.fr.yml
Normal file
16
config/locales/release_notes.fr.yml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
fr:
|
||||||
|
super_admins:
|
||||||
|
release_notes:
|
||||||
|
create: &save
|
||||||
|
success: L’annonce a été sauvegardée.
|
||||||
|
error: L’annonce n’a pas pu être sauvegardée.
|
||||||
|
update:
|
||||||
|
<<: *save
|
||||||
|
activerecord:
|
||||||
|
attributes:
|
||||||
|
release_note:
|
||||||
|
body: Annonce
|
||||||
|
categories: Catégories
|
||||||
|
released_on: Date de publication
|
||||||
|
|
|
@ -125,6 +125,10 @@ Rails.application.routes.draw do
|
||||||
passwords: 'super_admins/passwords'
|
passwords: 'super_admins/passwords'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace :super_admins do
|
||||||
|
resources :release_notes, only: [:index, :new, :create, :edit, :update, :show]
|
||||||
|
end
|
||||||
|
|
||||||
get 'super_admins/edit_otp', to: 'super_admins#edit_otp', as: 'edit_super_admin_otp'
|
get 'super_admins/edit_otp', to: 'super_admins#edit_otp', as: 'edit_super_admin_otp'
|
||||||
put 'super_admins/enable_otp', to: 'super_admins#enable_otp', as: 'enable_super_admin_otp'
|
put 'super_admins/enable_otp', to: 'super_admins#enable_otp', as: 'enable_super_admin_otp'
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ class CreateReleaseNotes < ActiveRecord::Migration[7.0]
|
||||||
def change
|
def change
|
||||||
create_table :release_notes do |t|
|
create_table :release_notes do |t|
|
||||||
t.date :released_on
|
t.date :released_on
|
||||||
t.text :body, default: nil
|
|
||||||
t.boolean :published, default: false, null: false
|
t.boolean :published, default: false, null: false
|
||||||
t.string :categories, array: true, default: []
|
t.string :categories, array: true, default: []
|
||||||
|
|
||||||
|
|
|
@ -897,7 +897,6 @@ ActiveRecord::Schema[7.0].define(version: 2023_10_26_161609) do
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "release_notes", force: :cascade do |t|
|
create_table "release_notes", force: :cascade do |t|
|
||||||
t.text "body"
|
|
||||||
t.string "categories", default: [], array: true
|
t.string "categories", default: [], array: true
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.boolean "published", default: false, null: false
|
t.boolean "published", default: false, null: false
|
||||||
|
@ -905,6 +904,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_10_26_161609) do
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.index ["categories"], name: "index_release_notes_on_categories", using: :gin
|
t.index ["categories"], name: "index_release_notes_on_categories", using: :gin
|
||||||
t.index ["published"], name: "index_release_notes_on_published"
|
t.index ["published"], name: "index_release_notes_on_published"
|
||||||
|
t.index ["released_on"], name: "index_release_notes_on_released_on"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "safe_mailers", force: :cascade do |t|
|
create_table "safe_mailers", force: :cascade do |t|
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe SuperAdmins::ReleaseNotesController, type: :controller do
|
||||||
|
let(:super_admin) { create(:super_admin) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in super_admin if super_admin.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "acl" do
|
||||||
|
context 'when user is not signed as super admin' do
|
||||||
|
let(:super_admin) { nil }
|
||||||
|
let!(:release_note) { create(:release_note, published: false) }
|
||||||
|
|
||||||
|
it 'is not allowed to post' do
|
||||||
|
expect { post :create, params: { release_note: { released_on: Date.current, published: "0", body: "bam" } } }.not_to change(ReleaseNote, :count)
|
||||||
|
expect(response.status).to eq(302)
|
||||||
|
expect(flash[:alert]).to be_present
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is not allowed to put' do
|
||||||
|
expect {
|
||||||
|
put :update, params: {
|
||||||
|
id: release_note.id,
|
||||||
|
release_note: {
|
||||||
|
released_on: Date.current,
|
||||||
|
published: "1",
|
||||||
|
categories: release_note.categories,
|
||||||
|
body: "hacked body"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.not_to change { release_note.reload.body }
|
||||||
|
expect(response.status).to eq(302)
|
||||||
|
expect(flash[:alert]).to be_present
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is not allowed to index' do
|
||||||
|
get :index
|
||||||
|
expect(response.status).to eq(302)
|
||||||
|
expect(flash[:alert]).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is signed as super admin' do
|
||||||
|
it 'is allowed to post' do
|
||||||
|
expect { post :create, params: { release_note: { categories: ['api'], released_on: Date.current, published: "0", body: "bam" } } }.to change(ReleaseNote, :count).by(1)
|
||||||
|
expect(flash[:notice]).to be_present
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is allowed to put' do
|
||||||
|
release_note = create(:release_note, published: false)
|
||||||
|
put :update, params: {
|
||||||
|
id: release_note.id,
|
||||||
|
release_note: {
|
||||||
|
released_on: Date.current,
|
||||||
|
published: "1",
|
||||||
|
categories: release_note.categories,
|
||||||
|
body: "new body"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
release_note.reload
|
||||||
|
expect(release_note.body.to_plain_text).to eq("new body")
|
||||||
|
expect(release_note.published).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue