From f341f9759af2d3b46c1dfef5f83df343282c5af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= <sebastien.gaya@gmail.com> Date: Mon, 20 Dec 2021 12:17:47 +0100 Subject: [PATCH] nested form for education program members --- Gemfile | 1 + Gemfile.lock | 2 + app/assets/javascripts/admin.js | 1 + .../administration/members_controller.rb | 2 +- .../website/authors_controller.rb | 4 +- .../admin/education/programs_controller.rb | 3 +- .../admin/education/teachers_controller.rb | 4 +- .../admin/research/researchers_controller.rb | 4 +- app/models/education/program.rb | 6 +++ app/models/education/program/member.rb | 25 +++++++++++ app/models/university/with_administration.rb | 2 +- .../website/posts/_form.html.erb | 2 +- .../admin/education/programs/_form.html.erb | 41 +++++++++++++++++-- .../research/journal/articles/_form.html.erb | 2 +- config/locales/education/en.yml | 2 + config/locales/education/fr.yml | 2 + ...085352_create_education_program_members.rb | 11 +++++ db/schema.rb | 14 ++++++- test/fixtures/education/program/members.yml | 32 +++++++++++++++ test/models/education/program/member_test.rb | 28 +++++++++++++ 20 files changed, 172 insertions(+), 16 deletions(-) create mode 100644 app/models/education/program/member.rb create mode 100644 db/migrate/20211220085352_create_education_program_members.rb create mode 100644 test/fixtures/education/program/members.yml create mode 100644 test/models/education/program/member_test.rb diff --git a/Gemfile b/Gemfile index ea196db37..13a352d2e 100644 --- a/Gemfile +++ b/Gemfile @@ -37,6 +37,7 @@ gem 'front_matter_parser' gem 'two_factor_authentication', git: 'https://github.com/noesya/two_factor_authentication.git' # gem 'two_factor_authentication', path: '../two_factor_authentication' gem 'curation'#, path: '../../arnaudlevy/curation' +gem 'nested_form' # Front gem 'jquery-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 460669c3d..42f72deee 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -263,6 +263,7 @@ GEM multipart-post (2.1.1) mustermann (1.1.1) ruby2_keywords (~> 0.0.1) + nested_form (0.3.2) nesty (1.0.2) nio4r (2.5.8) nokogiri (1.12.5) @@ -437,6 +438,7 @@ DEPENDENCIES kaminari listen (~> 3.3) mini_magick + nested_form octokit pg (~> 1.1) puma diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js index 7d66de99b..8d5f8c633 100644 --- a/app/assets/javascripts/admin.js +++ b/app/assets/javascripts/admin.js @@ -12,6 +12,7 @@ //= require trix //= require sortablejs/Sortable //= require slug/slug +//= require jquery_nested_form //= require_self //= require_tree ./admin/commons //= require_tree ./admin/plugins diff --git a/app/controllers/admin/administration/members_controller.rb b/app/controllers/admin/administration/members_controller.rb index b683ef4b2..d17fe8e7f 100644 --- a/app/controllers/admin/administration/members_controller.rb +++ b/app/controllers/admin/administration/members_controller.rb @@ -1,7 +1,7 @@ class Admin::Administration::MembersController < Admin::Administration::ApplicationController load_and_authorize_resource class: Administration::Member, through: :current_university, - through_association: :members + through_association: :administration_members def index @members = @members.ordered.page(params[:page]) diff --git a/app/controllers/admin/communication/website/authors_controller.rb b/app/controllers/admin/communication/website/authors_controller.rb index 83c09f2d0..bc2418e82 100644 --- a/app/controllers/admin/communication/website/authors_controller.rb +++ b/app/controllers/admin/communication/website/authors_controller.rb @@ -1,12 +1,12 @@ class Admin::Communication::Website::AuthorsController < Admin::Communication::Website::ApplicationController def index - @authors = current_university.members.authors.accessible_by(current_ability).ordered.page(params[:page]) + @authors = current_university.administration_members.authors.accessible_by(current_ability).ordered.page(params[:page]) breadcrumb end def show - @author = current_university.members.authors.accessible_by(current_ability).find(params[:id]) + @author = current_university.administration_members.authors.accessible_by(current_ability).find(params[:id]) @posts = @author.communication_website_posts.ordered.page(params[:page]) breadcrumb end diff --git a/app/controllers/admin/education/programs_controller.rb b/app/controllers/admin/education/programs_controller.rb index d928c482a..36c0b863a 100644 --- a/app/controllers/admin/education/programs_controller.rb +++ b/app/controllers/admin/education/programs_controller.rb @@ -83,7 +83,8 @@ class Admin::Education::ProgramsController < Admin::Education::ApplicationContro :featured_image, :featured_image_delete, :featured_image_infos, :prerequisites, :objectives, :duration, :registration, :pedagogy, :evaluation, :accessibility, :pricing, :contacts, :opportunities, :other, - :parent_id, school_ids: [], teacher_ids: [] + :parent_id, school_ids: [], teacher_ids: [], + members_attributes: [:id, :role, :member_id, :_destroy] ) end end diff --git a/app/controllers/admin/education/teachers_controller.rb b/app/controllers/admin/education/teachers_controller.rb index aac641dce..34f774cd4 100644 --- a/app/controllers/admin/education/teachers_controller.rb +++ b/app/controllers/admin/education/teachers_controller.rb @@ -2,7 +2,7 @@ class Admin::Education::TeachersController < Admin::Education::ApplicationContro before_action :get_teacher, except: :index def index - @teachers = current_university.members.teachers.accessible_by(current_ability).ordered.page(params[:page]) + @teachers = current_university.administration_members.teachers.accessible_by(current_ability).ordered.page(params[:page]) breadcrumb end @@ -29,7 +29,7 @@ class Admin::Education::TeachersController < Admin::Education::ApplicationContro protected def get_teacher - @teacher = current_university.members.teachers.accessible_by(current_ability).find(params[:id]) + @teacher = current_university.administration_members.teachers.accessible_by(current_ability).find(params[:id]) end def breadcrumb diff --git a/app/controllers/admin/research/researchers_controller.rb b/app/controllers/admin/research/researchers_controller.rb index 9f51dadd4..e6a11401c 100644 --- a/app/controllers/admin/research/researchers_controller.rb +++ b/app/controllers/admin/research/researchers_controller.rb @@ -1,12 +1,12 @@ class Admin::Research::ResearchersController < Admin::Research::ApplicationController def index - @researchers = current_university.members.researchers.accessible_by(current_ability).ordered.page(params[:page]) + @researchers = current_university.administration_members.researchers.accessible_by(current_ability).ordered.page(params[:page]) breadcrumb end def show - @researcher = current_university.members.authors.accessible_by(current_ability).find(params[:id]) + @researcher = current_university.administration_members.authors.accessible_by(current_ability).find(params[:id]) @articles = @researcher.research_journal_articles.ordered.page(params[:page]) breadcrumb end diff --git a/app/models/education/program.rb b/app/models/education/program.rb index 6ad5acac4..207a259a2 100644 --- a/app/models/education/program.rb +++ b/app/models/education/program.rb @@ -47,6 +47,10 @@ class Education::Program < ApplicationRecord class_name: 'Education::Program', foreign_key: :parent_id, dependent: :destroy + has_many :members, + class_name: 'Education::Program::Member', + dependent: :destroy, + inverse_of: :program has_and_belongs_to_many :schools, class_name: 'Education::School', join_table: 'education_programs_schools', @@ -59,6 +63,8 @@ class Education::Program < ApplicationRecord association_foreign_key: 'education_teacher_id' has_many :websites, -> { distinct }, through: :schools + accepts_nested_attributes_for :members, allow_destroy: true + enum level: { first_year: 100, second_year: 200, diff --git a/app/models/education/program/member.rb b/app/models/education/program/member.rb new file mode 100644 index 000000000..c0c64f8ea --- /dev/null +++ b/app/models/education/program/member.rb @@ -0,0 +1,25 @@ +# == Schema Information +# +# Table name: education_program_members +# +# id :uuid not null, primary key +# role :string +# created_at :datetime not null +# updated_at :datetime not null +# member_id :uuid not null +# program_id :uuid not null +# +# Indexes +# +# index_education_program_members_on_member_id (member_id) +# index_education_program_members_on_program_id (program_id) +# +# Foreign Keys +# +# fk_rails_... (member_id => administration_members.id) +# fk_rails_... (program_id => education_programs.id) +# +class Education::Program::Member < ApplicationRecord + belongs_to :program, class_name: 'Education::Program', inverse_of: :members + belongs_to :member, class_name: 'Administration::Member' +end diff --git a/app/models/university/with_administration.rb b/app/models/university/with_administration.rb index 2db83f980..313e80472 100644 --- a/app/models/university/with_administration.rb +++ b/app/models/university/with_administration.rb @@ -2,6 +2,6 @@ module University::WithAdministration extend ActiveSupport::Concern included do - has_many :members, class_name: 'Administration::Member', dependent: :destroy + has_many :administration_members, class_name: 'Administration::Member', dependent: :destroy end end diff --git a/app/views/admin/communication/website/posts/_form.html.erb b/app/views/admin/communication/website/posts/_form.html.erb index 9b7fddc98..057fb390d 100644 --- a/app/views/admin/communication/website/posts/_form.html.erb +++ b/app/views/admin/communication/website/posts/_form.html.erb @@ -27,7 +27,7 @@ <%= f.input :published %> <%= f.input :published_at, html5: true %> <%= f.input :pinned %> - <%= f.association :author, collection: current_university.members.authors.ordered %> + <%= f.association :author, collection: current_university.administration_members.authors.ordered %> <%= f.association :categories, as: :check_boxes, collection: @website.list_of_categories.map { |category| [ diff --git a/app/views/admin/education/programs/_form.html.erb b/app/views/admin/education/programs/_form.html.erb index 274caa93f..53d220d17 100644 --- a/app/views/admin/education/programs/_form.html.erb +++ b/app/views/admin/education/programs/_form.html.erb @@ -1,6 +1,6 @@ -<%= simple_form_for [:admin, program] do |f| %> +<%= simple_nested_form_for [:admin, program] do |f| %> <div class="row"> - <div class="col-md-4"> + <div class="col-md-3"> <div class="card flex-fill w-100"> <div class="card-header"> <h5 class="card-title mb-0"><%= t('education.program.main_informations') %></h5> @@ -39,7 +39,7 @@ </div> </div> </div> - <div class="col-md-8"> + <div class="col-md-4"> <div class="card flex-fill w-100"> <div class="card-header"> <h5 class="card-title mb-0"><%= t('education.program.useful_informations') %></h5> @@ -55,6 +55,39 @@ </div> </div> </div> + <div class="col-md-5"> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h5 class="card-title mb-0">Members</h5> + </div> + <div class="card-body"> + <div id="js-program-members"> + <%= f.fields_for :members, program.members, wrapper: false do |member_form| %> + <div class="row js-program-member fields"> + <div class="col-md-4"> + <%= member_form.input :role, label: false, required: true, placeholder: t('activerecord.attributes.education/program/member.role') %> + </div> + <div class="col-md-5"> + <% + base_members = current_university.administration_members + list_of_members = base_members.administratives.or(base_members.teachers).ordered + %> + <%= member_form.association :member, + collection: list_of_members, + include_blank: "Sélectionnez un membre", + label: false, + required: true %> + </div> + <div class="col-md-3"> + <%= member_form.link_to_remove "Supprimer", class: button_classes_danger %> + </div> + </div> + <% end %> + </div> + <p><%= f.link_to_add "Ajouter un membre", :members, class: 'btn btn-xs btn-primary', data: { target: "#js-program-members" } %></p> + </div> + </div> + </div> </div> <div class="card flex-fill w-100"> <div class="card-header"> @@ -72,7 +105,7 @@ <%= f.input :evaluation, as: :rich_text_area %> <%= f.association :teachers, as: :check_boxes, - collection: current_university.members.teachers.ordered %> + collection: current_university.administration_members.teachers.ordered %> </div> </div> </div> diff --git a/app/views/admin/research/journal/articles/_form.html.erb b/app/views/admin/research/journal/articles/_form.html.erb index 1ca5b93cb..c2131ffce 100644 --- a/app/views/admin/research/journal/articles/_form.html.erb +++ b/app/views/admin/research/journal/articles/_form.html.erb @@ -29,7 +29,7 @@ <%= f.association :volume, collection: @journal.volumes, label: Research::Journal::Volume.model_name.human %> <%= f.input :published_at, html5: true %> <%= f.input :keywords, as: :text, input_html: { rows: 2 } %> - <%= f.association :researchers, collection: current_university.members.researchers.ordered, as: :check_boxes %> + <%= f.association :researchers, collection: current_university.administration_members.researchers.ordered, as: :check_boxes %> </div> </div> </div> diff --git a/config/locales/education/en.yml b/config/locales/education/en.yml index 7c0cd5413..4b6780bf2 100644 --- a/config/locales/education/en.yml +++ b/config/locales/education/en.yml @@ -33,6 +33,8 @@ en: registration: Modalités et délais d’accès schools: Schools with this formation teachers: Teachers + education/program/member: + role: Role education/school: address: Address city: City diff --git a/config/locales/education/fr.yml b/config/locales/education/fr.yml index 509c363e7..7c13e0b24 100644 --- a/config/locales/education/fr.yml +++ b/config/locales/education/fr.yml @@ -33,6 +33,8 @@ fr: registration: Modalités et délais d’accès schools: Écoles proposant cette formation teachers: Enseignants·es + education/program/member: + role: Rôle education/school: address: Adresse city: Ville diff --git a/db/migrate/20211220085352_create_education_program_members.rb b/db/migrate/20211220085352_create_education_program_members.rb new file mode 100644 index 000000000..e4ed85b5f --- /dev/null +++ b/db/migrate/20211220085352_create_education_program_members.rb @@ -0,0 +1,11 @@ +class CreateEducationProgramMembers < ActiveRecord::Migration[6.1] + def change + create_table :education_program_members, id: :uuid do |t| + t.string :role + t.references :member, null: false, foreign_key: { to_table: :administration_members }, type: :uuid + t.references :program, null: false, foreign_key: { to_table: :education_programs }, type: :uuid + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index dd5a22ca6..73760d36b 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_17_115802) do +ActiveRecord::Schema.define(version: 2021_12_20_085352) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" @@ -360,6 +360,16 @@ ActiveRecord::Schema.define(version: 2021_12_17_115802) do t.index ["priority", "run_at"], name: "delayed_jobs_priority" end + create_table "education_program_members", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.string "role" + t.uuid "member_id", null: false + t.uuid "program_id", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["member_id"], name: "index_education_program_members_on_member_id" + t.index ["program_id"], name: "index_education_program_members_on_program_id" + end + create_table "education_programs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "name" @@ -571,6 +581,8 @@ ActiveRecord::Schema.define(version: 2021_12_17_115802) do add_foreign_key "communication_website_posts", "communication_websites" add_foreign_key "communication_website_posts", "universities" add_foreign_key "communication_websites", "universities" + add_foreign_key "education_program_members", "administration_members", column: "member_id" + add_foreign_key "education_program_members", "education_programs", column: "program_id" add_foreign_key "education_programs", "education_programs", column: "parent_id" add_foreign_key "education_programs", "universities" add_foreign_key "education_programs_teachers", "administration_members", column: "education_teacher_id" diff --git a/test/fixtures/education/program/members.yml b/test/fixtures/education/program/members.yml new file mode 100644 index 000000000..d9c701b91 --- /dev/null +++ b/test/fixtures/education/program/members.yml @@ -0,0 +1,32 @@ +# == Schema Information +# +# Table name: education_program_members +# +# id :uuid not null, primary key +# role :string +# created_at :datetime not null +# updated_at :datetime not null +# member_id :uuid not null +# program_id :uuid not null +# +# Indexes +# +# index_education_program_members_on_member_id (member_id) +# index_education_program_members_on_program_id (program_id) +# +# Foreign Keys +# +# fk_rails_... (member_id => administration_members.id) +# fk_rails_... (program_id => education_programs.id) +# +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + role: MyString + member: one + program: one + +two: + role: MyString + member: two + program: two diff --git a/test/models/education/program/member_test.rb b/test/models/education/program/member_test.rb new file mode 100644 index 000000000..3e004507a --- /dev/null +++ b/test/models/education/program/member_test.rb @@ -0,0 +1,28 @@ +# == Schema Information +# +# Table name: education_program_members +# +# id :uuid not null, primary key +# role :string +# created_at :datetime not null +# updated_at :datetime not null +# member_id :uuid not null +# program_id :uuid not null +# +# Indexes +# +# index_education_program_members_on_member_id (member_id) +# index_education_program_members_on_program_id (program_id) +# +# Foreign Keys +# +# fk_rails_... (member_id => administration_members.id) +# fk_rails_... (program_id => education_programs.id) +# +require "test_helper" + +class Education::Program::MemberTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end -- GitLab