diff --git a/app/controllers/admin/university/alumni/cohorts_controller.rb b/app/controllers/admin/university/alumni/cohorts_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..d58acefb4210abacd92a58af93a6bc89b1824f6c --- /dev/null +++ b/app/controllers/admin/university/alumni/cohorts_controller.rb @@ -0,0 +1,36 @@ +class Admin::University::Alumni::CohortsController < Admin::University::ApplicationController + load_and_authorize_resource :alumnus, + class: University::Person, + through: :current_university, + through_association: :people, + parent: false + def edit + breadcrumb + end + + def update + if @alumnus.update(cohorts_params) + redirect_to admin_university_alumnus_path(@alumnus), + notice: t('admin.successfully_updated_html', model: @alumnus.to_s) + else + render :edit + breadcrumb + end + end + + private + + def breadcrumb + super + add_breadcrumb University::Person::Alumnus.model_name.human(count: 2), + admin_university_alumni_path + add_breadcrumb @alumnus, admin_university_alumnus_path(@alumnus) + add_breadcrumb Education::Cohort.model_name.human(count: 2) + end + + def cohorts_params + params.require(:university_person) + .permit(cohorts_attributes: [:id, :program_id, :university_id, :year, :_destroy]) + end + +end diff --git a/app/controllers/admin/university/alumni/experiences_controller.rb b/app/controllers/admin/university/alumni/experiences_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..29d1689b065c7adb8969290d8c74f4687f62ef78 --- /dev/null +++ b/app/controllers/admin/university/alumni/experiences_controller.rb @@ -0,0 +1,36 @@ +class Admin::University::Alumni::ExperiencesController < Admin::University::ApplicationController + load_and_authorize_resource :alumnus, + class: University::Person, + through: :current_university, + through_association: :people, + parent: false + def edit + breadcrumb + end + + def update + if @alumnus.update(experiences_params) + redirect_to admin_university_alumnus_path(@alumnus), + notice: t('admin.successfully_updated_html', model: @alumnus.to_s) + else + render :edit + breadcrumb + end + end + + private + + def breadcrumb + super + add_breadcrumb University::Person::Alumnus.model_name.human(count: 2), + admin_university_alumni_path + add_breadcrumb @alumnus, admin_university_alumnus_path(@alumnus) + add_breadcrumb University::Person::Experience.model_name.human(count: 2) + end + + def experiences_params + params.require(:university_person) + .permit(experiences_attributes: [:id, :organization_id, :university_id, :from_year, :to_year, :_destroy]) + end + +end diff --git a/app/controllers/admin/university/alumni_controller.rb b/app/controllers/admin/university/alumni_controller.rb index ae1f4a38b11069de87c3ec4130ef6deb57147fd9..08a4dcfba526994c1490a2a8839d8f67d3427d4b 100644 --- a/app/controllers/admin/university/alumni_controller.rb +++ b/app/controllers/admin/university/alumni_controller.rb @@ -20,22 +20,6 @@ class Admin::University::AlumniController < Admin::University::ApplicationContro breadcrumb end - def edit_cohorts - breadcrumb - add_breadcrumb t('edit') - end - - def update_cohorts - if @alumnus.update(alumnus_params) - redirect_to admin_university_alumnus_path(@alumnus), - notice: t('admin.successfully_updated_html', model: @alumnus.to_s) - else - render :edit_cohorts - breadcrumb - add_breadcrumb t('edit') - end - end - protected def breadcrumb @@ -45,8 +29,4 @@ class Admin::University::AlumniController < Admin::University::ApplicationContro add_breadcrumb @alumnus, admin_university_alumni_path(@alumnus) if @alumnus end - def alumnus_params - params.require(:university_person) - .permit(cohorts_attributes: [:id, :program_id, :university_id, :year, :_destroy]) - end end diff --git a/app/models/university/person.rb b/app/models/university/person.rb index ae8ee83c2424ef43a6aa8c436c82234a5a56cc68..85e28db5f4278130e42c639b9323d1577ca9f254 100644 --- a/app/models/university/person.rb +++ b/app/models/university/person.rb @@ -42,10 +42,11 @@ class University::Person < ApplicationRecord include WithUniversity include WithGit include WithBlobs + include WithEducation + include WithExperiences include WithSlug include WithPicture include WithRoles - include WithEducation LIST_OF_ROLES = [ :administration, diff --git a/app/models/university/person/experience.rb b/app/models/university/person/experience.rb index 3cee8c3347cd85fbc792cc0aac2bfa61b3ac4523..7a07ecd396a65efa71e56702971532a3a3227802 100644 --- a/app/models/university/person/experience.rb +++ b/app/models/university/person/experience.rb @@ -29,5 +29,7 @@ class University::Person::Experience < ApplicationRecord belongs_to :person belongs_to :organization, class_name: "University::Organization" + validates :from_year, presence: true + scope :ordered, -> { order(from_year: :desc)} end diff --git a/app/models/university/person/with_education.rb b/app/models/university/person/with_education.rb index f22aed32deca953f0c34397016482345a9a9f67b..15a7e3682261b48ebe8882a95c1fee4b95f6f43f 100644 --- a/app/models/university/person/with_education.rb +++ b/app/models/university/person/with_education.rb @@ -2,46 +2,45 @@ module University::Person::WithEducation extend ActiveSupport::Concern included do - has_many :involvements_as_teacher, - -> { where(kind: 'teacher') }, - class_name: 'University::Person::Involvement', - dependent: :destroy + has_many :involvements_as_teacher, + -> { where(kind: 'teacher') }, + class_name: 'University::Person::Involvement', + dependent: :destroy - has_many :education_programs_as_teacher, - through: :involvements_as_teacher, - source: :target, - source_type: "Education::Program" + has_many :education_programs_as_teacher, + through: :involvements_as_teacher, + source: :target, + source_type: "Education::Program" - has_many :education_programs_as_administrator, - -> { distinct }, - through: :roles_as_administrator, - source: :target, - source_type: "Education::Program" + has_many :education_programs_as_administrator, + -> { distinct }, + through: :roles_as_administrator, + source: :target, + source_type: "Education::Program" - has_many :experiences, class_name: "University::Person::Experience" - - has_and_belongs_to_many :cohorts, - class_name: '::Education::Cohort', - foreign_key: 'university_person_id', - association_foreign_key: 'education_cohort_id' + has_and_belongs_to_many :cohorts, + class_name: '::Education::Cohort', + foreign_key: 'university_person_id', + association_foreign_key: 'education_cohort_id' accepts_nested_attributes_for :cohorts, reject_if: :all_blank, allow_destroy: true + # Dénormalisation des liens via cohorts, pour la recherche par facettes + has_and_belongs_to_many :diploma_years, + class_name: 'Education::AcademicYear', + foreign_key: 'university_person_id', + association_foreign_key: 'education_academic_year_id' + + has_and_belongs_to_many :diploma_programs, + class_name: 'Education::Program', + foreign_key: 'university_person_id', + association_foreign_key: 'education_program_id' + before_validation :find_cohorts validates_associated :cohorts - # Dénormalisation des liens via cohorts, pour la recherche par facettes - has_and_belongs_to_many :diploma_years, - class_name: 'Education::AcademicYear', - foreign_key: 'university_person_id', - association_foreign_key: 'education_academic_year_id' - has_and_belongs_to_many :diploma_programs, - class_name: 'Education::Program', - foreign_key: 'university_person_id', - association_foreign_key: 'education_program_id' - scope :for_alumni_program, -> (program_id) { left_joins(:cohorts) .where(education_cohorts: { program_id: program_id }) diff --git a/app/models/university/person/with_experiences.rb b/app/models/university/person/with_experiences.rb new file mode 100644 index 0000000000000000000000000000000000000000..297f779a745a0723ccd0fbbd5c138976a77b0a87 --- /dev/null +++ b/app/models/university/person/with_experiences.rb @@ -0,0 +1,17 @@ +module University::Person::WithExperiences + extend ActiveSupport::Concern + + included do + + has_many :experiences, + class_name: "University::Person::Experience" + + accepts_nested_attributes_for :experiences, + reject_if: :all_blank, + allow_destroy: true + + validates_associated :experiences + + end + +end diff --git a/app/views/admin/university/alumni/_cohort_fields.html.erb b/app/views/admin/university/alumni/cohorts/_cohort_fields.html.erb similarity index 64% rename from app/views/admin/university/alumni/_cohort_fields.html.erb rename to app/views/admin/university/alumni/cohorts/_cohort_fields.html.erb index 632f02976117be7297d2e905c93f94dd629e4981..4887bdd6ba803495852a0b5f38c3259f58907e5d 100644 --- a/app/views/admin/university/alumni/_cohort_fields.html.erb +++ b/app/views/admin/university/alumni/cohorts/_cohort_fields.html.erb @@ -4,10 +4,10 @@ <div class="card-body"> <div class="row"> <div class="col-md-5"> - <%= f.input :university_id, - as: :hidden, - input_html: { value: current_university.id }, - wrapper: false %> + <%= f.input :university_id, + as: :hidden, + input_html: { value: current_university.id }, + wrapper: false %> <%= f.association :program, collection: collection_tree(current_university.education_programs), label_method: ->(p) { sanitize p[:label] }, @@ -18,13 +18,13 @@ wrapper: false %> </div> <div class="col-md-6"> - <%= f.input :year, - as: :select, - collection: ((Time.now.year + 5).downto(1950)), - label: false, - include_blank: t('simple_form.include_blanks.defaults.year'), - required: true, - wrapper: false %> + <%= f.input :year, + as: :select, + collection: ((Time.now.year + 5).downto(1950)), + label: false, + include_blank: t('simple_form.include_blanks.defaults.year'), + required: true, + wrapper: false %> </div> <div class="col-md-1 text-end"> <%= link_to_remove_association '<i class="fas fa-times"></i>'.html_safe, diff --git a/app/views/admin/university/alumni/edit_cohorts.html.erb b/app/views/admin/university/alumni/cohorts/edit.html.erb similarity index 76% rename from app/views/admin/university/alumni/edit_cohorts.html.erb rename to app/views/admin/university/alumni/cohorts/edit.html.erb index ea332608a5f07d98cbd8af1d4797073b4af5b2fb..c4f3de3af35601e502a52c330ea8a90eb710bb4b 100644 --- a/app/views/admin/university/alumni/edit_cohorts.html.erb +++ b/app/views/admin/university/alumni/cohorts/edit.html.erb @@ -1,8 +1,8 @@ <% content_for :title, @alumnus %> -<h2 class="h3"><%= Education::Program.model_name.human(count: 2) %></h2> +<h2 class="h3"><%= Education::Cohort.model_name.human(count: 2) %></h2> -<%= simple_form_for [:admin, @alumnus], url: edit_cohorts_admin_university_alumnus_path(@alumnus) do |f| %> +<%= simple_form_for [:admin, @alumnus], url: cohorts_admin_university_alumnus_path(@alumnus) do |f| %> <%= f.error_notification %> <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %> @@ -21,11 +21,12 @@ <div class="col-md-10"> <div id="cohorts"> <%= f.simple_fields_for :cohorts, @alumnus.cohorts.sort_by { |c| [c.year ? 0 : 1, c.year] }.reverse, include_id: false do |cohort_f| %> - <%= render 'admin/university/alumni/cohort_fields', f: cohort_f, include_id: true %> + <%= render 'admin/university/alumni/cohorts/cohort_fields', f: cohort_f, include_id: true %> <% end %> </div> </div> </div> + <% content_for :action_bar_right do %> <%= submit f %> <% end %> diff --git a/app/views/admin/university/alumni/experiences/_experience_fields.html.erb b/app/views/admin/university/alumni/experiences/_experience_fields.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..eb6b7bd848e67df626f8d5ad055eadcb801578fb --- /dev/null +++ b/app/views/admin/university/alumni/experiences/_experience_fields.html.erb @@ -0,0 +1,47 @@ +<% include_id ||= false %> +<div class="nested-fields"> + <div class="card mb-3"> + <div class="card-body"> + <div class="row"> + <div class="col-md-5"> + <%= f.input :university_id, + as: :hidden, + input_html: { value: current_university.id }, + wrapper: false %> + <%= f.association :organization, + collection: current_university.organizations.ordered, + label: false, + include_blank: t('simple_form.include_blanks.defaults.organization'), + hint: can?(:create, University::Organization) ? t('university.person.experience.no_organization_hint_html', url: new_admin_university_organization_path) : + t('university.person.experience.no_organization_hint_no_access_html'), + required: true, + wrapper: false %> + </div> + <div class="col-md-3"> + <%= f.input :from_year, + as: :select, + collection: ((Time.now.year).downto(1950)), + label: false, + include_blank: University::Person::Experience.human_attribute_name('from_year'), + required: true, + wrapper: false %> + </div> + <div class="col-md-3"> + <%= f.input :to_year, + as: :select, + collection: ((Time.now.year).downto(1950)), + label: false, + include_blank: University::Person::Experience.human_attribute_name('to_year'), + required: true, + wrapper: false %> + </div> + <div class="col-md-1 text-end"> + <%= link_to_remove_association '<i class="fas fa-times"></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/university/alumni/experiences/edit.html.erb b/app/views/admin/university/alumni/experiences/edit.html.erb new file mode 100644 index 0000000000000000000000000000000000000000..e21fe1ce8a5bd9f3e8fca697cb9cc86f157f74a8 --- /dev/null +++ b/app/views/admin/university/alumni/experiences/edit.html.erb @@ -0,0 +1,33 @@ +<% content_for :title, @alumnus %> + +<h2 class="h3"><%= University::Person::Experience.model_name.human(count: 2) %></h2> + +<%= simple_form_for [:admin, @alumnus], url: experiences_admin_university_alumnus_path(@alumnus) do |f| %> + <%= f.error_notification %> + <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %> + + <div class="row"> + + <div class="col-md-2"> + <%= link_to_add_association t('add'), f, :experiences, + class: button_classes, + data: { + 'association-insertion-method': 'append', + 'association-insertion-node': '#experiences', + } %> + + </div> + + <div class="col-md-10"> + <div id="experiences"> + <%= f.simple_fields_for :experiences, @alumnus.experiences.sort_by(&:from_year).reverse, include_id: false do |experience_f| %> + <%= render 'admin/university/alumni/experiences/experience_fields', f: experience_f, include_id: true %> + <% end %> + </div> + </div> + </div> + + <% content_for :action_bar_right do %> + <%= submit f %> + <% end %> +<% end %> diff --git a/app/views/admin/university/alumni/show.html.erb b/app/views/admin/university/alumni/show.html.erb index c122295e9ef3ad42c37457d47f6a4a3f50faeb2c..83ad9faef63fa4ca4ecaa31c4a347c5b2d9fc846 100644 --- a/app/views/admin/university/alumni/show.html.erb +++ b/app/views/admin/university/alumni/show.html.erb @@ -20,5 +20,6 @@ <% content_for :action_bar_right do %> <%= edit_link @alumnus %> - <%= link_to t('university.manage_cohorts'), edit_cohorts_admin_university_alumnus_path(@alumnus), class: button_classes if can?(:update, @alumnus) %> + <%= link_to t('university.manage_cohorts'), cohorts_admin_university_alumnus_path(@alumnus), class: button_classes if can?(:update, @alumnus) %> + <%= link_to t('university.manage_experiences'), experiences_admin_university_alumnus_path(@alumnus), class: button_classes if can?(:update, @alumnus) %> <% end %> diff --git a/config/locales/education/en.yml b/config/locales/education/en.yml index e83ec1619925852f0974c3692cc7f9570885530e..d3f7ef9cdf5b376e498c8bf1a0cc43ea2a364f43 100644 --- a/config/locales/education/en.yml +++ b/config/locales/education/en.yml @@ -142,3 +142,6 @@ en: evaluation: Means mobilised to measure with objective criteria the beneficiary's achievements during and/or at the end of the service. accessibility: Conditions of reception and access for people with disabilities (premises, adaptation of the means of provision). description: Plain text without HTML, dedicated to SEO + include_blanks: + defaults: + program: "Select a program" diff --git a/config/locales/education/fr.yml b/config/locales/education/fr.yml index 1c657a83016d3269dec0c90c9042cfff7aa43c70..41e74e7d34275b13977584e24349e52cd48a324b 100644 --- a/config/locales/education/fr.yml +++ b/config/locales/education/fr.yml @@ -160,3 +160,6 @@ fr: evaluation: Moyens mobilisés pour mesurer à l'aide de critères objectifs les acquis du bénéficiaire en cours et/ou à la fin de la prestation. accessibility: Conditions d'accueil et d’accès des publics en situation de handicap (locaux, adaptation des moyens de la prestation). description: Texte simple, sans HTML, pour le SEO + include_blanks: + defaults: + program: "Sélectionnez une formation" diff --git a/config/locales/en.yml b/config/locales/en.yml index bc9a6fa7cb07d0a75ab9e4adcf6ed0907b4d780d..a24c9010c881d4bdcd5c1476bc2f74656eb97a9a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -49,7 +49,7 @@ en: status: Inherited value pending_tasks: label: Background tasks pending - hint: Those tasks precompute your data in order to minimize its carbon footprint. It creates a delay before your changes are online. + hint: Those tasks precompute your data in order to minimize its carbon footprint. It creates a delay before your changes are online. 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." @@ -172,7 +172,6 @@ en: 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 diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 99b80a8739f2f4942c61a2f0c138dd5230ebc9df..a03167dfd59c21ff640a304066d7365cbdd87960 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -49,7 +49,7 @@ fr: status: Valeur héritée pending_tasks: label: Tâches en cours de traitement - hint: L'exécution de ces tâches contribue à diminuer l'empreinte carbone du numérique, en précalculant ce qui peut l'être. Cela peut générer un délai avant que vos modifications ne soient visibles. + hint: L'exécution de ces tâches contribue à diminuer l'empreinte carbone du numérique, en précalculant ce qui peut l'être. Cela peut générer un délai avant que vos modifications ne soient visibles. 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)." @@ -172,7 +172,6 @@ fr: 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 6de579a94b3757e9ee037e4de09bc694fe85c1ad..7b1e4780fa4a510fbf5aa7778def32c9b5da57e3 100644 --- a/config/locales/university/en.yml +++ b/config/locales/university/en.yml @@ -55,6 +55,8 @@ en: url: Website user: User university/person/experience: + from_year: Start year + to_year: End year today: Today university/person/involvement: description: Mission (in this context) @@ -100,9 +102,9 @@ en: university/person/alumnus: one: Alumnus other: Alumni - university/person/Experience: - one: Experience - other: Experiences + university/person/experience: + one: Professional experience + other: Professional experiences university/organization: one: Organization other: Organizations @@ -131,6 +133,7 @@ en: twitter: "Example: osuny" include_blanks: defaults: + organization: Select organization year: Select year enums: university: @@ -147,6 +150,9 @@ en: manage_experiences: Manage experiences person: administrator_roles: Administrator roles + experience: + no_organization_hint_html: "If the organization is not in the list,<br>you can <a href=\"%{url}\">create it</a>" + no_organization_hint_no_access_html: "If the organization is not in the list,<br>you should ask to create it" taught_programs: Taught programs sso: SSO sso_key: SSO Key diff --git a/config/locales/university/fr.yml b/config/locales/university/fr.yml index af72d52d27263c1fea9d70bd08509b8f68cb6ebc..502fa6a9249c2a8dd51f035671546d2884d381fe 100644 --- a/config/locales/university/fr.yml +++ b/config/locales/university/fr.yml @@ -55,6 +55,8 @@ fr: url: Site web user: Utilisateur university/person/experience: + from_year: Année de début + to_year: Année de fin today: Aujourd'hui university/person/involvement: description: Mission (dans ce contexte) @@ -100,9 +102,9 @@ fr: university/person/alumnus: one: Alumnus other: Alumni - university/person/Experience: - one: Expérience - other: Expériences + university/person/experience: + one: Expérience professionnelle + other: Expériences professionnelles university/organization: one: Organisation other: Organisations @@ -131,6 +133,7 @@ fr: twitter: "Exemple : osuny" include_blanks: defaults: + organization: Sélectionnez une organisation year: Sélectionnez une année enums: university: @@ -147,6 +150,9 @@ fr: manage_experiences: Gérer les expériences professionnelles person: administrator_roles: Rôles administratifs + experience: + no_organization_hint_html: "Si l'entreprise n'apparait pas dans la liste,<br>vous pouvez la <a href=\"%{url}\">créer</a>" + no_organization_hint_no_access_html: "Si l'entreprise n'apparait pas dans la liste,<br>il faut demander à la créer" taught_programs: Formations enseignées sso: SSO sso_key: Clé sur le SSO diff --git a/config/routes/admin/university.rb b/config/routes/admin/university.rb index 8b8d2a3b5dafb9064928c2b76d84d7e06d98013a..3acfe622ec80685a2c9b57c8ab3f731f4e696c25 100644 --- a/config/routes/admin/university.rb +++ b/config/routes/admin/university.rb @@ -8,10 +8,10 @@ namespace :university do end resources :alumni, only: [:index, :show] do member do - get 'edit_cohorts' => 'alumni#edit_cohorts' - patch 'edit_cohorts' => 'alumni#update_cohorts' - get 'edit_experience' => 'alumni#edit_experiences' - patch 'edit_experiences' => 'alumni#update_experiences' + get 'cohorts' => 'alumni/cohorts#edit' + patch 'cohorts' => 'alumni/cohorts#update' + get 'experiences' => 'alumni/experiences#edit' + patch 'experiences' => 'alumni/experiences#update' end end resources :people, :organizations