diff --git a/app/controllers/admin/administration/members_controller.rb b/app/controllers/admin/administration/members_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..fb2384cad42f738c5bbd370eacb4073d9b0e5246 --- /dev/null +++ b/app/controllers/admin/administration/members_controller.rb @@ -0,0 +1,63 @@ +class Admin::Administration::MembersController < Admin::Administration::ApplicationController + load_and_authorize_resource class: Administration::Member, + through: :current_university, + through_association: :members + + def index + @members = @members.ordered.page(params[:page]) + breadcrumb + end + + def show + breadcrumb + end + + def new + breadcrumb + end + + def edit + breadcrumb + add_breadcrumb t('edit') + end + + def create + if @member.save + redirect_to admin_administration_member_path(@member), notice: t('admin.successfully_created_html', model: @member.to_s) + else + breadcrumb + render :new, status: :unprocessable_entity + end + end + + def update + if @member.update(member_params) + redirect_to admin_administration_member_path(@member), notice: t('admin.successfully_updated_html', model: @member.to_s) + else + breadcrumb + add_breadcrumb t('edit') + render :edit, status: :unprocessable_entity + end + end + + def destroy + @member.destroy + redirect_to admin_administration_members_url, notice: t('admin.successfully_destroyed_html', model: @member.to_s) + end + + protected + + def breadcrumb + super + add_breadcrumb Administration::Member.model_name.human(count: 2), + admin_administration_members_path + breadcrumb_for @member + end + + def member_params + params.require(:administration_member) + .permit(:first_name, :last_name, :biography, :slug, :user_id, + :is_author, :is_researcher, :is_teacher, :is_administrative) + .merge(university_id: current_university.id) + end +end diff --git a/app/models/administration/member.rb b/app/models/administration/member.rb new file mode 100644 index 0000000000000000000000000000000000000000..aec03d4188d9f481dd8ce2273b33f84d027f1a33 --- /dev/null +++ b/app/models/administration/member.rb @@ -0,0 +1,42 @@ +# == Schema Information +# +# Table name: administration_members +# +# id :uuid not null, primary key +# first_name :string +# is_administrative :boolean +# is_author :boolean +# is_researcher :boolean +# is_teacher :boolean +# last_name :string +# slug :string +# created_at :datetime not null +# updated_at :datetime not null +# university_id :uuid not null +# user_id :uuid +# +# Indexes +# +# index_administration_members_on_university_id (university_id) +# index_administration_members_on_user_id (user_id) +# +# Foreign Keys +# +# fk_rails_... (university_id => universities.id) +# fk_rails_... (user_id => users.id) +# +class Administration::Member < ApplicationRecord + include WithSlug + + has_rich_text :biography + + belongs_to :university + belongs_to :user, optional: true + + scope :ordered, -> { order(:last_name, :first_name) } + + def to_s + "#{last_name} #{first_name}" + end + +end diff --git a/app/models/university.rb b/app/models/university.rb index 2b3ff4bce445dd94d1853707bb07c609e33369ea..6d027182e80b946e2467f4a7a898e272af64c566 100644 --- a/app/models/university.rb +++ b/app/models/university.rb @@ -17,6 +17,7 @@ # updated_at :datetime not null # class University < ApplicationRecord + include WithAdministration include WithCommunication include WithEducation include WithIdentifier diff --git a/app/models/university/with_administration.rb b/app/models/university/with_administration.rb new file mode 100644 index 0000000000000000000000000000000000000000..2db83f9804f833bfcf9b32da4359e0805fb1a017 --- /dev/null +++ b/app/models/university/with_administration.rb @@ -0,0 +1,7 @@ +module University::WithAdministration + extend ActiveSupport::Concern + + included do + has_many :members, class_name: 'Administration::Member', dependent: :destroy + end +end diff --git a/app/views/admin/administration/members/_form.html.erb b/app/views/admin/administration/members/_form.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..39f5ea34fc786a91b8aa29ec5c5761e3630c1542 --- /dev/null +++ b/app/views/admin/administration/members/_form.html.erb @@ -0,0 +1,54 @@ +<%= simple_form_for [:admin, member] do |f| %> + <div class="row"> + <div class="col-md-4"> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h5 class="card-title mb-0"><%= t('content') %></h5> + </div> + <div class="card-body"> + <div class="row"> + <div class="col-md-6"> + <%= f.input :first_name %> + </div> + <div class="col-md-6"> + <%= f.input :last_name %> + </div> + </div> + <%= f.input :biography, as: :rich_text_area %> + </div> + </div> + </div> + <div class="col-md-4"> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h5 class="card-title mb-0"><%= Administration::Member.human_attribute_name('abilities') %></h5> + </div> + <div class="card-body"> + <%= f.input :is_author %> + <%= f.input :is_teacher %> + <%= f.input :is_researcher %> + <%= f.input :is_administrative %> + </div> + </div> + </div> + <div class="col-md-4"> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h5 class="card-title mb-0"><%= t('metadata') %></h5> + </div> + <div class="card-body"> + <%= f.input :slug, + as: :string, + input_html: member.persisted? ? {} : { + class: 'js-slug-input', + data: { source: '#administration_member_first_name, #administration_member_last_name' } + } %> + <%= f.association :user, collection: current_university.users.ordered %> + </div> + </div> + </div> + </div> + <% content_for :action_bar_right do %> + <%= submit f %> + <% end %> +<% end %> diff --git a/app/views/admin/administration/members/_list.html.erb b/app/views/admin/administration/members/_list.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..f1cdd3ffb33e745505bfa1c5430bbbbde06d5f39 --- /dev/null +++ b/app/views/admin/administration/members/_list.html.erb @@ -0,0 +1,27 @@ +<table class="<%= table_classes %>"> + <thead> + <tr> + <th><%= Administration::Member.human_attribute_name('name') %></th> + <th></th> + </tr> + </thead> + <tbody> + <% members.each do |member| %> + <tr> + <td><%= link_to member, admin_administration_member_path(member) %></td> + <td class="text-end"> + <div class="btn-group" role="group"> + <%= link_to t('edit'), + edit_admin_administration_member_path(member), + class: button_classes %> + <%= link_to t('delete'), + admin_administration_member_path(member), + method: :delete, + data: { confirm: t('please-confirm') }, + class: button_classes_danger %> + </div> + </td> + </tr> + <% end %> + </tbody> +</table> diff --git a/app/views/admin/administration/members/edit.html.erb b/app/views/admin/administration/members/edit.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..8a3aebfee7a3a619535f13aeb210ad22646b6864 --- /dev/null +++ b/app/views/admin/administration/members/edit.html.erb @@ -0,0 +1,3 @@ +<% content_for :title, @member %> + +<%= render 'form', member: @member %> diff --git a/app/views/admin/administration/members/index.html.erb b/app/views/admin/administration/members/index.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..0392345040995193022de9b89a9d9acbd2699da8 --- /dev/null +++ b/app/views/admin/administration/members/index.html.erb @@ -0,0 +1,9 @@ +<% content_for :title, "#{Administration::Member.model_name.human(count: 2)} (#{@members.total_count})" %> + +<%= render 'admin/administration/members/list', members: @members %> +<%= paginate @members, theme: 'bootstrap-5' %> + + +<% content_for :action_bar_right do %> + <%= create_link Administration::Member %> +<% end %> diff --git a/app/views/admin/administration/members/jekyll.html.erb b/app/views/admin/administration/members/jekyll.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..2f03cecedaa4aa58b5c13a7e3775587905b87180 --- /dev/null +++ b/app/views/admin/administration/members/jekyll.html.erb @@ -0,0 +1,15 @@ +--- +title: "<%= @teacher.to_s %>" +identifier: "<%= @teacher.id %>" +first_name: "<%= @teacher.first_name %>" +last_name: "<%= @teacher.last_name %>" +slug: "<%= @teacher.slug %>" +<% if @teacher.programs.any? %> +programs: + <% @teacher.programs.each do |program| %> + - "<%= program.id %>" + <% end %> +<% end %> +biography: > + <%= prepare_for_github @teacher.biography, @teacher.university %> +--- diff --git a/app/views/admin/administration/members/new.html.erb b/app/views/admin/administration/members/new.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..47b25fa3e3056227cb9970d1284cd33ca8e2b4c9 --- /dev/null +++ b/app/views/admin/administration/members/new.html.erb @@ -0,0 +1,3 @@ +<% content_for :title, Administration::Member.model_name.human %> + +<%= render 'form', member: @member %> diff --git a/app/views/admin/administration/members/show.html.erb b/app/views/admin/administration/members/show.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..85793fc7f31395b1d53fc56a6189bdcf725999f0 --- /dev/null +++ b/app/views/admin/administration/members/show.html.erb @@ -0,0 +1,28 @@ +<% content_for :title, @member %> + +<div class="row"> + + <div class="col-md-8"> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h2 class="card-title mb-0 h5"><%= t('metadata') %></h2> + </div> + <div class="card-body"> + <h3 class="h5"><%= Administration::Member.human_attribute_name('biography') %></h3> + <p><%= @member.biography %></p> + <h3 class="h5"><%= Administration::Member.human_attribute_name('slug') %></h3> + <p><%= @member.slug %></p> + <% if @member.user %> + <h3 class="h5"><%= Administration::Member.human_attribute_name('user') %></h3> + <p><%= link_to_if can?(:read, @member.user), @member.user, admin_user_path(@member.user) %></p> + <% end %> + </div> + </div> + </div> + +</div> + + +<% content_for :action_bar_right do %> + <%= edit_link @member %> +<% end %> diff --git a/config/admin_navigation.rb b/config/admin_navigation.rb index aee969e3afdd3421e985cdf02e29f34f4b75f017..4ff4e4eb8051d8a3c2da4d346e17c799fe1201be 100644 --- a/config/admin_navigation.rb +++ b/config/admin_navigation.rb @@ -32,7 +32,7 @@ SimpleNavigation::Configuration.run do |navigation| if can?(:read, User) || can?(:read, Administration::Qualiopi::Criterion) primary.item :administration, 'Administration', nil, { kind: :header } - primary.item :administration, 'Équipe administrative', nil, { icon: 'users-cog' } + primary.item :administration, Administration::Member.model_name.human(count: 2), admin_administration_members_path, { icon: 'users-cog' } primary.item :administration, 'Campus', nil, { icon: 'map-marker-alt' } primary.item :administration, 'Admissions', nil, { icon: 'door-open' } primary.item :administration, 'Statistiques', nil, { icon: 'cog' } diff --git a/config/locales/administration/en.yml b/config/locales/administration/en.yml index ee9d57f1e169bd4891f7d13a738f1ff57ac26da9..05c6ad9c7cdf6ab6b30aaf16986166c8b48663ff 100644 --- a/config/locales/administration/en.yml +++ b/config/locales/administration/en.yml @@ -10,7 +10,22 @@ en: administration/qualiopi/indicator: one: Indicator other: Indicators + administration/member: + one: Staff + other: Staff attributes: + administration/member: + abilities: Abilities + biography: Biography + first_name: First name + is_administrative: Administrative staff + is_author: Author + is_researcher: Researcher + is_teacher: Teacher + last_name: Last name + name: Name + slug: Slug + user: User administration/qualiopi/criterion: number: Number name: Name diff --git a/config/locales/administration/fr.yml b/config/locales/administration/fr.yml index e9d4fa0f992598683c0c90b3147be503e6d99c4a..e02744d33529abd46506d988026551faf16bc944 100644 --- a/config/locales/administration/fr.yml +++ b/config/locales/administration/fr.yml @@ -10,7 +10,22 @@ fr: administration/qualiopi/indicator: one: Indicateur other: Indicateurs + administration/member: + one: Personnel + other: Personnel attributes: + administration/member: + abilities: Responsabilités + biography: Biographie + first_name: Prénom + is_administrative: Personnel administratif + is_author: Auteur·rice + is_researcher: Chercheur·se + is_teacher: Enseignant·e + last_name: Nom de famille + name: Nom + slug: Slug + user: Utilisateur administration/qualiopi/criterion: number: Numéro name: Nom diff --git a/config/routes/admin/administration.rb b/config/routes/admin/administration.rb index f5b69fe50d8ccc61e2d3a2873a87271df524af51..50ef7b6cc97207bd507a97b53041d6ab20bd24c0 100644 --- a/config/routes/admin/administration.rb +++ b/config/routes/admin/administration.rb @@ -3,4 +3,6 @@ namespace :administration do resources :criterions, only: [:index, :show] resources :indicators, only: [:index, :show] end + + resources :members end diff --git a/db/migrate/20211214101323_create_administration_member.rb b/db/migrate/20211214101323_create_administration_member.rb new file mode 100644 index 0000000000000000000000000000000000000000..568369e6c56db31ca72fb58dd230191ad3890a45 --- /dev/null +++ b/db/migrate/20211214101323_create_administration_member.rb @@ -0,0 +1,16 @@ +class CreateAdministrationMember < ActiveRecord::Migration[6.1] + def change + create_table :administration_members, id: :uuid do |t| + t.references :university, null: false, foreign_key: true, type: :uuid + t.references :user, foreign_key: true, type: :uuid + t.string :last_name + t.string :first_name + t.string :slug + t.boolean :is_author + t.boolean :is_researcher + t.boolean :is_teacher + t.boolean :is_administrative + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 5dd2fbb7035f10ea08955f7ede116f8f1dda513a..73cdaade806fd993625235120030d34e259d60bc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_12_13_140240) do +ActiveRecord::Schema.define(version: 2021_12_14_101323) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" @@ -56,6 +56,22 @@ ActiveRecord::Schema.define(version: 2021_12_13_140240) do t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end + create_table "administration_members", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "university_id", null: false + t.uuid "user_id" + t.string "last_name" + t.string "first_name" + t.string "slug" + t.boolean "is_author" + t.boolean "is_researcher" + t.boolean "is_teacher" + t.boolean "is_administrative" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["university_id"], name: "index_administration_members_on_university_id" + t.index ["user_id"], name: "index_administration_members_on_user_id" + end + create_table "administration_qualiopi_criterions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.integer "number" t.text "name" @@ -547,6 +563,8 @@ ActiveRecord::Schema.define(version: 2021_12_13_140240) do add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" + add_foreign_key "administration_members", "universities" + add_foreign_key "administration_members", "users" add_foreign_key "administration_qualiopi_indicators", "administration_qualiopi_criterions", column: "criterion_id" add_foreign_key "communication_website_authors", "communication_websites" add_foreign_key "communication_website_authors", "universities"