diff --git a/Gemfile b/Gemfile index fd73aa125cefe41af4fcc3bd27c74a650abcec69..7342df7bc001dd45ae8116efe417f4f191626f6d 100644 --- a/Gemfile +++ b/Gemfile @@ -36,7 +36,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' +gem "cocoon", "~> 1.2" # Front gem 'jquery-rails' diff --git a/Gemfile.lock b/Gemfile.lock index d80a92781546013564092059c7bd22517b832c77..05191986e8cbaf751e56c071af2930d6bdb8f837 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -122,6 +122,7 @@ GEM regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) childprocess (4.1.0) + cocoon (1.2.15) concurrent-ruby (1.1.9) countries (4.2.1) i18n_data (~> 0.15.0) @@ -267,7 +268,6 @@ 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.13.1) @@ -426,6 +426,7 @@ DEPENDENCIES byebug cancancan capybara (>= 3.26) + cocoon (~> 1.2) country_select curation delayed_job_active_record @@ -443,7 +444,6 @@ 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 8d5f8c6330f1170a5514e1c1f4bf4d810953a5fb..8325a2d7fb557ccbcf2813bec4b23fe348317df0 100644 --- a/app/assets/javascripts/admin.js +++ b/app/assets/javascripts/admin.js @@ -12,7 +12,7 @@ //= require trix //= require sortablejs/Sortable //= require slug/slug -//= require jquery_nested_form +//= require cocoon //= require_self //= require_tree ./admin/commons //= require_tree ./admin/plugins diff --git a/app/assets/javascripts/admin/plugins/sortable.js b/app/assets/javascripts/admin/plugins/sortable.js index e34e6fbfd08c626604e59e291d180ac10a2ed92b..ab073755a18f930db9ac6dc3c088b4a04ee10e64 100644 --- a/app/assets/javascripts/admin/plugins/sortable.js +++ b/app/assets/javascripts/admin/plugins/sortable.js @@ -1,26 +1,87 @@ /*global $, Sortable */ -$(function () { - 'use strict'; - // Re-order elements of a table. Needs a "table-sortable" class on the table, a "data-reorder-url" param on the tbody and a "data-id" param on each tr - var nestedSortables = [].slice.call(document.querySelectorAll('.table-sortable tbody')), - i; - for (i = 0; i < nestedSortables.length; i += 1) { - new Sortable(nestedSortables[i], { + +// Add [data-sortable] to container. Its direct children can be sortable. +// You can pass a value to data-sortable. It can be "xhr" or "inputs". Defaults to "xhr". +// With "xhr", you need to set [data-id="<id>"] on the children and [data-sort-url="<post url to call>"] on the container. +// With "inputs", you need to set [data-sortable-input] on the input field of each child. +window.sortableManager = { + init: function () { + 'use strict'; + var i; + this.containers = document.querySelectorAll('[data-sortable]'); + this.instances = []; + for (i = 0; i < this.containers.length; i += 1) { + this.instances.push(this.createInstance(this.containers[i])); + } + }, + + createInstance: function (container) { + 'use strict'; + var sortableType = container.dataset.sortable; + if (sortableType === 'input') { + $(container).on('cocoon:after-add cocoon:after-remove', this.updateViaInputs); + } + + return new Sortable(container, { handle: '.handle', group: 'nested', animation: 150, fallbackOnBody: true, swapThreshold: 0.65, - onEnd: function (evt) { - var to = evt.to, - ids = [], - url = $(to).attr('data-reorder-url'); - // get list of ids - $('> tr', to).each(function () { - ids.push($(this).attr('data-id')); - }); - $.post(url, { ids: ids }); - } + onEnd: sortableType === 'inputs' ? this.updateViaInputs : this.updateViaXhr }); + }, + + updateViaXhr: function (event) { + 'use strict'; + var url = event.to.dataset.sortUrl, + children = event.to.children, + ids = [], + i; + + if (!url) { + return; + } + + for (i = 0; i < children.length; i += 1) { + ids.push(children[i].dataset.id); + } + + $.post(url, { ids: ids }); + }, + + updateViaInputs: function (event) { + 'use strict'; + var children = event.to.children, + newPosition = 0, + destroyInput, + targetInput, + i; + + for (i = 0; i < children.length; i += 1) { + destroyInput = children[i].querySelector('input[name$="[_destroy]"]'); + if (destroyInput !== null && destroyInput.value === '1') { + continue; + } + + newPosition += 1; + + targetInput = children[i].querySelector('[data-sortable-input]'); + if (targetInput !== null) { + targetInput.value = newPosition; + } + } + }, + + invoke: function () { + 'use strict'; + return { + init: this.init.bind(this) + }; } +}.invoke(); + +window.addEventListener('DOMContentLoaded', function () { + 'use strict'; + window.sortableManager.init(); }); diff --git a/app/controllers/admin/education/program/role/people_controller.rb b/app/controllers/admin/education/program/role/people_controller.rb index 0369f528d938061f02e333bce423a3d35b9856e1..ff0fe767c8b3f77faaa3a3871ec8e587c95468da 100644 --- a/app/controllers/admin/education/program/role/people_controller.rb +++ b/app/controllers/admin/education/program/role/people_controller.rb @@ -1,51 +1,68 @@ class Admin::Education::Program::Role::PeopleController < Admin::Education::Program::ApplicationController - load_and_authorize_resource :role, class: Education::Program::Role, through: :program - load_and_authorize_resource class: Education::Program::Role::Person, through: :role - - before_action :get_available_people, except: :destroy + load_and_authorize_resource :role, class: University::Role, through: :program, param: :role_id, through_association: :university_roles + load_and_authorize_resource :involvement, class: University::Person::Involvement, through: :role, parent: false include Admin::Reorderable - def reorder - super { |first_person| first_person.sync_program } - end + before_action :get_available_people, except: [:reorder, :destroy] def new breadcrumb end + def edit + breadcrumb + add_breadcrumb t('edit') + end + def create - if @person.save - redirect_to admin_education_program_role_path(@role), notice: t('admin.successfully_created_html', model: @person.to_s) + if @involvement.save + redirect_to admin_education_program_role_path(@role, { program_id: @program.id }), notice: t('admin.successfully_created_html', model: @person.to_s) else breadcrumb render :new, status: :unprocessable_entity end end + def update + if @involvement.update(involvement_params) + redirect_to admin_education_program_role_path(@role, { program_id: @program.id }), notice: t('admin.successfully_updated_html', model: @involvement.to_s) + else + breadcrumb + render :edit, status: :unprocessable_entity + add_breadcrumb t('edit') + end + end + def destroy - @person.destroy - redirect_to admin_education_program_role_path(@role), notice: t('admin.successfully_destroyed_html', model: @person.to_s) + @involvement.destroy + redirect_to admin_education_program_role_path(@role, { program_id: @program.id }), notice: t('admin.successfully_destroyed_html', model: @person.to_s) end protected def get_available_people - used_person_ids = @role.people.where.not(id: @person.id).pluck(:person_id) + used_person_ids = @role.involvements.where.not(id: @involvement.id).pluck(:person_id) @available_people = current_university.people.where.not(id: used_person_ids).accessible_by(current_ability).ordered end def breadcrumb super - add_breadcrumb Education::Program::Role.model_name.human(count: 2) - breadcrumb_for @role - add_breadcrumb Education::Program::Role::Person.model_name.human(count: 2) - breadcrumb_for @person + add_breadcrumb University::Role.model_name.human(count: 2) + add_breadcrumb(@role, admin_education_program_role_path(@role, { program_id: @program.id })) + if @involvement + @involvement.persisted? ? add_breadcrumb(@involvement, admin_education_program_role_person_path(@involvement, { program_id: @program.id, role_id: @role.id })) + : add_breadcrumb(t('create')) + end + end + + def involvement_params + params.require(:university_person_involvement) + .permit(:description, :position, :person_id) + .merge(university_id: @program.university_id, kind: :administrator) end - def person_params - params.require(:education_program_role_person) - .permit(:person_id) - .merge(role_id: @role.id) + def model + University::Person::Involvement end end diff --git a/app/controllers/admin/education/program/roles_controller.rb b/app/controllers/admin/education/program/roles_controller.rb index edf300d53dd07ea862b9ad2f4dd91d8c9918e47b..2d95bfaf5fd0af9ef72efed7a40312d38f54cb11 100644 --- a/app/controllers/admin/education/program/roles_controller.rb +++ b/app/controllers/admin/education/program/roles_controller.rb @@ -1,13 +1,17 @@ class Admin::Education::Program::RolesController < Admin::Education::Program::ApplicationController - load_and_authorize_resource class: Education::Program::Role, through: :program + load_and_authorize_resource class: University::Role, through: :program, through_association: :university_roles include Admin::Reorderable - def reorder - super { |first_role| first_role.sync_program } + before_action :load_people, only: [:new, :edit, :create, :update] + + def index + @roles = @roles.ordered + breadcrumb end def show + @involvements = @role.involvements.ordered breadcrumb end @@ -48,13 +52,24 @@ class Admin::Education::Program::RolesController < Admin::Education::Program::Ap def breadcrumb super - add_breadcrumb Education::Program::Role.model_name.human(count: 2) - breadcrumb_for @role + add_breadcrumb University::Role.model_name.human(count: 2), admin_education_program_roles_path(@program) + if @role + @role.persisted? ? add_breadcrumb(@role, admin_education_program_role_path(@role, { program_id: @program.id })) + : add_breadcrumb(t('create')) + end end def role_params - params.require(:education_program_role) - .permit(:title) - .merge(program_id: @program.id, university_id: current_university.id) + params.require(:university_role) + .permit(:description, involvements_attributes: [:id, :person_id, :position, :_destroy]) + .merge(target: @program, university_id: current_university.id) + end + + def model + University::Role + end + + def load_people + @people = current_university.people.accessible_by(current_ability).ordered end end diff --git a/app/controllers/admin/education/program/teachers_controller.rb b/app/controllers/admin/education/program/teachers_controller.rb index 52d7085d53b763e28311db97fbfe040db9a152cc..f469eecb8801d2ad5a09e442b854b615d26220f8 100644 --- a/app/controllers/admin/education/program/teachers_controller.rb +++ b/app/controllers/admin/education/program/teachers_controller.rb @@ -1,7 +1,18 @@ class Admin::Education::Program::TeachersController < Admin::Education::Program::ApplicationController - load_and_authorize_resource class: Education::Program::Teacher, through: :program + load_and_authorize_resource :involvement, + class: University::Person::Involvement, + through: :program, + through_association: :university_person_involvements, + parent: false - before_action :get_teachers, except: :destroy + include Admin::Reorderable + + before_action :get_available_people, except: [:index, :reorder, :destroy] + + def index + @involvements = @involvements.ordered_by_name + breadcrumb + end def new breadcrumb @@ -13,8 +24,8 @@ class Admin::Education::Program::TeachersController < Admin::Education::Program: end def create - if @teacher.save - redirect_to admin_education_program_path(@program), notice: t('admin.successfully_created_html', model: @teacher.to_s) + if @involvement.save + redirect_to admin_education_program_teachers_path(@program), notice: t('admin.successfully_created_html', model: @involvement.to_s) else breadcrumb render :new, status: :unprocessable_entity @@ -22,8 +33,8 @@ class Admin::Education::Program::TeachersController < Admin::Education::Program: end def update - if @teacher.update(teacher_params) - redirect_to admin_education_program_path(@program), notice: t('admin.successfully_updated_html', model: @teacher.to_s) + if @involvement.update(involvement_params) + redirect_to admin_education_program_teachers_path(@program), notice: t('admin.successfully_updated_html', model: @involvement.to_s) else breadcrumb render :edit, status: :unprocessable_entity @@ -32,26 +43,33 @@ class Admin::Education::Program::TeachersController < Admin::Education::Program: end def destroy - @teacher.destroy - redirect_to admin_education_program_path(@program), notice: t('admin.successfully_destroyed_html', model: @teacher.to_s) + @involvement.destroy + redirect_back fallback_location: admin_education_program_path(@program), notice: t('admin.successfully_quit_html', model: @involvement.to_s, target: @involvement.target.to_s) end protected - def get_teachers - used_teacher_ids = @program.teachers.where.not(id: @teacher.id).pluck(:person_id) - @teachers = current_university.people.teachers.where.not(id: used_teacher_ids).accessible_by(current_ability).ordered + def get_available_people + used_person_ids = @program.university_person_involvements.where.not(id: @involvement.id).pluck(:person_id) + @available_people = current_university.people.teachers.where.not(id: used_person_ids).accessible_by(current_ability).ordered end def breadcrumb super - add_breadcrumb Education::Program::Teacher.model_name.human(count: 2) - breadcrumb_for @teacher + add_breadcrumb Education::Program.human_attribute_name("teachers"), admin_education_program_teachers_path(@program) + if @involvement + @involvement.persisted? ? add_breadcrumb(@involvement) + : add_breadcrumb(t('create')) + end + end + + def involvement_params + params.require(:university_person_involvement) + .permit(:description, :position, :person_id) + .merge(university_id: @program.university_id, kind: :teacher) end - def teacher_params - params.require(:education_program_teacher) - .permit(:description, :person_id) - .merge(program_id: @program.id) + def model + University::Person::Involvement end end diff --git a/app/controllers/admin/education/programs_controller.rb b/app/controllers/admin/education/programs_controller.rb index 3402156592d980c2c2c7d4f6afee0d49bfa528fe..980e088b8226826818179ce43fb832675bbe71aa 100644 --- a/app/controllers/admin/education/programs_controller.rb +++ b/app/controllers/admin/education/programs_controller.rb @@ -3,6 +3,8 @@ class Admin::Education::ProgramsController < Admin::Education::ApplicationContro through: :current_university, through_association: :education_programs + before_action :load_teacher_people, only: [:new, :edit, :create, :update] + def index @programs = @programs.root.ordered breadcrumb @@ -31,6 +33,8 @@ class Admin::Education::ProgramsController < Admin::Education::ApplicationContro end def show + @roles = @program.university_roles.ordered + @teacher_involvements = @program.university_person_involvements.includes(:person).ordered_by_name breadcrumb end @@ -82,7 +86,11 @@ class Admin::Education::ProgramsController < Admin::Education::ApplicationContro :featured_image, :featured_image_delete, :featured_image_infos, :featured_image_alt, :prerequisites, :objectives, :duration, :registration, :pedagogy, :evaluation, :accessibility, :pricing, :contacts, :opportunities, :other, - :parent_id, school_ids: [] + :parent_id, school_ids: [], university_person_involvements_attributes: [:id, :person_id, :description, :position, :_destroy] ) end + + def load_teacher_people + @teacher_people = current_university.people.teachers.accessible_by(current_ability).ordered + end end diff --git a/app/controllers/admin/education/school/administrators_controller.rb b/app/controllers/admin/education/school/administrators_controller.rb deleted file mode 100644 index d7788a8b49a0ce838ac66a389ae470bacf113151..0000000000000000000000000000000000000000 --- a/app/controllers/admin/education/school/administrators_controller.rb +++ /dev/null @@ -1,50 +0,0 @@ -class Admin::Education::School::AdministratorsController < Admin::Education::School::ApplicationController - load_and_authorize_resource class: Education::School::Administrator, through: :school - - def new - breadcrumb - end - - def edit - breadcrumb - add_breadcrumb t('edit') - end - - def create - if @administrator.save - redirect_to admin_education_school_path(@school), notice: t('admin.successfully_created_html', model: @administrator.to_s) - else - breadcrumb - render :new, status: :unprocessable_entity - end - end - - def update - if @administrator.update(administrator_params) - redirect_to admin_education_school_path(@school), notice: t('admin.successfully_updated_html', model: @administrator.to_s) - else - breadcrumb - render :edit, status: :unprocessable_entity - add_breadcrumb t('edit') - end - end - - def destroy - @administrator.destroy - redirect_to admin_education_school_path(@school), notice: t('admin.successfully_destroyed_html', model: @administrator.to_s) - end - - protected - - def breadcrumb - super - add_breadcrumb Education::School::Administrator.model_name.human(count: 2) - breadcrumb_for @administrator - end - - def administrator_params - params.require(:education_school_administrator) - .permit(:description, :person_id) - .merge(school_id: @school.id) - end -end diff --git a/app/controllers/admin/education/school/role/people_controller.rb b/app/controllers/admin/education/school/role/people_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..a1bd4624bdd02b8390da2cfbed647be8cdaa9ffb --- /dev/null +++ b/app/controllers/admin/education/school/role/people_controller.rb @@ -0,0 +1,66 @@ +class Admin::Education::School::Role::PeopleController < Admin::Education::School::ApplicationController + load_and_authorize_resource :role, class: University::Role, through: :school, param: :role_id, through_association: :university_roles + load_and_authorize_resource :involvement, class: University::Person::Involvement, through: :role, parent: false + + include Admin::Reorderable + + before_action :get_available_people, except: [:reorder, :destroy] + + def new + breadcrumb + end + + def edit + breadcrumb + add_breadcrumb t('edit') + end + + def create + if @involvement.save + redirect_to admin_education_school_role_path(@role, { school_id: @school.id }), notice: t('admin.successfully_created_html', model: @involvement.to_s) + else + breadcrumb + render :new, status: :unprocessable_entity + end + end + + def update + if @involvement.update(involvement_params) + redirect_to admin_education_school_role_path(@role, { school_id: @school.id }), notice: t('admin.successfully_updated_html', model: @involvement.to_s) + else + breadcrumb + render :edit, status: :unprocessable_entity + add_breadcrumb t('edit') + end + end + + def destroy + @involvement.destroy + redirect_to admin_education_school_role_path(@role, { school_id: @school.id }), notice: t('admin.successfully_destroyed_html', model: @involvement.to_s) + end + + protected + + def get_available_people + used_person_ids = @role.involvements.where.not(id: @involvement.id).pluck(:person_id) + @available_people = current_university.people.administration.where.not(id: used_person_ids).accessible_by(current_ability).ordered + end + + def breadcrumb + super + add_breadcrumb University::Role.model_name.human(count: 2), admin_education_school_roles_path(@school) + add_breadcrumb(@role, admin_education_school_role_path(@role, { school_id: @school.id })) + if @involvement + @involvement.persisted? ? add_breadcrumb(@involvement, admin_education_school_role_person_path(@involvement, { school_id: @school.id, role_id: @role.id })) + : add_breadcrumb(t('create')) + end + end + + def involvement_params + params.require(:university_person_involvement).permit(:position, :person_id) + end + + def model + University::Person::Involvement + end +end diff --git a/app/controllers/admin/education/school/roles_controller.rb b/app/controllers/admin/education/school/roles_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..7ab46b743b6a18ddeb7ae3c95e381842896a8173 --- /dev/null +++ b/app/controllers/admin/education/school/roles_controller.rb @@ -0,0 +1,75 @@ +class Admin::Education::School::RolesController < Admin::Education::School::ApplicationController + load_and_authorize_resource class: University::Role, through: :school, through_association: :university_roles + + include Admin::Reorderable + + before_action :load_administration_people, only: [:new, :edit, :create, :update] + + def index + @roles = @roles.ordered + breadcrumb + end + + def show + @involvements = @role.involvements.ordered + breadcrumb + end + + def new + breadcrumb + end + + def edit + breadcrumb + add_breadcrumb t('edit') + end + + def create + if @role.save + redirect_to admin_education_school_role_path(@role), notice: t('admin.successfully_created_html', model: @role.to_s) + else + breadcrumb + render :new, status: :unprocessable_entity + end + end + + def update + if @role.update(role_params) + redirect_to admin_education_school_role_path(@role), notice: t('admin.successfully_updated_html', model: @role.to_s) + else + breadcrumb + render :edit, status: :unprocessable_entity + add_breadcrumb t('edit') + end + end + + def destroy + @role.destroy + redirect_to admin_education_school_roles_path(@school), notice: t('admin.successfully_destroyed_html', model: @role.to_s) + end + + protected + + def breadcrumb + super + add_breadcrumb Education::School.human_attribute_name('roles'), admin_education_school_roles_path(@school) + if @role + @role.persisted? ? add_breadcrumb(@role, admin_education_school_role_path(@role, { school_id: @school.id })) + : add_breadcrumb(t('create')) + end + end + + def role_params + params.require(:university_role) + .permit(:description, involvements_attributes: [:id, :person_id, :position, :_destroy]) + .merge(target: @school, university_id: @school.university_id) + end + + def model + University::Role + end + + def load_administration_people + @administration_people = current_university.people.administration.accessible_by(current_ability).ordered + end +end diff --git a/app/controllers/admin/education/schools_controller.rb b/app/controllers/admin/education/schools_controller.rb index e1368257c8d1520570065c6c0a9817a75a720f91..7152bbd2748ae5a6622823a90566cf1fea61c082 100644 --- a/app/controllers/admin/education/schools_controller.rb +++ b/app/controllers/admin/education/schools_controller.rb @@ -8,6 +8,7 @@ class Admin::Education::SchoolsController < Admin::Education::ApplicationControl end def show + @roles = @school.university_roles.ordered breadcrumb end diff --git a/app/controllers/admin/education/teachers_controller.rb b/app/controllers/admin/education/teachers_controller.rb index 6aa8315db54177a5b0375306232d42218d9c01ec..93b626fd9a9a89e3889f33b120465588666abaaa 100644 --- a/app/controllers/admin/education/teachers_controller.rb +++ b/app/controllers/admin/education/teachers_controller.rb @@ -1,13 +1,29 @@ class Admin::Education::TeachersController < Admin::Education::ApplicationController + before_action :load_teacher, only: [:show, :edit, :update] + def index @teachers = current_university.people.teachers.accessible_by(current_ability).ordered.page(params[:page]) breadcrumb end def show - @teacher = current_university.people.teachers.accessible_by(current_ability).find(params[:id]) + @involvements = @teacher.involvements_as_teacher.includes(:target).order(:created_at).page(params[:page]) + breadcrumb + end + + def edit breadcrumb - @programs = @teacher.education_programs.ordered.page(params[:page]) + add_breadcrumb t('edit') + end + + def update + if @teacher.update(teacher_params) + redirect_to admin_education_teacher_path(@teacher), notice: t('admin.successfully_updated_html', model: @teacher.to_s) + else + render :edit + breadcrumb + add_breadcrumb t('edit') + end end protected @@ -17,4 +33,14 @@ class Admin::Education::TeachersController < Admin::Education::ApplicationContro add_breadcrumb t('education.teachers', count: 2), admin_education_teachers_path add_breadcrumb @teacher, admin_education_teacher_path(@teacher) if @teacher end + + def load_teacher + @teacher = current_university.people.teachers.accessible_by(current_ability).find(params[:id]) + end + + def teacher_params + params.require(:university_person).permit( + involvements_attributes: [:id, :target_id, :target_type, :description, :_destroy] + ) + end end diff --git a/app/models/ability.rb b/app/models/ability.rb index 905dd2f6a0db3038439066dcc1c2fec1f76f2273..0a189db00a1f71e12f6c32180960d1b03550b4ca 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -32,10 +32,12 @@ class Ability def teacher can :manage, University::Person, user_id: @user.id + # can :read, University::Person, university_id: @user.university_id + cannot :create, University::Person can :read, Education::Program, university_id: @user.university_id - can :manage, Education::Program::Teacher, person_id: @user.person&.id - can :read, Education::Program::Role, university_id: @user.university_id - can :manage, Education::Program::Role::Person, person_id: @user.person&.id + can :read, University::Role, university_id: @user.university_id + can :manage, University::Person::Involvement, person_id: @user.person&.id + can :read, University::Person::Involvement, university_id: @user.university_id end def program_manager @@ -57,15 +59,13 @@ class Ability can :manage, Communication::Website::Imported::Page, university_id: @user.university_id can :manage, Communication::Website::Imported::Post, university_id: @user.university_id can :manage, Education::School, university_id: @user.university_id - can :manage, Education::School::Administrator, university_id: @user.university_id can :manage, Education::Program, university_id: @user.university_id - can :manage, Education::Program::Teacher, university_id: @user.university_id - can :manage, Education::Program::Role, university_id: @user.university_id - can :manage, Education::Program::Role::Person, university_id: @user.university_id can :manage, Research::Journal, university_id: @user.university_id can :manage, Research::Journal::Article, university_id: @user.university_id can :manage, Research::Journal::Volume, university_id: @user.university_id can :manage, Research::Laboratory, university_id: @user.university_id + can :manage, University::Role, university_id: @user.university_id + can :manage, University::Person::Involvement, university_id: @user.university_id can :read, User, university_id: @user.university_id can :manage, User, university_id: @user.university_id, role: @user.managed_roles end diff --git a/app/models/communication/website.rb b/app/models/communication/website.rb index 7549fdf462e06c88fe75fba7e750b66b95637c51..d583ecedbd4a216b8653318347c9cd3dc4490104 100644 --- a/app/models/communication/website.rb +++ b/app/models/communication/website.rb @@ -57,13 +57,18 @@ class Communication::Website < ApplicationRecord pages + pages.map(&:active_storage_blobs).flatten + posts + posts.map(&:active_storage_blobs).flatten + [home] + home.explicit_active_storage_blobs + - categories + menus + people + [about] + people_with_facets + people.map(&:active_storage_blobs).flatten + + categories + menus + [about] ) if about.is_a? Education::School dependencies += about.programs + dependencies += about.programs.map(&:active_storage_blobs).flatten elsif about.is_a? Research::Journal - dependencies.concat [about.articles, about.volumes] + dependencies += about.articles + dependencies += about.articles.map(&:active_storage_blobs).flatten + dependencies += about.volumes + dependencies += about.volumes.map(&:active_storage_blobs).flatten end dependencies diff --git a/app/models/communication/website/with_abouts.rb b/app/models/communication/website/with_abouts.rb index 88ef5400cfd0a5fb59902f4fb2de8ca8f507e54a..83916b81544fc65b6e2c256bc20e4053ddcff20e 100644 --- a/app/models/communication/website/with_abouts.rb +++ b/app/models/communication/website/with_abouts.rb @@ -64,15 +64,31 @@ module Communication::Website::WithAbouts def people @people ||= begin + people = authors + if about_school? + people += about.university_people_through_role_involvements + people += about.university_people_through_program_involvements + people += about.university_people_through_program_role_involvements + elsif about_journal? + people += about.people + end + people.uniq.compact + end + end + + def people_with_facets + @people_with_facets ||= begin people = authors + authors.compact.map(&:author) if about_school? - people += programs.collect(&:university_people_through_teachers).flatten - people += programs.collect(&:university_people_through_teachers).flatten.map(&:teacher) - people += about.university_people_through_administrators - people += about.university_people_through_administrators.map(&:administrator) + people += about.university_people_through_role_involvements + people += about.university_people_through_role_involvements.map(&:administrator) + people += about.university_people_through_program_involvements + people += about.university_people_through_program_involvements.map(&:teacher) + people += about.university_people_through_program_role_involvements + people += about.university_people_through_program_role_involvements.map(&:administrator) elsif about_journal? - people += research_articles.collect(&:people).flatten - people += research_articles.collect(&:people).flatten.map(&:researcher) + people += about.people + people += about.people.map(&:researcher) end people.uniq.compact end diff --git a/app/models/communication/website/with_menu_items.rb b/app/models/communication/website/with_menu_items.rb index b40ed1b5ba50f358da6acfebf8d9082dd68136f2..4a343d7dccf2dec0b13c2a8aff251e23dfe6eae3 100644 --- a/app/models/communication/website/with_menu_items.rb +++ b/app/models/communication/website/with_menu_items.rb @@ -53,11 +53,11 @@ module Communication::Website::WithMenuItems end def menu_item_kind_researchers? - research_articles.collect(&:people).flatten.any? + about_journal? && about.people.any? end def menu_item_kind_teachers? - programs.collect(&:university_people_through_teachers).flatten.any? + about_school? && about.university_people_through_program_involvements.any? end def menu_item_kind_research_volumes? diff --git a/app/models/education/program.rb b/app/models/education/program.rb index c4c75482b940290fbf10fc1dc4c503b05a43a4c2..37c7c1ff77a18c8f4ba8ce4971b1cb57211ab0b3 100644 --- a/app/models/education/program.rb +++ b/app/models/education/program.rb @@ -63,20 +63,23 @@ class Education::Program < ApplicationRecord class_name: 'Education::Program', foreign_key: :parent_id, dependent: :destroy - has_many :teachers, - class_name: 'Education::Program::Teacher', + has_many :university_roles, + class_name: 'University::Role', + as: :target, dependent: :destroy - has_many :university_people_through_teachers, - through: :teachers, + has_many :involvements_through_roles, + through: :university_roles, + source: :involvements + has_many :university_people_through_role_involvements, + through: :involvements_through_roles, source: :person - has_many :roles, - class_name: 'Education::Program::Role', + has_many :university_person_involvements, + class_name: 'University::Person::Involvement', + as: :target, + inverse_of: :target, dependent: :destroy - has_many :role_people, - through: :roles, - source: :people - has_many :university_people_through_roles, - through: :role_people, + has_many :university_people_through_involvements, + through: :university_person_involvements, source: :person has_many :website_categories, class_name: 'Communication::Website::Category', @@ -88,6 +91,8 @@ class Education::Program < ApplicationRecord association_foreign_key: 'education_school_id' has_many :websites, -> { distinct }, through: :schools + accepts_nested_attributes_for :university_person_involvements, reject_if: :all_blank, allow_destroy: true + enum level: { first_year: 100, second_year: 200, @@ -122,10 +127,12 @@ class Education::Program < ApplicationRecord def git_dependencies(website) [self] + active_storage_blobs + - university_people_through_teachers + - university_people_through_teachers.map(&:teacher) + - university_people_through_roles - # TODO: les administrative via roles + university_people_through_involvements + + university_people_through_involvements.map(&:active_storage_blobs) + + university_people_through_involvements.map(&:teacher) + + university_people_through_role_involvements + + university_people_through_role_involvements.map(&:active_storage_blobs) + + university_people_through_role_involvements.map(&:administrator) end def git_destroy_dependencies(website) diff --git a/app/models/education/program/role.rb b/app/models/education/program/role.rb deleted file mode 100644 index d52e7447e3c4043422d87aaf474c03f9561149c7..0000000000000000000000000000000000000000 --- a/app/models/education/program/role.rb +++ /dev/null @@ -1,46 +0,0 @@ -# == Schema Information -# -# Table name: education_program_roles -# -# id :uuid not null, primary key -# position :integer -# title :string -# created_at :datetime not null -# updated_at :datetime not null -# program_id :uuid not null -# university_id :uuid not null -# -# Indexes -# -# index_education_program_roles_on_program_id (program_id) -# index_education_program_roles_on_university_id (university_id) -# -# Foreign Keys -# -# fk_rails_... (program_id => education_programs.id) -# fk_rails_... (university_id => universities.id) -# -class Education::Program::Role < ApplicationRecord - include WithPosition - - belongs_to :university - belongs_to :program, class_name: 'Education::Program' - has_many :people, class_name: 'Education::Program::Role::Person', dependent: :destroy - has_many :university_people, through: :people, source: :person - - after_commit :sync_program - - def to_s - "#{title}" - end - - def sync_program - program.sync_with_git - end - - protected - - def last_ordered_element - program.roles.ordered.last - end -end diff --git a/app/models/education/program/role/person.rb b/app/models/education/program/role/person.rb deleted file mode 100644 index 87521175e302f56ef0abed9e39ee19f90ad281e5..0000000000000000000000000000000000000000 --- a/app/models/education/program/role/person.rb +++ /dev/null @@ -1,44 +0,0 @@ -# == Schema Information -# -# Table name: education_program_role_people -# -# id :uuid not null, primary key -# position :integer -# created_at :datetime not null -# updated_at :datetime not null -# person_id :uuid not null -# role_id :uuid not null -# -# Indexes -# -# index_education_program_role_people_on_person_id (person_id) -# index_education_program_role_people_on_role_id (role_id) -# -# Foreign Keys -# -# fk_rails_... (person_id => university_people.id) -# fk_rails_... (role_id => education_program_roles.id) -# -class Education::Program::Role::Person < ApplicationRecord - include WithPosition - - belongs_to :person, class_name: 'University::Person' - belongs_to :role, class_name: 'Education::Program::Role' - delegate :program, to: :role - - after_commit :sync_program - - def to_s - person.to_s - end - - def sync_program - program.sync_with_git - end - - protected - - def last_ordered_element - role.people.ordered.last - end -end diff --git a/app/models/education/program/teacher.rb b/app/models/education/program/teacher.rb deleted file mode 100644 index ee27e125906adac518d821a451926a46c520ab5a..0000000000000000000000000000000000000000 --- a/app/models/education/program/teacher.rb +++ /dev/null @@ -1,45 +0,0 @@ -# == Schema Information -# -# Table name: education_program_teachers -# -# id :uuid not null, primary key -# description :text -# created_at :datetime not null -# updated_at :datetime not null -# person_id :uuid not null -# program_id :uuid not null -# -# Indexes -# -# index_education_program_teachers_on_person_id (person_id) -# index_education_program_teachers_on_program_id (program_id) -# -# Foreign Keys -# -# fk_rails_... (person_id => university_people.id) -# fk_rails_... (program_id => education_programs.id) -# -class Education::Program::Teacher < ApplicationRecord - belongs_to :program, class_name: 'Education::Program' - belongs_to :person, class_name: 'University::Person' - - validates :person_id, uniqueness: { scope: :program_id } - - scope :ordered, -> { joins(:person).order('university_people.last_name, university_people.first_name') } - - after_commit :sync_program - - def to_s - person.to_s - end - - def best_description - description.blank? ? person.description : description - end - - protected - - def sync_program - program.sync_with_git - end -end diff --git a/app/models/education/school.rb b/app/models/education/school.rb index 6f79e2f3beb978ade47e0fe8d554ec8fcb5824c6..7af5c773bd9de1908bf2ecb106bd3b78a58502cd 100644 --- a/app/models/education/school.rb +++ b/app/models/education/school.rb @@ -28,16 +28,23 @@ class Education::School < ApplicationRecord belongs_to :university has_many :websites, class_name: 'Communication::Website', as: :about, dependent: :nullify - has_many :administrators, dependent: :destroy - has_many :university_people_through_administrators, - through: :administrators, - source: :person has_and_belongs_to_many :programs, class_name: 'Education::Program', join_table: 'education_programs_schools', foreign_key: 'education_school_id', association_foreign_key: 'education_program_id' - has_many :teachers, -> { distinct }, through: :programs + + has_many :university_roles, class_name: 'University::Role', as: :target, dependent: :destroy + has_many :involvements_through_roles, through: :university_roles, source: :involvements + has_many :university_people_through_role_involvements, + through: :involvements_through_roles, + source: :person + has_many :university_people_through_program_involvements, + through: :programs, + source: :university_people_through_involvements + has_many :university_people_through_program_role_involvements, + through: :programs, + source: :university_people_through_role_involvements validates :name, :address, :city, :zipcode, :country, presence: true @@ -53,7 +60,7 @@ class Education::School < ApplicationRecord def git_dependencies(website) [self] + - university_people_through_administrators + - university_people_through_administrators.map(&:administrator) + university_people_through_role_involvements + + university_people_through_role_involvements.map(&:administrator) end end diff --git a/app/models/education/school/administrator.rb b/app/models/education/school/administrator.rb deleted file mode 100644 index 6b9e5a69dcb76d99c0d9f55c30fd405b1102385d..0000000000000000000000000000000000000000 --- a/app/models/education/school/administrator.rb +++ /dev/null @@ -1,45 +0,0 @@ -# == Schema Information -# -# Table name: education_school_administrators -# -# id :uuid not null, primary key -# description :text -# created_at :datetime not null -# updated_at :datetime not null -# person_id :uuid not null -# school_id :uuid not null -# -# Indexes -# -# index_education_school_administrators_on_person_id (person_id) -# index_education_school_administrators_on_school_id (school_id) -# -# Foreign Keys -# -# fk_rails_... (person_id => university_people.id) -# fk_rails_... (school_id => education_schools.id) -# -class Education::School::Administrator < ApplicationRecord - belongs_to :school - belongs_to :person, class_name: "University::Person" - - validates :person_id, uniqueness: { scope: :school_id } - - after_commit :sync_school - - scope :ordered, -> { joins(:person).order('university_people.last_name, university_people.first_name') } - - def to_s - person.to_s - end - - def best_description - description.blank? ? person.description : description - end - - protected - - def sync_school - school.sync_with_git - end -end diff --git a/app/models/research/journal.rb b/app/models/research/journal.rb index bc4be6eca437a294db96061f4629166f8fc11b20..f4f6fc15f97fa17618ec065c2abfd9d7a57110ff 100644 --- a/app/models/research/journal.rb +++ b/app/models/research/journal.rb @@ -27,7 +27,7 @@ class Research::Journal < ApplicationRecord has_many :websites, class_name: 'Communication::Website', as: :about, dependent: :nullify has_many :volumes, foreign_key: :research_journal_id, dependent: :destroy has_many :articles, foreign_key: :research_journal_id, dependent: :destroy - has_many :people, through: :articles + has_many :people, -> { distinct }, through: :articles scope :ordered, -> { order(:title) } @@ -40,7 +40,7 @@ class Research::Journal < ApplicationRecord end def git_dependencies(website) - [self] + articles + volumes + people + people.map(&:researcher) + [self] + articles + volumes + people + people.map(&:active_storage_blobs).flatten + people.map(&:researcher) end def git_destroy_dependencies(website) diff --git a/app/models/research/journal/article.rb b/app/models/research/journal/article.rb index 5617202477cb2a9af6cf8e85dd15d144a276b35b..1d899b51a97105eefebe45a66a5650d1c0273489 100644 --- a/app/models/research/journal/article.rb +++ b/app/models/research/journal/article.rb @@ -66,6 +66,7 @@ class Research::Journal::Article < ApplicationRecord active_storage_blobs + other_articles_in_the_volume + people + + people.map(&:active_storage_blobs).flatten + people.map(&:researcher) end diff --git a/app/models/research/journal/volume.rb b/app/models/research/journal/volume.rb index 80c1fb01f42f15b0b67f75d08389b31b3064f273..9365b67740f1130f468ba8cd4b88f6b240bcca87 100644 --- a/app/models/research/journal/volume.rb +++ b/app/models/research/journal/volume.rb @@ -8,7 +8,7 @@ # keywords :text # number :integer # published :boolean default(FALSE) -# published_at :date +# published_at :datetime # slug :string # title :string # created_at :datetime not null @@ -47,11 +47,11 @@ class Research::Journal::Volume < ApplicationRecord end def git_path(website) - "content/volumes/#{published_at.year}/#{published_at.strftime "%Y-%m-%d"}-#{slug}.html" if published_at + "content/volumes/#{published_at.year}/#{slug}/_index.html" if published_at end def git_dependencies(website) - [self] + articles + people + people.map(&:researcher) + active_storage_blobs + [self] + articles + people + people.map(&:active_storage_blobs).flatten + people.map(&:researcher) + active_storage_blobs end def git_destroy_dependencies(website) diff --git a/app/models/university/person.rb b/app/models/university/person.rb index c23ba6098c2fd5f751b094e316035e8ea0acf018..392568a1cb285f87087fc15a7bd4fd83f68f207d 100644 --- a/app/models/university/person.rb +++ b/app/models/university/person.rb @@ -31,8 +31,10 @@ # class University::Person < ApplicationRecord include WithGit + include WithBlobs include WithSlug include WithPicture + include WithEducation has_rich_text :biography @@ -44,22 +46,6 @@ class University::Person < ApplicationRecord join_table: :research_journal_articles_researchers, foreign_key: :researcher_id - has_many :education_program_teachers, - class_name: 'Education::Program::Teacher', - dependent: :destroy - - has_many :education_program_role_people, - class_name: 'Education::Program::Role::Person', - dependent: :destroy - - has_many :education_programs, - through: :education_program_teachers, - source: :program - - has_many :education_school_administrators, - class_name: 'Education::School::Administrator', - dependent: :destroy - has_many :communication_website_posts, class_name: 'Communication::Website::Post', foreign_key: :author_id, @@ -70,6 +56,10 @@ class University::Person < ApplicationRecord foreign_key: :author_id, dependent: :destroy + has_many :involvements, + class_name: 'University::Person::Involvement', + dependent: :destroy + has_many :author_websites, -> { distinct }, through: :communication_website_posts, @@ -85,6 +75,7 @@ class University::Person < ApplicationRecord through: :education_programs, source: :websites + accepts_nested_attributes_for :involvements validates_presence_of :first_name, :last_name validates_uniqueness_of :email, @@ -119,7 +110,7 @@ class University::Person < ApplicationRecord dependencies = [] if for_website?(website) dependencies << self - dependencies << best_picture.blob + dependencies.concat active_storage_blobs end dependencies << administrator if administrator.for_website?(website) dependencies << author if author.for_website?(website) @@ -153,6 +144,14 @@ class University::Person < ApplicationRecord protected + def explicit_blob_ids + [picture&.blob_id] + end + + def inherited_blob_ids + [best_picture&.blob_id] + end + def sanitize_email self.email = self.email.downcase.strip end diff --git a/app/models/university/person/administrator.rb b/app/models/university/person/administrator.rb index fc58865e3cace8c5bedd097b13181c71e4346e33..82976022e823969216acde098bb649c11b5dd955 100644 --- a/app/models/university/person/administrator.rb +++ b/app/models/university/person/administrator.rb @@ -39,6 +39,9 @@ class University::Person::Administrator < University::Person end def for_website?(website) - is_administration && website.about_school? && Education::School::Administrator.where(school_id: website.about_id, person_id: id).any? + is_administration && website.about_school? && ( + website.about.university_people_through_role_involvements.find_by(id: id).present? || + website.programs.published.joins(:involvements_through_roles).where(university_person_involvements: { person_id: id }).any? + ) end end diff --git a/app/models/university/person/involvement.rb b/app/models/university/person/involvement.rb index 83c1b444a5dc914519773f8f35a3c593cf96ea18..8cc875a66c538f7a9ed09f04e97380021e56f6e3 100644 --- a/app/models/university/person/involvement.rb +++ b/app/models/university/person/involvement.rb @@ -27,15 +27,50 @@ class University::Person::Involvement < ApplicationRecord include WithPosition + enum kind: { administrator: 10, researcher: 20, teacher: 30 } + belongs_to :university - belongs_to :person + belongs_to :person, class_name: 'University::Person' belongs_to :target, polymorphic: true - enum kind: { administrator: 10, researcher: 20, teacher: 30 } + validates :person_id, uniqueness: { scope: [:target_id, :target_type] } + validates :target_id, uniqueness: { scope: [:person_id, :target_type] } + + before_validation :set_kind, on: :create + before_validation :set_university_id, on: :create + after_commit :sync_with_git + + scope :ordered_by_name, -> { + joins(:person).select('university_person_involvements.*') + .order('university_people.last_name', 'university_people.first_name') + } + + def to_s + "#{person}" + end + + def sync_with_git + target.sync_with_git if target.respond_to? :sync_with_git + end protected def last_ordered_element self.class.unscoped.where(university_id: university_id, target: target).ordered.last end + + def set_kind + case target_type + when "Education::Program" + self.kind = :teacher + when "Research::Laboratory" + self.kind = :researcher + else + self.kind = :administrator + end + end + + def set_university_id + self.university_id = self.person.university_id + end end diff --git a/app/models/university/person/teacher.rb b/app/models/university/person/teacher.rb index 8f354959b118a2d4486826f5be6117b6ab8c9ee6..89e5a7d3441b0720af6edb0d7993ec93a27734af 100644 --- a/app/models/university/person/teacher.rb +++ b/app/models/university/person/teacher.rb @@ -41,8 +41,8 @@ class University::Person::Teacher < University::Person def for_website?(website) is_teacher && website.about_school? && website.programs .published - .joins(:teachers) - .where(education_program_teachers: { person_id: id }) + .joins(:university_person_involvements) + .where(university_person_involvements: { person_id: id }) .any? end end diff --git a/app/models/university/person/with_education.rb b/app/models/university/person/with_education.rb new file mode 100644 index 0000000000000000000000000000000000000000..e350249f0676aa67435303ce7b9f29d5524c81ce --- /dev/null +++ b/app/models/university/person/with_education.rb @@ -0,0 +1,21 @@ +module University::Person::WithEducation + extend ActiveSupport::Concern + + included do + has_many :involvements_as_teacher, + -> { where(kind: 'teacher') }, + class_name: 'University::Person::Involvement' + + has_many :education_programs_as_teacher, + through: :involvements_as_teacher, + source: :target, + source_type: "Education::Program" + end + + def education_programs_as_administrator + university.education_programs + .joins(:involvements_through_roles) + .where(university_person_involvements: { person_id: id }) + .distinct + end +end diff --git a/app/models/university/role.rb b/app/models/university/role.rb index d63eb7041925492af796c72c6b8585b4f7140ce6..7d6c29d6fa46ae38b9e2b5da3ecc6a13cb3b9371 100644 --- a/app/models/university/role.rb +++ b/app/models/university/role.rb @@ -25,6 +25,18 @@ class University::Role < ApplicationRecord belongs_to :university belongs_to :target, polymorphic: true, optional: true + has_many :involvements, class_name: 'University::Person::Involvement', as: :target, dependent: :destroy, inverse_of: :target + has_many :people, through: :involvements + + accepts_nested_attributes_for :involvements, reject_if: :all_blank, allow_destroy: true + + def to_s + "#{description}" + end + + def sync_with_git + target.sync_with_git if target&.respond_to? :sync_with_git + end protected diff --git a/app/views/admin/dashboard/index.html.erb b/app/views/admin/dashboard/index.html.erb index bfc04677d206700925559742c2e0515ee3048532..06139d6319f2d2cd80d83698d1b671bde6bd88dc 100644 --- a/app/views/admin/dashboard/index.html.erb +++ b/app/views/admin/dashboard/index.html.erb @@ -15,7 +15,7 @@ </div> </div> -<% if current_university.research_journals.any? %> +<% if current_university.research_journals.any? && can?(:read, Research::Journal) %> <h2 class="h4 my-4"><%= Research::Journal.model_name.human(count: 2) %></h2> <div class="row"> <% current_university.research_journals.each do |journal| %> @@ -33,7 +33,7 @@ </div> <% end %> -<% if current_university.communication_websites.any? %> +<% if current_university.communication_websites.any? && can?(:read, Communication::Website) %> <h2 class="h4 my-4"><%= Communication::Website.model_name.human(count: 2) %></h2> <div class="row"> <% current_university.communication_websites.each do |website| %> diff --git a/app/views/admin/education/program/role/people/_list.html.erb b/app/views/admin/education/program/role/people/_list.html.erb deleted file mode 100644 index fc31ddd11a709929630337c2f87dde710821fc42..0000000000000000000000000000000000000000 --- a/app/views/admin/education/program/role/people/_list.html.erb +++ /dev/null @@ -1,30 +0,0 @@ -<% if people.any? %> - <table class="table table-sortable"> - <thead> - <tr> - <th><%= Education::Program::Role::Person.model_name.human %></th> - <th></th> - </tr> - </thead> - <tbody data-reorder-url="<%= reorder_admin_education_program_role_people_path(program_id: @program.id, role_id: @role.id) %>"> - <% people.each do |person| %> - <tr class="handle" data-id="<%= person.id %>"> - <td> - <%= link_to_if can?(:read, person.person), - person.person, - admin_university_person_path(person.person) %> - </td> - <td class="text-end pe-0"> - <div class="btn-group" role="group"> - <%= link_to t('delete'), - admin_education_program_role_person_path(person, { role_id: @role.id }), - method: :delete, - data: { confirm: t('please_confirm') }, - class: button_classes_danger %> - </div> - </td> - </tr> - <% end %> - </tbody> - </table> -<% end %> diff --git a/app/views/admin/education/program/role/people/new.html.erb b/app/views/admin/education/program/role/people/new.html.erb deleted file mode 100644 index d2a7ac69768b51844a88ea8619cf00ff449dd98e..0000000000000000000000000000000000000000 --- a/app/views/admin/education/program/role/people/new.html.erb +++ /dev/null @@ -1,19 +0,0 @@ -<% content_for :title, Education::Program::Role::Person.model_name.human %> - -<%= simple_form_for [:admin, @person] do |f| %> - <div class="row"> - <div class="col-md-8"> - <div class="card flex-fill w-100"> - <div class="card-header"> - <h5 class="card-title mb-0"><%= t('admin.infos') %></h5> - </div> - <div class="card-body"> - <%= f.association :person, collection: @available_people %> - </div> - </div> - </div> - </div> - <% content_for :action_bar_right do %> - <%= submit f %> - <% end %> -<% end %> diff --git a/app/views/admin/education/program/roles/_form.html.erb b/app/views/admin/education/program/roles/_form.html.erb index 26ccb783e9660e9a9c21fdeab7c8088934d0a0c9..54d99730bb0f75ceb39daa2b09be65eb3fe51a9c 100644 --- a/app/views/admin/education/program/roles/_form.html.erb +++ b/app/views/admin/education/program/roles/_form.html.erb @@ -1,4 +1,6 @@ -<%= simple_form_for [:admin, role] do |f| %> +<%= simple_form_for [:admin, role], + url: role.new_record? ? admin_education_program_roles_path(@program) + : admin_education_program_role_path(role, { program_id: @program.id }) do |f| %> <div class="row"> <div class="col-md-8"> <div class="card flex-fill w-100"> @@ -6,11 +8,31 @@ <h5 class="card-title mb-0"><%= t('admin.infos') %></h5> </div> <div class="card-body"> - <%= f.input :title %> + <%= f.input :description %> + </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"><%= University::Person.model_name.human(count: 2) %></h5> + </div> + <div class="card-body"> + <%= link_to_add_association t('add'), f, :involvements, class: "btn btn-primary mb-3", data: { + 'association-insertion-method': 'append', + 'association-insertion-node': '#involvements' + } %> + + <div class="mb-3" id="involvements" data-sortable="inputs"> + <%= f.simple_fields_for :involvements, role.involvements.sort_by(&:position), include_id: false do |involvement_f| %> + <%= render 'admin/education/program/roles/involvement_fields', f: involvement_f, include_id: true %> + <% end %> + </div> </div> </div> </div> </div> + <% content_for :action_bar_right do %> <%= submit f %> <% end %> diff --git a/app/views/admin/education/program/roles/_involvement_fields.html.erb b/app/views/admin/education/program/roles/_involvement_fields.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..505d7ca9b103695623cc39c52ffe75af6058a0f1 --- /dev/null +++ b/app/views/admin/education/program/roles/_involvement_fields.html.erb @@ -0,0 +1,18 @@ +<% include_id ||= false %> +<div class="card nested-fields mb-2"> + <div class="card-body"> + <div class="row align-items-center"> + <div class="col-1"> + <i class="fa fa-bars handle"></i> + </div> + <div class="col-9"> + <%= f.association :person, collection: @people, label: false, include_blank: :translate, wrapper: false, required: true %> + </div> + <div class="col-2"> + <%= link_to_remove_association '<i class="fas fa-trash"></i>'.html_safe, f, class: 'btn btn-sm btn-danger' %> + </div> + </div> + </div> + <%= f.hidden_field :position, data: { 'sortable-input': '' } %> + <%= f.hidden_field :id if include_id %> +</div> diff --git a/app/views/admin/education/program/roles/_list.html.erb b/app/views/admin/education/program/roles/_list.html.erb index c4465b6573d625c4e5fee70a81ee2240a26b8f47..6362fc22b67d75f730ad6e9b29d8cce234696bef 100644 --- a/app/views/admin/education/program/roles/_list.html.erb +++ b/app/views/admin/education/program/roles/_list.html.erb @@ -1,21 +1,27 @@ <% if roles.any? %> - <table class="table table-sortable"> + <table class="table"> <thead> <tr> - <th class="ps-0"><%= Education::Program::Role.model_name.human %></th> - <th><%= Education::Program::Role.human_attribute_name('people') %></th> + <% if can? :reorder, University::Role %> + <th width="20" class="ps-0"> </th> + <% end %> + <th class="ps-0"><%= University::Role.model_name.human %></th> + <th><%= University::Role.human_attribute_name('people') %></th> <th></th> </tr> </thead> - <tbody data-reorder-url="<%= reorder_admin_education_program_roles_path(program_id: @program.id) %>"> + <tbody data-sortable data-sort-url="<%= reorder_admin_education_program_roles_path(program_id: @program.id) %>"> <% roles.each do |role| %> - <tr class="handle" data-id="<%= role.id %>"> + <tr data-id="<%= role.id %>"> + <% if can? :reorder, University::Role %> + <td><i class="fa fa-bars handle"></i></td> + <% end %> <td class="ps-0"> <%= link_to_if can?(:read, role), role, admin_education_program_role_path(role, { program_id: @program.id }) %> </td> - <td><%= role.people.includes(:person).ordered.map { |person| person.person.to_s }.to_sentence %></td> + <td><%= role.involvements.includes(:person).ordered.map { |involvement| involvement.person.to_s }.to_sentence %></td> <td class="text-end pe-0"> <div class="btn-group" role="group"> <%= link_to t('edit'), diff --git a/app/views/admin/education/program/roles/index.html.erb b/app/views/admin/education/program/roles/index.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..fa4e8a5493acf50486e09e7e5389558adbfad9bf --- /dev/null +++ b/app/views/admin/education/program/roles/index.html.erb @@ -0,0 +1,6 @@ +<% content_for :title, University::Role.model_name.human(count: 2) %> +<%= render 'admin/education/program/roles/list', roles: @roles %> + +<% content_for :action_bar_right do %> + <%= link_to t('add'), new_admin_education_program_role_path(program_id: @program.id), class: button_classes if can? :create, University::Role %> +<% end %> diff --git a/app/views/admin/education/program/roles/new.html.erb b/app/views/admin/education/program/roles/new.html.erb index 1bad6fa6b7171dc693ea7eeb1652b264eca17d07..1e11d9157b4247984613930c39a66a5f5287ec23 100644 --- a/app/views/admin/education/program/roles/new.html.erb +++ b/app/views/admin/education/program/roles/new.html.erb @@ -1,3 +1,3 @@ -<% content_for :title, Education::Program::Role.model_name.human %> +<% content_for :title, University::Role.model_name.human %> <%= render 'form', role: @role %> diff --git a/app/views/admin/education/program/roles/show.html.erb b/app/views/admin/education/program/roles/show.html.erb index 09d1438bae5ebeb50909afb7c2d79e657036ada7..07f5ed11bf9bd060aaf62e01ae4852827611b5d0 100644 --- a/app/views/admin/education/program/roles/show.html.erb +++ b/app/views/admin/education/program/roles/show.html.erb @@ -1,32 +1,35 @@ <% content_for :title, @role %> -<div class="row"> - <div class="col-md-4"> - <div class="card flex-fill w-100"> - <div class="card-header"> - <h2 class="card-title mb-0 h5"><%= t('admin.infos') %></h2> - </div> - <div class="card-body"> - <h3 class="h5"><%= Education::Program::Role.human_attribute_name('title') %></h3> - <%= @role.title %> - </div> - </div> - </div> - <div class="col-md-8"> - <div class="card flex-fill w-100"> - <div class="card-header"> - <h2 class="card-title mb-0 h5"><%= Education::Program::Role.human_attribute_name('people') %></h2> - </div> - <div class="card-body"> - <%= render 'admin/education/program/role/people/list', people: @role.people.includes(:person).ordered %> - <% if can? :create, Education::Program::Role::Person %> - <p><%= link_to t('create'), new_admin_education_program_role_person_path(role_id: @role.id), class: 'btn btn-primary' %></p> +<% if @involvements.any? %> + <table class="table"> + <thead> + <tr> + <% if can? :reorder, University::Role %> + <th width="20" class="ps-0"> </th> <% end %> - </div> - </div> - </div> -</div> + <th class="ps-0"><%= University::Person.model_name.human %></th> + </tr> + </thead> + <tbody data-sortable data-sort-url="<%= reorder_admin_education_program_role_people_path(@role, { program_id: @program.id }) %>"> + <% @involvements.each do |involvement| %> + <tr data-id="<%= involvement.id %>"> + <% if can? :reorder, University::Role %> + <td><i class="fa fa-bars handle"></i></td> + <% end %> + <td class="ps-0"> + <%= link_to_if can?(:read, involvement.person), + involvement.person, + [:admin, involvement.person] %> + </td> + </tr> + <% end %> + </tbody> + </table> +<% end %> + <% content_for :action_bar_right do %> - <%= edit_link @role %> + <%= link_to t('edit'), + edit_admin_education_program_role_path(@role, { program_id: @program.id }), + class: button_classes if can?(:update, @role) %> <% end %> diff --git a/app/views/admin/education/program/teachers/_form.html.erb b/app/views/admin/education/program/teachers/_form.html.erb index 31950531cded62732c883007d24af5dd0f8a7685..b77505dfdb3e19597b8ccde8c8765dfaa5c4278a 100644 --- a/app/views/admin/education/program/teachers/_form.html.erb +++ b/app/views/admin/education/program/teachers/_form.html.erb @@ -1,4 +1,6 @@ -<%= simple_form_for [:admin, teacher] do |f| %> +<%= simple_form_for [:admin, involvement], + url: involvement.new_record? ? admin_education_program_teachers_path(@program) + : admin_education_program_teacher_path(involvement, { program_id: @program.id }) do |f| %> <div class="card flex-fill w-100"> <div class="card-header"> <h5 class="card-title mb-0"><%= t('admin.infos') %></h5> @@ -6,10 +8,10 @@ <div class="card-body"> <div class="row"> <div class="col-md-6"> - <%= f.association :person, collection: @teachers %> + <%= f.association :person, collection: @available_people %> </div> <div class="col-md-6"> - <%= f.input :description, as: :string %> + <%= f.input :description %> </div> </div> </div> diff --git a/app/views/admin/education/program/teachers/_list.html.erb b/app/views/admin/education/program/teachers/_list.html.erb index cc7d9c17b4e0f0bd685a4fc0525771250f30610f..2d7acf1dcdb15f68b4a35541726a5d16986d75d8 100644 --- a/app/views/admin/education/program/teachers/_list.html.erb +++ b/app/views/admin/education/program/teachers/_list.html.erb @@ -1,31 +1,29 @@ -<% if teachers.any? %> +<% if involvements.any? %> <table class="table"> <thead> <tr> - <th class="ps-0"><%= Education::Program::Teacher.model_name.human %></th> - <th><%= Education::Program::Teacher.human_attribute_name('description') %></th> + <th class="ps-0"><%= University::Person.model_name.human %></th> + <th><%= University::Person::Involvement.human_attribute_name('description') %></th> <th></th> </tr> </thead> <tbody> - <% teachers.each do |teacher| %> + <% involvements.each do |involvement| %> <tr> <td class="ps-0"> - <%= link_to_if can?(:read, teacher.person), - teacher.person, - admin_education_teacher_path(teacher.person) %> + <%= link_to_if can?(:read, involvement.person), involvement.person.to_s, admin_university_person_path(involvement.person) %> </td> - <td><%= teacher.description %></td> + <td><%= involvement.description %></td> <td class="text-end pe-0"> <div class="btn-group" role="group"> <%= link_to t('edit'), - edit_admin_education_program_teacher_path(teacher, { program_id: @program.id }), - class: button_classes if can? :update, teacher.person %> - <%= link_to t('delete'), - admin_education_program_teacher_path(teacher, { program_id: @program.id }), + edit_admin_education_program_teacher_path(involvement, { program_id: @program.id }), + class: button_classes if can?(:edit, involvement) %> + <%= link_to t('remove'), + admin_education_program_teacher_path(involvement, { program_id: @program.id }), method: :delete, data: { confirm: t('please_confirm') }, - class: button_classes_danger if can? :update, teacher.person %> + class: button_classes_danger if can?(:destroy, involvement) %> </div> </td> </tr> diff --git a/app/views/admin/education/program/teachers/edit.html.erb b/app/views/admin/education/program/teachers/edit.html.erb index b3f94ca300bb5361d5c000f96b377bd2bd76eb0e..da924cd052e14cfa55c1f75b9fe56ee8d15a1b8a 100644 --- a/app/views/admin/education/program/teachers/edit.html.erb +++ b/app/views/admin/education/program/teachers/edit.html.erb @@ -1,3 +1,3 @@ -<% content_for :title, @teacher %> +<% content_for :title, @involvement %> -<%= render 'form', teacher: @teacher %> +<%= render 'form', involvement: @involvement %> diff --git a/app/views/admin/education/program/teachers/index.html.erb b/app/views/admin/education/program/teachers/index.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..f37281009002c9944136ec4e9d76b43ee96b9d5c --- /dev/null +++ b/app/views/admin/education/program/teachers/index.html.erb @@ -0,0 +1,6 @@ +<% content_for :title, Education::Program.human_attribute_name("teachers") %> +<%= render 'admin/education/program/teachers/list', involvements: @involvements %> + +<% content_for :action_bar_right do %> + <%= link_to t('add'), new_admin_education_program_teacher_path(program_id: @program.id), class: button_classes %> +<% end %> diff --git a/app/views/admin/education/program/teachers/new.html.erb b/app/views/admin/education/program/teachers/new.html.erb index 1617fb343abe20477a921b1b7488d6ffaf546fa9..f07ff39c18ffb7d9e598688bb41a9361413d804f 100644 --- a/app/views/admin/education/program/teachers/new.html.erb +++ b/app/views/admin/education/program/teachers/new.html.erb @@ -1,3 +1,3 @@ -<% content_for :title, Education::Program::Teacher.model_name.human %> +<% content_for :title, University::Person.model_name.human %> -<%= render 'form', teacher: @teacher %> +<%= render 'form', involvement: @involvement %> diff --git a/app/views/admin/education/programs/_form.html.erb b/app/views/admin/education/programs/_form.html.erb index f930ef9bfe4761f01d51c994ae8cd99c8d29ea66..461c20397edabcdfe9e4465e00516fa02e001774 100644 --- a/app/views/admin/education/programs/_form.html.erb +++ b/app/views/admin/education/programs/_form.html.erb @@ -1,4 +1,4 @@ -<%= simple_nested_form_for [:admin, program] do |f| %> +<%= simple_form_for [:admin, program] do |f| %> <div class="row"> <div class="col-md-3"> <div class="card flex-fill w-100"> @@ -59,13 +59,33 @@ <%= f.input :featured_image_alt %> </div> </div> - <div class="card flex-fill w-100"> - <div class="card-header"> - <h5 class="card-title mb-0"><%= t('activerecord.attributes.education/program.team') %></h5> - </div> - <div class="card-body"> - <%= render 'admin/education/programs/forms/input_with_inheritance', f: f, property: :contacts %> - </div> + </div> + </div> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h5 class="card-title mb-0"><%= t('activerecord.attributes.education/program.team') %></h5> + </div> + <div class="card-body"> + <%= render 'admin/education/programs/forms/input_with_inheritance', f: f, property: :contacts %> + + <p><%= Education::Program.human_attribute_name('teachers') %></p> + <%= link_to_add_association t('add'), f, :university_person_involvements, + class: "btn btn-primary mb-3", + partial: 'admin/education/programs/involvement_fields', + data: { + 'association-insertion-method': 'append', + 'association-insertion-node': '#involvements', + } %> + + <div class="row mb-3" id="involvements"> + <% + sorted_involvements = program.university_person_involvements.sort_by { |involvement| + [involvement.person&.last_name, involvement.person&.first_name] + } + %> + <%= f.simple_fields_for :university_person_involvements, sorted_involvements, include_id: false do |involvement_f| %> + <%= render 'admin/education/programs/involvement_fields', f: involvement_f, include_id: true %> + <% end %> </div> </div> </div> diff --git a/app/views/admin/education/programs/_involvement_fields.html.erb b/app/views/admin/education/programs/_involvement_fields.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..08a3e0acc0b5d3db6f4edf28e1e7b9d3c8473036 --- /dev/null +++ b/app/views/admin/education/programs/_involvement_fields.html.erb @@ -0,0 +1,17 @@ +<% include_id ||= false %> +<div class="nested-fields col-md-3"> + <div class="card mb-2"> + <div class="card-body"> + <div class="row align-items-center"> + <div class="col-10"> + <%= f.association :person, collection: @teacher_people, label: false, include_blank: :translate, required: true %> + <%= f.input :description, label: false, placeholder: University::Person::Involvement.human_attribute_name('description'), wrapper: false %> + </div> + <div class="col-2"> + <%= link_to_remove_association '<i class="fas fa-trash"></i>'.html_safe, f, class: 'btn btn-sm btn-danger' %> + </div> + </div> + </div> + <%= f.hidden_field :id if include_id %> + </div> +</div> diff --git a/app/views/admin/education/programs/show.html.erb b/app/views/admin/education/programs/show.html.erb index 4ebd03b90caa3aa1586b5ea5b0ac6d798ec67e58..d6ef2d1ab04c6a560963ca2bb57040cf0e72bb42 100644 --- a/app/views/admin/education/programs/show.html.erb +++ b/app/views/admin/education/programs/show.html.erb @@ -121,14 +121,10 @@ <div class="card-body"> <div class="row"> <div class="col-md-6"> - <h3 class="h5"><%= Education::Program.human_attribute_name('roles') %></h3> - <%= render 'admin/education/program/roles/list', roles: @program.roles.ordered %> - <%= link_to t('create'), new_admin_education_program_role_path(program_id: @program.id), class: button_classes if can?(:create, Education::Program::Role) %> + <%= render 'admin/education/programs/show/roles', roles: @roles %> </div> <div class="col-md-6"> - <h3 class="h5"><%= Education::Program.human_attribute_name('teachers') %></h3> - <%= render 'admin/education/program/teachers/list', teachers: @program.teachers.includes(:person).ordered %> - <%= link_to t('create'), new_admin_education_program_teacher_path(program_id: @program.id), class: button_classes %> + <%= render 'admin/education/programs/show/teachers', involvements: @teacher_involvements %> </div> </div> </div> diff --git a/app/views/admin/education/programs/show/_roles.html.erb b/app/views/admin/education/programs/show/_roles.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..22c9ea57aca1e14b34a744456828eaba189b1861 --- /dev/null +++ b/app/views/admin/education/programs/show/_roles.html.erb @@ -0,0 +1,28 @@ +<div class="float-end"> + <%= link_to t('education.manage_roles'), + admin_education_program_roles_path(program_id: @program.id), + class: button_classes if can?(:update, University::Role) %> +</div> +<h3 class="h5"><%= Education::Program.human_attribute_name('roles') %></h3> +<% if @roles.any? %> + <table class="table"> + <thead> + <tr> + <th class="ps-0"><%= University::Role.model_name.human %></th> + <th><%= University::Role.human_attribute_name('people') %></th> + </tr> + </thead> + <tbody> + <% @roles.each do |role| %> + <tr> + <td class="ps-0"> + <%= link_to_if can?(:read, role), + role, + admin_education_program_role_path(role, { program_id: @program.id }) %> + </td> + <td><%= role.involvements.includes(:person).ordered.map { |involvement| link_to_if can?(:read, involvement.person), involvement.person.to_s, admin_university_person_path(involvement.person) }.to_sentence.html_safe %></td> + </tr> + <% end %> + </tbody> + </table> +<% end %> diff --git a/app/views/admin/education/programs/show/_teachers.html.erb b/app/views/admin/education/programs/show/_teachers.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..f32470ae7d2ca53fc6b160892f5e2ecad922f548 --- /dev/null +++ b/app/views/admin/education/programs/show/_teachers.html.erb @@ -0,0 +1,26 @@ +<div class="float-end"> + <%= link_to t('education.manage_teachers'), + admin_education_program_teachers_path(program_id: @program.id), + class: button_classes if can?(:update, University::Person::Involvement) %> +</div> +<h3 class="h5"><%= Education::Program.human_attribute_name('teachers') %></h3> +<% if @teacher_involvements.any? %> + <table class="table"> + <thead> + <tr> + <th class="ps-0"><%= University::Person.model_name.human %></th> + <th><%= University::Person::Involvement.human_attribute_name('description') %></th> + </tr> + </thead> + <tbody> + <% @teacher_involvements.each do |involvement| %> + <tr> + <td class="ps-0"> + <%= link_to_if can?(:read, involvement.person), involvement.person.to_s, admin_university_person_path(involvement.person) %> + </td> + <td><%= involvement.description %></td> + </tr> + <% end %> + </tbody> + </table> +<% end %> diff --git a/app/views/admin/education/programs/static.html.erb b/app/views/admin/education/programs/static.html.erb index 505c7a206bfa7aefb738391ca926a37e7660a1e7..4da9b86d49106a152435ff2b7316e0e022a3d806 100644 --- a/app/views/admin/education/programs/static.html.erb +++ b/app/views/admin/education/programs/static.html.erb @@ -1,4 +1,5 @@ --- +<% teacher_involvements = @program.university_person_involvements.includes(:person).ordered_by_name %> title: > <%= @program.name %> url: /<%= @website.static_pathname_programs %><%= @program.path %>/ @@ -11,23 +12,27 @@ image_alt: "<%= @program.featured_image_alt %>" <% end %> category: "<%= @website.categories.find_by(program_id: @program.id)&.path %>/" teachers: -<% @program.teachers.includes(:person).ordered.each do |teacher| %> - - "<%= teacher.person.slug %>" +<% teacher_involvements.each do |involvement| %> + - "<%= involvement.person.slug %>" <% end %> teachers_description: -<% @program.teachers.includes(:person).ordered.each do |teacher| %> - "<%= teacher.person.slug %>": > - <%= teacher.best_description %> +<% teacher_involvements.each do |involvement| %> + "<%= involvement.person.slug %>": > + <%= involvement.description %> <% end %> +<% if @program.university_roles.any? %> roles: -<% @program.roles.ordered.each do |role| %> +<% @program.university_roles.ordered.each do |role| %> - title: > <%= role.to_s %> persons: - <% role.people.includes(:person).ordered.each do |role_person| %> - - "<%= role_person.person.slug %>" + <% role.involvements.includes(:person).ordered.each do |involvement| %> + - "<%= involvement.person.slug %>" <% end %> <% end %> +<% else %> +roles: [] +<% end %> continuing: <%= @program.continuing %> level: <%= @program.level %> ects: <%= @program.ects %> diff --git a/app/views/admin/education/school/administrators/_form.html.erb b/app/views/admin/education/school/administrators/_form.html.erb deleted file mode 100644 index 42c01254a796ec1fad06fe563dd7ed2a07adac26..0000000000000000000000000000000000000000 --- a/app/views/admin/education/school/administrators/_form.html.erb +++ /dev/null @@ -1,21 +0,0 @@ -<%= simple_form_for [:admin, administrator] do |f| %> - <div class="card flex-fill w-100"> - <div class="card-header"> - <h5 class="card-title mb-0"><%= t('admin.infos') %></h5> - </div> - <div class="card-body"> - <div class="row"> - <div class="col-md-6"> - <% used_administrator_ids = @school.administrators.where.not(id: administrator.id).pluck(:person_id) %> - <%= f.association :person, collection: current_university.people.administration.where.not(id: used_administrator_ids).ordered %> - </div> - <div class="col-md-6"> - <%= f.input :description, as: :string %> - </div> - </div> - </div> - </div> - <% content_for :action_bar_right do %> - <%= submit f %> - <% end %> -<% end %> diff --git a/app/views/admin/education/school/administrators/_list.html.erb b/app/views/admin/education/school/administrators/_list.html.erb deleted file mode 100644 index 569c595ec8484f23a561d1d16fb4ac9aea34466b..0000000000000000000000000000000000000000 --- a/app/views/admin/education/school/administrators/_list.html.erb +++ /dev/null @@ -1,35 +0,0 @@ -<% if administrators.any? %> - <table class="table"> - <thead> - <tr> - <th class="ps-0"><%= Education::School::Administrator.model_name.human %></th> - <th><%= Education::School::Administrator.human_attribute_name('description') %></th> - <th></th> - </tr> - </thead> - <tbody> - <% administrators.each do |administrator| %> - <tr> - <td class="ps-0"> - <%= link_to_if can?(:read, administrator.person), - administrator.person, - admin_university_person_path(administrator.person) %> - </td> - <td><%= administrator.description %></td> - <td class="text-end pe-0"> - <div class="btn-group" role="group"> - <%= link_to t('edit'), - edit_admin_education_school_administrator_path(administrator, { school_id: @school.id }), - class: button_classes %> - <%= link_to t('delete'), - admin_education_school_administrator_path(administrator, { school_id: @school.id }), - method: :delete, - data: { confirm: t('please_confirm') }, - class: button_classes_danger %> - </div> - </td> - </tr> - <% end %> - </tbody> - </table> -<% end %> diff --git a/app/views/admin/education/school/administrators/edit.html.erb b/app/views/admin/education/school/administrators/edit.html.erb deleted file mode 100644 index d2a82994691505b7789cdf1252c47e02b635ad7c..0000000000000000000000000000000000000000 --- a/app/views/admin/education/school/administrators/edit.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -<% content_for :title, @administrator %> - -<%= render 'form', administrator: @administrator %> diff --git a/app/views/admin/education/school/administrators/new.html.erb b/app/views/admin/education/school/administrators/new.html.erb deleted file mode 100644 index 491f71583cc0b5c2f5be4abc2e892f093ad25d9e..0000000000000000000000000000000000000000 --- a/app/views/admin/education/school/administrators/new.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -<% content_for :title, Education::School::Administrator.model_name.human %> - -<%= render 'form', administrator: @administrator %> diff --git a/app/views/admin/education/school/roles/_form.html.erb b/app/views/admin/education/school/roles/_form.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..c5ef4a1c65b23b012228150fb597516195c798c5 --- /dev/null +++ b/app/views/admin/education/school/roles/_form.html.erb @@ -0,0 +1,40 @@ +<%= simple_form_for [:admin, role], + url: role.new_record? ? admin_education_school_roles_path(@school) + : admin_education_school_role_path(role, { school_id: @school.id }) do |f| %> + + <div class="row"> + <div class="col-md-8"> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h5 class="card-title mb-0"><%= t('admin.infos') %></h5> + </div> + <div class="card-body"> + <%= f.input :description %> + </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"><%= University::Person.model_name.human(count: 2) %></h5> + </div> + <div class="card-body"> + <%= link_to_add_association t('add'), f, :involvements, class: "btn btn-primary mb-3", data: { + 'association-insertion-method': 'append', + 'association-insertion-node': '#involvements' + } %> + + <div class="mb-3" id="involvements" data-sortable="inputs"> + <%= f.simple_fields_for :involvements, role.involvements.sort_by(&:position), include_id: false do |involvement_f| %> + <%= render 'admin/education/school/roles/involvement_fields', f: involvement_f, include_id: true %> + <% end %> + </div> + </div> + </div> + </div> + </div> + + <% content_for :action_bar_right do %> + <%= submit f %> + <% end %> +<% end %> diff --git a/app/views/admin/education/school/roles/_involvement_fields.html.erb b/app/views/admin/education/school/roles/_involvement_fields.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..0ce4a6118749b46cf3abc74eab502d958da82191 --- /dev/null +++ b/app/views/admin/education/school/roles/_involvement_fields.html.erb @@ -0,0 +1,18 @@ +<% include_id ||= false %> +<div class="card nested-fields mb-2"> + <div class="card-body"> + <div class="row align-items-center"> + <div class="col-1"> + <i class="fa fa-bars handle"></i> + </div> + <div class="col-9"> + <%= f.association :person, collection: @administration_people, label: false, include_blank: :translate, wrapper: false, required: true %> + </div> + <div class="col-2"> + <%= link_to_remove_association '<i class="fas fa-trash"></i>'.html_safe, f, class: 'btn btn-sm btn-danger' %> + </div> + </div> + </div> + <%= f.hidden_field :position, data: { 'sortable-input': '' } %> + <%= f.hidden_field :id if include_id %> +</div> diff --git a/app/views/admin/education/school/roles/_list.html.erb b/app/views/admin/education/school/roles/_list.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..5d694d93e0a80f5a2afa8c1e21fa0088ea619f47 --- /dev/null +++ b/app/views/admin/education/school/roles/_list.html.erb @@ -0,0 +1,41 @@ +<% if roles.any? %> + <table class="table"> + <thead> + <tr> + <% if can? :reorder, University::Role %> + <th width="20" class="ps-0"> </th> + <% end %> + <th class="ps-0"><%= University::Role.model_name.human %></th> + <th><%= University::Role.human_attribute_name('people') %></th> + <th></th> + </tr> + </thead> + <tbody data-sortable data-sort-url="<%= reorder_admin_education_school_roles_path(school_id: @school.id) %>"> + <% roles.each do |role| %> + <tr data-id="<%= role.id %>"> + <% if can? :reorder, University::Role %> + <td><i class="fa fa-bars handle"></i></td> + <% end %> + <td class="ps-0"> + <%= link_to_if can?(:read, role), + role, + admin_education_school_role_path(role, { school_id: @school.id }) %> + </td> + <td><%= role.involvements.includes(:person).ordered.map { |involvement| involvement.person.to_s }.to_sentence %></td> + <td class="text-end pe-0"> + <div class="btn-group" role="group"> + <%= link_to t('edit'), + edit_admin_education_school_role_path(role, { school_id: @school.id }), + class: button_classes if can?(:edit, role) %> + <%= link_to t('delete'), + admin_education_school_role_path(role, { school_id: @school.id }), + method: :delete, + data: { confirm: t('please_confirm') }, + class: button_classes_danger if can?(:destroy, role) %> + </div> + </td> + </tr> + <% end %> + </tbody> + </table> +<% end %> diff --git a/app/views/admin/education/school/roles/edit.html.erb b/app/views/admin/education/school/roles/edit.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..ff1ec73bd6f1465a96497606080d481b6fd6ca51 --- /dev/null +++ b/app/views/admin/education/school/roles/edit.html.erb @@ -0,0 +1,3 @@ +<% content_for :title, @role %> + +<%= render 'form', role: @role %> diff --git a/app/views/admin/education/school/roles/index.html.erb b/app/views/admin/education/school/roles/index.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..169795ed215ab55d5484cbc72e0affb3662fd532 --- /dev/null +++ b/app/views/admin/education/school/roles/index.html.erb @@ -0,0 +1,6 @@ +<% content_for :title, Education::School.human_attribute_name('roles') %> +<%= render 'admin/education/school/roles/list', roles: @roles %> + +<% content_for :action_bar_right do %> + <%= link_to t('add'), new_admin_education_school_role_path(school_id: @school.id), class: button_classes if can? :create, University::Role %> +<% end %> diff --git a/app/views/admin/education/school/roles/new.html.erb b/app/views/admin/education/school/roles/new.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..1e11d9157b4247984613930c39a66a5f5287ec23 --- /dev/null +++ b/app/views/admin/education/school/roles/new.html.erb @@ -0,0 +1,3 @@ +<% content_for :title, University::Role.model_name.human %> + +<%= render 'form', role: @role %> diff --git a/app/views/admin/education/school/roles/show.html.erb b/app/views/admin/education/school/roles/show.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..05b170d15700dd54ece0ef3813a9a97763a0b3d3 --- /dev/null +++ b/app/views/admin/education/school/roles/show.html.erb @@ -0,0 +1,35 @@ +<% content_for :title, @role %> + +<% if @involvements.any? %> + <table class="table"> + <thead> + <tr> + <% if can? :reorder, University::Person::Involvement %> + <th width="20" class="ps-0"> </th> + <% end %> + <th class="ps-0"><%= University::Person.model_name.human %></th> + </tr> + </thead> + <tbody data-sortable data-sort-url="<%= reorder_admin_education_school_role_people_path(@role, { school_id: @school.id }) %>"> + <% @involvements.each do |involvement| %> + <tr data-id="<%= involvement.id %>"> + <% if can? :reorder, University::Person::Involvement %> + <td><i class="fa fa-bars handle"></i></td> + <% end %> + <td class="ps-0"> + <%= link_to_if can?(:read, involvement.person), + involvement.person, + [:admin, involvement.person] %> + </td> + </tr> + <% end %> + </tbody> + </table> +<% end %> + + +<% content_for :action_bar_right do %> + <%= link_to t('edit'), + edit_admin_education_school_role_path(@role, { school_id: @school.id }), + class: button_classes if can?(:update, @role) %> +<% end %> diff --git a/app/views/admin/education/schools/show.html.erb b/app/views/admin/education/schools/show.html.erb index 5367e4558ab1221f8c894ae179fcc1a437f85a94..2bd93a35f76d5ae1e23836e4b513b10860d460f5 100644 --- a/app/views/admin/education/schools/show.html.erb +++ b/app/views/admin/education/schools/show.html.erb @@ -56,15 +56,7 @@ </div> -<div class="card flex-fill w-100"> - <div class="card-header"> - <h2 class="card-title mb-0 h5"><%= Education::School.human_attribute_name('administrators') %></h2> - </div> - <div class="card-body"> - <%= render 'admin/education/school/administrators/list', administrators: @school.administrators.includes(:person).ordered %> - <%= link_to t('create'), new_admin_education_school_administrator_path(school_id: @school.id), class: button_classes %> - </div> -</div> +<%= render 'admin/education/schools/show/roles', roles: @roles %> <% content_for :action_bar_right do %> <%= edit_link @school %> diff --git a/app/views/admin/education/schools/show/_roles.html.erb b/app/views/admin/education/schools/show/_roles.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..c76b6046d3d5ef9a71cbbf3b58749e0dd0640aa5 --- /dev/null +++ b/app/views/admin/education/schools/show/_roles.html.erb @@ -0,0 +1,40 @@ +<div class="card flex-fill w-100"> + <div class="card-header"> + <div class="float-end"> + <%= link_to t('education.schools.manage_roles'), + admin_education_school_roles_path(school_id: @school.id), + class: button_classes if can?(:update, University::Role) %> + </div> + <h2 class="card-title mb-0 h5"><%= Education::School.human_attribute_name('roles') %></h2> + </div> + <div class="card-body"> + <% if @roles.any? %> + <table class="table"> + <thead> + <tr> + <th class="ps-0"><%= University::Role.model_name.human %></th> + <th><%= University::Role.human_attribute_name('people') %></th> + </tr> + </thead> + <tbody> + <% roles.each do |role| %> + <tr> + <td class="ps-0"> + <%= link_to_if can?(:read, role), + role, + edit_admin_education_school_role_path(role, { school_id: @school.id }) %> + </td> + <td> + <ul> + <% role.involvements.includes(:person).ordered.each do |involvement| %> + <li><%= link_to_if can?(:read, involvement.person), involvement.person.to_s, admin_university_person_path(involvement.person) %></li> + <% end %> + </ul> + </td> + </tr> + <% end %> + </tbody> + </table> + <% end %> + </div> +</div> diff --git a/app/views/admin/education/schools/static.html.erb b/app/views/admin/education/schools/static.html.erb index 800d8c5b1c974e925f1adff080b1b4a7a612fbbe..a0afec14d317ea794c1c1de5ea7e94dd25aa5d04 100644 --- a/app/views/admin/education/schools/static.html.erb +++ b/app/views/admin/education/schools/static.html.erb @@ -11,13 +11,17 @@ country: > <%= ISO3166::Country[@school.country].translations[@school.country.downcase] %> phone: > <%= @school.phone %> -administrators: -<% @school.administrators.includes(:person).ordered.each do |administrator| %> - - "<%= administrator.person.slug %>" +<% if @school.university_roles.any? %> +roles: +<% @school.university_roles.ordered.each do |role| %> + - title: > + <%= role.to_s %> + persons: + <% role.involvements.includes(:person).ordered.each do |involvement| %> + - "<%= involvement.person.slug %>" + <% end %> <% end %> -administrators_description: -<% @school.administrators.includes(:person).ordered.each do |administrator| %> - "<%= administrator.person.slug %>": > - <%= administrator.best_description %> +<% else %> +roles: [] <% end %> --- diff --git a/app/views/admin/education/teachers/_involvement_fields.html.erb b/app/views/admin/education/teachers/_involvement_fields.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..b53edeec8ee8d608a5150c0934b3688ef3eba77a --- /dev/null +++ b/app/views/admin/education/teachers/_involvement_fields.html.erb @@ -0,0 +1,24 @@ +<% include_id ||= false %> +<div class="nested-fields col-md-4"> + <div class="card mb-2"> + <div class="card-body"> + <div class="row align-items-center"> + <div class="col-10"> + <%= f.hidden_field :target_type, value: "Education::Program" %> + <%= f.association :target, + collection: collection_tree(current_university.education_programs), + label_method: ->(p) { sanitize p[:label] }, + value_method: ->(p) { p[:id] }, + label: false, + include_blank: t('simple_form.include_blanks.defaults.program'), + required: true %> + <%= f.input :description, label: false, placeholder: University::Person::Involvement.human_attribute_name('description'), wrapper: false %> + </div> + <div class="col-2"> + <%= link_to_remove_association '<i class="fas fa-trash"></i>'.html_safe, f, class: 'btn btn-sm btn-danger' %> + </div> + </div> + </div> + <%= f.hidden_field :id if include_id %> + </div> +</div> diff --git a/app/views/admin/education/teachers/edit.html.erb b/app/views/admin/education/teachers/edit.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..769b9ea4c9bf132a798d30c94e4793a829f28f67 --- /dev/null +++ b/app/views/admin/education/teachers/edit.html.erb @@ -0,0 +1,28 @@ +<% content_for :title, @teacher %> + +<%= simple_form_for [:admin, @teacher], url: admin_education_teacher_path(@teacher) do |f| %> + <div class="card flex-fill w-100"> + <div class="card-header"> + <h5 class="card-title mb-0"><%= Education::Program.model_name.human(count: 2) %></h5> + </div> + <div class="card-body"> + <%= link_to_add_association t('add'), f, :involvements, + class: "btn btn-primary mb-3", + data: { + 'association-insertion-method': 'append', + 'association-insertion-node': '#involvements', + } %> + + <div class="row mb-3" id="involvements"> + <% sorted_teacher_involvements = @teacher.involvements.select(&:teacher?).sort_by { |involvement| involvement.created_at || Time.zone.now } %> + <%= f.simple_fields_for :involvements, sorted_teacher_involvements, include_id: false do |involvement_f| %> + <%= render 'admin/education/teachers/involvement_fields', f: involvement_f, include_id: true %> + <% end %> + </div> + </div> + </div> + + <% content_for :action_bar_right do %> + <%= submit f %> + <% end %> +<% end %> diff --git a/app/views/admin/education/teachers/show.html.erb b/app/views/admin/education/teachers/show.html.erb index cfb4ef8e703ce264403458eb27c93628101da575..6430d8c3dc9350b6fb602c64a68e51ab653fc321 100644 --- a/app/views/admin/education/teachers/show.html.erb +++ b/app/views/admin/education/teachers/show.html.erb @@ -2,21 +2,47 @@ <%= render 'admin/university/people/main_infos', person: @teacher %> - -<% if @programs.total_count > 0 %> +<% if @involvements.total_count > 0 %> <div class="card"> <div class="card-header"> - <h2 class="card-title mb-0 h5"><%= "#{Education::Program.model_name.human(count: 2)} (#{@programs.total_count})" %></h2> + <h2 class="card-title mb-0 h5"><%= "#{Education::Program.model_name.human(count: 2)} (#{@involvements.total_count})" %></h2> </div> - <%= render 'admin/education/programs/list', programs: @programs %> - <% if @programs.total_pages > 1 %> + <table class="table"> + <thead> + <tr> + <th><%= Education::Program.model_name.human %></th> + <th><%= Education::Program.human_attribute_name('level') %></th> + <th><%= University::Person::Involvement.human_attribute_name('description') %></th> + <th></th> + </tr> + </thead> + <tbody> + <% @involvements.each do |involvement| %> + <% program = involvement.target %> + <tr> + <td><%= link_to_if can?(:read, program), program, [:admin, program] %></td> + <td><%= program.level_i18n %></td> + <td><%= involvement.description %></td> + <td class="text-end"> + <%= link_to t('quit'), + admin_education_program_teacher_path(involvement, { program_id: program.id }), + method: :delete, + data: { confirm: t('please_confirm') }, + class: button_classes_danger if can?(:destroy, involvement) %> + </td> + </tr> + <% end %> + </tbody> + </table> + + <% if @involvements.total_pages > 1 %> <div class="card-footer"> - <%= paginate @programs, theme: 'bootstrap-5' %> + <%= paginate @involvements, theme: 'bootstrap-5' %> </div> <% end %> </div> <% end %> <% content_for :action_bar_right do %> - <%#= link_to t('edit'), edit_admin_education_teacher_path(@teacher), class: button_classes if can?(:edit, Education::Program) %> + <%= link_to t('education.manage_programs'), edit_admin_education_teacher_path(@teacher), class: button_classes if can?(:manage, University::Person::Involvement) %> <% end %> diff --git a/app/views/admin/research/journal/volumes/show.html.erb b/app/views/admin/research/journal/volumes/show.html.erb index da93defb44dc656924bfa7525c335a8b5b387732..d485e48b49840e135c31b7378a6aaf68f10abe82 100644 --- a/app/views/admin/research/journal/volumes/show.html.erb +++ b/app/views/admin/research/journal/volumes/show.html.erb @@ -11,17 +11,23 @@ <p><%= @volume.description %></p> <% if @articles.any? %> <h3 class="h5 mt-4"><%= Research::Journal::Volume.human_attribute_name('articles') %></h3> - <table class="table table-sortable"> + <table class="table"> <thead> <tr> - <th><%= Research::Journal::Article.model_name.human %></th> + <% if can? :reorder, Research::Journal::Article %> + <th width="20" class="ps-0"> </th> + <% end %> + <th class="ps-0"><%= Research::Journal::Article.model_name.human %></th> <th><%= Research::Journal::Article.human_attribute_name('published_at') %></th> <th></th> </tr> </thead> - <tbody data-reorder-url="<%= reorder_admin_research_journal_articles_path(journal_id: @journal.id) %>"> + <tbody data-sortable data-sort-url="<%= reorder_admin_research_journal_articles_path(journal_id: @journal.id) %>"> <% @articles.each do |article| %> - <tr class="handle" data-id="<%= article.id %>"> + <tr data-id="<%= article.id %>"> + <% if can? :reorder, Research::Journal::Article %> + <td><i class="fa fa-bars handle"></i></td> + <% end %> <td> <%= link_to article, admin_research_journal_article_path(journal_id: article.journal, id: article), diff --git a/app/views/admin/research/laboratory/axes/_list.html.erb b/app/views/admin/research/laboratory/axes/_list.html.erb index baf2e27f8c1f5365eb765453cbe898a151f12ad9..f9df418ab25be326c44cc61fbb9fc7d6fd69f149 100644 --- a/app/views/admin/research/laboratory/axes/_list.html.erb +++ b/app/views/admin/research/laboratory/axes/_list.html.erb @@ -1,14 +1,20 @@ -<table class="table table-sortable"> +<table class="table"> <thead> <tr> + <% if can? :reorder, Research::Laboratory::Axis %> + <th width="20" class="ps-0"> </th> + <% end %> <th><%= Research::Laboratory::Axis.model_name.human %></th> <th><%= Research::Laboratory::Axis.human_attribute_name('short_name') %></th> <th></th> </tr> </thead> - <tbody data-reorder-url="<%= reorder_admin_research_laboratory_axes_path(laboratory_id: @laboratory.id) %>"> + <tbody data-sortable data-sort-url="<%= reorder_admin_research_laboratory_axes_path(laboratory_id: @laboratory.id) %>"> <% axes.each do |axis| %> - <tr class="handle" data-id="<%= axis.id %>"> + <tr data-id="<%= axis.id %>"> + <% if can? :reorder, Research::Laboratory::Axis %> + <td><i class="fa fa-bars handle"></i></td> + <% end %> <td> <%= link_to axis, admin_research_laboratory_axis_path(laboratory_id: axis.laboratory, id: axis) %> </td> diff --git a/app/views/admin/university/people/_list.html.erb b/app/views/admin/university/people/_list.html.erb index d7e02ab29da8cc88bb5114d27ac171594ccad2c1..6218535649f66a8a1b6d70ac749c2b2e49534087 100644 --- a/app/views/admin/university/people/_list.html.erb +++ b/app/views/admin/university/people/_list.html.erb @@ -15,12 +15,12 @@ <div class="btn-group" role="group"> <%= link_to t('edit'), edit_admin_university_person_path(person), - class: button_classes %> + class: button_classes if can?(:update, person) %> <%= link_to t('delete'), admin_university_person_path(person), method: :delete, data: { confirm: t('please_confirm') }, - class: button_classes_danger %> + class: button_classes_danger if can?(:destroy, person) %> </div> </td> </tr> diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index 17a26328ee8d1cc5f44a9411d93506b626c158d0..f8850cffd8c2093a9464d6f321d53e2f027b90b3 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -18,7 +18,7 @@ <%= f.association :language, required: true, label_method: lambda { |l| t("languages.#{l.iso_code.to_s}") }, - include_blank: t('select_language') %> + include_blank: :translate %> </div> <div class="col-md-6"> <%= f.input :password, diff --git a/app/views/server/dashboard/index.html.erb b/app/views/server/dashboard/index.html.erb index a537f930ac782da272e191983be28430d3b16851..7cda9c12f2349d1f56b17184ded3ecdb3e0a6133 100644 --- a/app/views/server/dashboard/index.html.erb +++ b/app/views/server/dashboard/index.html.erb @@ -1 +1 @@ -<% content_for :title, "Bonjour #{ current_user.first_name }!" %> +<% content_for :title, t('hello', name: current_user.first_name) %> diff --git a/config/locales/education/en.yml b/config/locales/education/en.yml index 011a5cad49bc54f2f9701b567a679a3ce3584654..ae65263548c98696aba87606c29fe3ca777d5556 100644 --- a/config/locales/education/en.yml +++ b/config/locales/education/en.yml @@ -7,21 +7,9 @@ en: education/program: one: Program other: Programs - education/program/role: - one: Role - other: Roles - education/program/role/person: - one: Person - other: People - education/program/teacher: - one: Teacher - other: Teachers education/school: one: School other: Schools - education/school/administrator: - one: Administrator - other: Administrators attributes: education/program: accessibility: Accessibilité @@ -48,14 +36,8 @@ en: schools: Schools with this formation teachers: Teachers team: Team - education/program/role: - people: People - title: Title - education/program/role/person: - person: Person - education/program/teacher: - description: Description - person: Person + content: Program's content + results: Results' indicator education/school: address: Address administrators: Administrators @@ -64,18 +46,23 @@ en: name: Name phone: Phone programs: Programs provided + roles: Team Members websites: Associated websites zipcode: Zipcode - education/school/administrator: - description: Description - person: Person education: + manage_programs: Manage programs + manage_roles: Manage roles manage_teachers: Manage teachers number_of_programs: Number of programs program: educational_informations: Educational informations main_informations: Main informations useful_informations: Useful informations + roles: + one: Role + other: Roles + schools: + manage_roles: Manage the team teachers: one: Teacher other: Teachers diff --git a/config/locales/education/fr.yml b/config/locales/education/fr.yml index 334e2e464512a0ccc317e0c44689f3bc1a614446..132a500f74d4fad39917ed6aa0411102450e92bf 100644 --- a/config/locales/education/fr.yml +++ b/config/locales/education/fr.yml @@ -7,21 +7,9 @@ fr: education/program: one: Formation other: Formations - education/program/role: - one: Rôle - other: Rôles - education/program/role/person: - one: Personne - other: Personnes - education/program/teacher: - one: Enseignant·e - other: Enseignants·es education/school: one: École other: Écoles - education/school/administrator: - one: Équipe administrative - other: Équipe administrative attributes: education/program: accessibility: Accessibilité @@ -50,14 +38,6 @@ fr: team: Équipe content: Contenus de la formation results: Indicateurs de résultats - education/program/role: - people: Personnes - title: Titre - education/program/role/person: - person: Personne - education/program/teacher: - description: Description - person: Personne education/school: address: Adresse administrators: Équipe administrative @@ -66,13 +46,13 @@ fr: name: Nom phone: Téléphone programs: Formations dispensées + roles: Membres de l'équipe websites: Sites webs associés zipcode: Code postal - education/school/administrator: - description: Description - person: Personne education: - manage_teachers: Gérer les Enseignants·es + manage_programs: Gérer les formations + manage_roles: Gérer les rôles + manage_teachers: Gérer les enseignants·es number_of_programs: Nombre de formations program: educational_informations: Informations pédagogiques @@ -81,6 +61,8 @@ fr: roles: one: Rôle other: Rôles + schools: + manage_roles: Gérer l'équipe teachers: one: Enseignant·e other: Enseignants·es diff --git a/config/locales/en.yml b/config/locales/en.yml index c692b52c30b57506cce0168e7d49cf8a83b99efe..06e4495933c11bbc3086c5105dda897b6d7d5e47 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -32,6 +32,7 @@ en: user: one: User other: Users + add: Add admin: attachment_not_available: Attachment not available dashboard: Dashboard @@ -42,6 +43,7 @@ en: password_hint: Leave blank if you do not wish to change the password. successfully_created_html: "<i>%{model}</i> was successfully created." successfully_destroyed_html: "<i>%{model}</i> was successfully destroyed." + successfully_quit_html: "<i>%{model}</i> successfully quit <i>%{target}</i>." successfully_updated_html: "<i>%{model}</i> was successfully updated." users_alerts: not_locked_html: '<i>%{model}</i> was not locked.' @@ -86,6 +88,7 @@ en: false: No gdpr: privacy_policy: https://osuny.org/politique-de-confidentialite + hello: "Hello %{name}!" home: Home languages: en: English @@ -106,6 +109,8 @@ en: please_confirm_with_children: "WARNING: deleting this element will also remove every child. Are you sure?" privacy_policy: Privacy policy privacy_policy_url: https://osuny.org/politique-de-confidentialite + quit: Quit + remove: Remove save: Save select_language: Select language simple_form: @@ -114,6 +119,11 @@ en: hints: user: mobile_phone: "International format (+XX). By filling this field, you accept to receive your two-factor authentication codes via SMS." + include_blanks: + defaults: + language: "Select a language" + person: "Select a person" + program: "Select a program" simple_form_password_with_hints: test_chars: "%{min_length} characters min." show: Show @@ -127,3 +137,10 @@ en: date_with_hour: "%B %d, %Y %H:%M" true: Yes validate: Validate + views: + pagination: + first: "« First" + last: "Last »" + previous: "‹ Previous" + next: "Next ›" + truncate: "…" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 768f6224d7e927bcbf8074ed9592f72993c6cc91..a9e297ee7b7d1a3176669eac3eb90c09c82a983f 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -32,6 +32,7 @@ fr: user: one: Utilisateur·rice other: Utilisateur·rice·s + add: Ajouter admin: attachment_not_available: Impossible d'accéder à l'élément dashboard: Tableau de bord @@ -42,6 +43,7 @@ fr: password_hint: Laissez vide si vous ne souhaitez pas modifier le mot de passe. successfully_created_html: "<i>%{model}</i> a bien été créé(e)." successfully_destroyed_html: "<i>%{model}</i> a bien été détruit(e)." + successfully_quit_html: "<i>%{model}</i> a bien quitté <i>%{target}</i>." successfully_updated_html: "<i>%{model}</i> a bien été mis(e) à jour." users_alerts: not_locked_html: "<i>%{model}</i> n'était pas verrouillé(e)." @@ -86,6 +88,7 @@ fr: false: Non gdpr: privacy_policy: https://osuny.org/politique-de-confidentialite + hello: "Bonjour %{name} !" home: Accueil languages: en: Anglais @@ -106,6 +109,8 @@ fr: please_confirm_with_children: "ATTENTION : effacer cet élément supprimera aussi tous ses enfants. Est-ce que vous confirmez ?" privacy_policy: Politique de confidentialité privacy_policy_url: https://osuny.org/politique-de-confidentialite + quit: Quitter + remove: Retirer save: Enregistrer select_language: Sélectionnez une langue simple_form: @@ -114,6 +119,11 @@ fr: hints: user: mobile_phone: "Format international (+XX). En renseignant ce champ, vous acceptez de recevoir vos codes de double authentification par SMS." + include_blanks: + defaults: + language: "Sélectionnez une langue" + person: "Sélectionnez une personne" + program: "Sélectionnez une formation" simple_form_password_with_hints: test_chars: "%{min_length} caractères min." show: Voir diff --git a/config/locales/university/en.yml b/config/locales/university/en.yml index 8d690dbb687aa5dd1691327ed3ba5c9e9de97061..2a332ee980a066fc29d622f280313f73ae96769b 100644 --- a/config/locales/university/en.yml +++ b/config/locales/university/en.yml @@ -35,6 +35,12 @@ en: slug: Slug tenure: Have tenure? user: User + university/person/involvement: + person: Person + target_id: '' + university/role: + description: Description + people: People models: university: one: University @@ -42,6 +48,12 @@ en: university/person: one: Person other: People + university/person/involvement: + one: Involvement + other: Involvements + university/role: + one: Role + other: Roles simple_form: hints: university: diff --git a/config/locales/university/fr.yml b/config/locales/university/fr.yml index d40b74e837c1e021fdc7e0d26fce0c6da9046248..5bb3fa4fee399807288e31ce3aaf81d4a5049756 100644 --- a/config/locales/university/fr.yml +++ b/config/locales/university/fr.yml @@ -35,6 +35,12 @@ fr: slug: Slug tenure: Titulaire ? user: Utilisateur + university/person/involvement: + person: Personne + target_id: '' + university/role: + description: Description + people: Personnes models: university: one: Université @@ -42,6 +48,12 @@ fr: university/person: one: Personne other: Personnes + university/person/involvement: + one: Involvement + other: Involvements + university/role: + one: Rôle + other: Rôles simple_form: hints: university: diff --git a/config/routes/admin/education.rb b/config/routes/admin/education.rb index c3ac5899ec1bdaae385534f3d240cf8716955689..082e5da5115944aa3f89b82cf255f5a27108d410 100644 --- a/config/routes/admin/education.rb +++ b/config/routes/admin/education.rb @@ -1,21 +1,29 @@ namespace :education do - resources :teachers, only: [:index, :show] + resources :teachers, only: [:index, :show, :edit, :update] resources :schools do - resources :administrators, controller: 'school/administrators', except: [:index, :show] + resources :roles, controller: 'school/roles' do + resources :people, controller: 'school/role/people', only: [] do + post :reorder, on: :collection + end + collection do + post :reorder + end + end end resources :programs do - resources :roles, controller: 'program/roles', except: :index do - resources :people, controller: 'program/role/people', except: [:index, :show, :edit, :update] do - collection do - post :reorder - end + resources :roles, controller: 'program/roles' do + resources :people, controller: 'program/role/people', only: [] do + post :reorder, on: :collection end - collection do post :reorder end end - resources :teachers, controller: 'program/teachers', except: [:index, :show] + resources :teachers, controller: 'program/teachers', except: :show do + collection do + post :reorder + end + end collection do post :reorder end diff --git a/db/migrate/20220128111528_remove_legacy_education_models.rb b/db/migrate/20220128111528_remove_legacy_education_models.rb new file mode 100644 index 0000000000000000000000000000000000000000..0ba2a7369cd30e58793dfd3f96d972c314a74733 --- /dev/null +++ b/db/migrate/20220128111528_remove_legacy_education_models.rb @@ -0,0 +1,8 @@ +class RemoveLegacyEducationModels < ActiveRecord::Migration[6.1] + def change + drop_table :education_school_administrators + drop_table :education_program_teachers + drop_table :education_program_role_people + drop_table :education_program_roles + end +end diff --git a/db/migrate/20220131163458_change_research_journal_volume_published_type.rb b/db/migrate/20220131163458_change_research_journal_volume_published_type.rb new file mode 100644 index 0000000000000000000000000000000000000000..6ac77d3639f17b38a7d172c46b1fe2ee17b6fd2d --- /dev/null +++ b/db/migrate/20220131163458_change_research_journal_volume_published_type.rb @@ -0,0 +1,5 @@ +class ChangeResearchJournalVolumePublishedType < ActiveRecord::Migration[6.1] + def change + change_column :research_journal_volumes, :published_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index fa449131e30109e0ca6ac24b1b24c9cfe0fd42d8..c2d823d76cade935dd6213bf06ead3cf8d8c8a28 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: 2022_01_24_165229) do +ActiveRecord::Schema.define(version: 2022_01_31_163458) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" @@ -352,37 +352,6 @@ ActiveRecord::Schema.define(version: 2022_01_24_165229) do t.index ["priority", "run_at"], name: "delayed_jobs_priority" end - create_table "education_program_role_people", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.integer "position" - t.uuid "person_id", null: false - t.uuid "role_id", null: false - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["person_id"], name: "index_education_program_role_people_on_person_id" - t.index ["role_id"], name: "index_education_program_role_people_on_role_id" - end - - create_table "education_program_roles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.string "title" - t.integer "position" - t.uuid "program_id", null: false - t.uuid "university_id", null: false - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["program_id"], name: "index_education_program_roles_on_program_id" - t.index ["university_id"], name: "index_education_program_roles_on_university_id" - end - - create_table "education_program_teachers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.text "description" - t.uuid "program_id", null: false - t.uuid "person_id", null: false - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["person_id"], name: "index_education_program_teachers_on_person_id" - t.index ["program_id"], name: "index_education_program_teachers_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" @@ -410,16 +379,6 @@ ActiveRecord::Schema.define(version: 2022_01_24_165229) do t.index ["education_school_id", "education_program_id"], name: "school_program" end - create_table "education_school_administrators", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.text "description" - t.uuid "school_id", null: false - t.uuid "person_id", null: false - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["person_id"], name: "index_education_school_administrators_on_person_id" - t.index ["school_id"], name: "index_education_school_administrators_on_school_id" - end - create_table "education_schools", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "name" @@ -476,7 +435,7 @@ ActiveRecord::Schema.define(version: 2022_01_24_165229) do t.uuid "research_journal_id", null: false t.string "title" t.integer "number" - t.date "published_at" + t.datetime "published_at" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.text "description" @@ -690,16 +649,8 @@ ActiveRecord::Schema.define(version: 2022_01_24_165229) do add_foreign_key "communication_website_posts", "universities" add_foreign_key "communication_website_posts", "university_people", column: "author_id" add_foreign_key "communication_websites", "universities" - add_foreign_key "education_program_role_people", "education_program_roles", column: "role_id" - add_foreign_key "education_program_role_people", "university_people", column: "person_id" - add_foreign_key "education_program_roles", "education_programs", column: "program_id" - add_foreign_key "education_program_roles", "universities" - add_foreign_key "education_program_teachers", "education_programs", column: "program_id" - add_foreign_key "education_program_teachers", "university_people", column: "person_id" add_foreign_key "education_programs", "education_programs", column: "parent_id" add_foreign_key "education_programs", "universities" - add_foreign_key "education_school_administrators", "education_schools", column: "school_id" - add_foreign_key "education_school_administrators", "university_people", column: "person_id" add_foreign_key "education_schools", "universities" add_foreign_key "research_journal_articles", "research_journal_volumes" add_foreign_key "research_journal_articles", "research_journals" diff --git a/docs/communication/websites/export.md b/docs/communication/websites/export.md index 5f0b61974f450f1637bce05eed426f9bb89897a1..bdabcff060960c773df6e5f0added753578385db 100644 --- a/docs/communication/websites/export.md +++ b/docs/communication/websites/export.md @@ -15,6 +15,27 @@ Les fichiers renommés doivent être déplacés sur git. Les fichiers supprimés ou dépubliés doivent être supprimés sur git. Il faut veiller à limiter le nombre de commits et à éviter les commits vides. +## Setup + +### GitHub + +- Créer un repository à partir du template suivant : https://github.com/noesya/osuny-hugo-template +- Une fois le repository créé, générer un personal access token ici : https://github.com/settings/tokens + - Permission à accorder : `repo` + - Durée : pour une bonne sécurité, il n'est pas recommandé de créer un token permanent, notez simplement qu'il faut le régénérer réguilièrement. +- Copier le personnal access token +- Dans le back-office d'Osuny, créer ou modifier un website et renseignez les 2 champs relatifs à Git : + - Repository : `username/repo` + - Access token : `ghp_xxxxxxxxxxxxxxxxxxxx` + +### Déploiement (Netlify) + +La récupération du thème se fait via SSH par défaut. Pour que le déploiement fonctionne correctement, vous pouvez : +- Changer le remote du submodule pour qu'il utilise HTTPS. +- Garder le SSH, cependant il faut : + - Générer et copier la deploy key du site sur Netlify (dans "Site settings", "Build & deploy" puis "Deploy key"). + - L'ajouter dans la section "Deploy keys" du repository contenant le thème (ici : https://github.com/noesya/osuny-hugo-theme/settings/keys). + ## Architecture Les git::providers permettent de dialoguer avec les services comme Github et Gitlab. diff --git a/lib/tasks/app.rake b/lib/tasks/app.rake index 0e862f5d679e6e5f6ed78b930a645e03915d1316..7882b1afab2410acebdea1bb686e865848ba5751 100644 --- a/lib/tasks/app.rake +++ b/lib/tasks/app.rake @@ -40,50 +40,6 @@ namespace :app do imported_post.post&.update_column :published_at, imported_post.published_at end end - - Education::Program::Teacher.find_each { |teacher| - involvement = University::Person::Involvement.where( - kind: 'teacher', - target: teacher.program, - person_id: teacher.person_id, - university_id: teacher.person.university_id - ).first_or_create - involvement.update_column(:description, teacher.description) - } - - Education::Program::Role.find_each { |program_role| - university_role = University::Role.where( - description: program_role.description, - target: program_role.program, - position: program_role.position, - university_id: program_role.university_id - ).first_or_create - - program_role.people.find_each { |role_person| - University::Person::Involvement.where( - kind: 'administrator', - target: university_role, - person_id: role_person.person_id, - position: role_person.position, - university_id: program_role.university_id - ).first_or_create - } - } - - Education::School::Administrator.find_each { |administrator| - university_role = University::Role.where( - description: administrator.description, - target: administrator.school, - university_id: administrator.person.university_id - ).first_or_create - - University::Person::Involvement.where( - kind: 'administrator', - target: university_role, - person_id: administrator.person_id, - university_id: administrator.person.university_id - ).first_or_create - } end namespace :db do