diff --git a/addons/hr_recruitment_skills/views/hr_applicant_views.xml b/addons/hr_recruitment_skills/views/hr_applicant_views.xml index 20e87f50c2d..23a6dcdf55f 100644 --- a/addons/hr_recruitment_skills/views/hr_applicant_views.xml +++ b/addons/hr_recruitment_skills/views/hr_applicant_views.xml @@ -7,7 +7,7 @@ -
+
diff --git a/addons/hr_skills/__manifest__.py b/addons/hr_skills/__manifest__.py index e67ef2d670d..db11b031fcd 100644 --- a/addons/hr_skills/__manifest__.py +++ b/addons/hr_skills/__manifest__.py @@ -36,11 +36,12 @@ This module introduces skills and resume management for employees. 'data/hr.resume.line.csv', ], 'installable': True, + 'auto_install': True, 'application': True, 'assets': { 'web.assets_backend': [ - 'hr_skills/static/src/fields/skills_one2many.xml', - 'hr_skills/static/src/fields/*', + 'hr_skills/static/src/fields/skills_one2many/*', + 'hr_skills/static/src/fields/**/*', 'hr_skills/static/src/scss/*.scss', 'hr_skills/static/src/views/*.js', 'hr_skills/static/src/xml/**/*', diff --git a/addons/hr_skills/data/hr.employee.skill.csv b/addons/hr_skills/data/hr.employee.skill.csv index 43338f06b71..980c23a2a5b 100644 --- a/addons/hr_skills/data/hr.employee.skill.csv +++ b/addons/hr_skills/data/hr.employee.skill.csv @@ -1,9 +1,5 @@ id,employee_id:id,skill_id:id,skill_type_id:id,skill_level_id:id employee_skill_admin_spark,hr.employee_admin,hr_skill_spark,hr_skill_type_dev,hr_skill_level_intermediate -employee_skill_admin_flute,hr.employee_admin,hr_skill_flute,hr_skill_type_music,hr_skill_level_l2 -employee_skill_admin_singing,hr.employee_admin,hr_skill_singing,hr_skill_type_music,hr_skill_level_l1 -employee_skill_admin_violin,hr.employee_admin,hr_skill_violin,hr_skill_type_music,hr_skill_level_l2 -employee_skill_admin_piano,hr.employee_admin,hr_skill_piano,hr_skill_type_music,hr_skill_level_l2 employee_skill_admin_french,hr.employee_admin,hr_skill_french,hr_skill_type_lang,hr_skill_level_a1 employee_skill_admin_english,hr.employee_admin,hr_skill_english,hr_skill_type_lang,hr_skill_level_a2 employee_skill_al_analytics,hr.employee_al,hr_skill_analytics,hr_skill_type_marketing,hr_skill_level_ml3 @@ -14,10 +10,6 @@ employee_skill_al_french,hr.employee_al,hr_skill_french,hr_skill_type_lang,hr_sk employee_skill_al_nosql,hr.employee_al,hr_skill_nosql,hr_skill_type_dev,hr_skill_level_beginner employee_skill_al_django,hr.employee_al,hr_skill_django,hr_skill_type_dev,hr_skill_level_advanced employee_skill_al_python,hr.employee_al,hr_skill_python,hr_skill_type_dev,hr_skill_level_advanced -employee_skill_mit_piano,hr.employee_mit,hr_skill_piano,hr_skill_type_music,hr_skill_level_l3 -employee_skill_mit_singing,hr.employee_mit,hr_skill_singing,hr_skill_type_music,hr_skill_level_l2 -employee_skill_mit_violin,hr.employee_mit,hr_skill_violin,hr_skill_type_music,hr_skill_level_l4 -employee_skill_mit_flute,hr.employee_mit,hr_skill_flute,hr_skill_type_music,hr_skill_level_l2 employee_skill_mit_email,hr.employee_mit,hr_skill_email,hr_skill_type_marketing,hr_skill_level_ml2 employee_skill_mit_public,hr.employee_mit,hr_skill_public,hr_skill_type_marketing,hr_skill_level_ml3 employee_skill_mit_cms,hr.employee_mit,hr_skill_cms,hr_skill_type_marketing,hr_skill_level_ml1 @@ -28,44 +20,30 @@ employee_skill_niv_public,hr.employee_niv,hr_skill_public,hr_skill_type_marketin employee_skill_niv_c,hr.employee_niv,hr_skill_c,hr_skill_type_dev,hr_skill_level_expert employee_skill_niv_android,hr.employee_niv,hr_skill_android,hr_skill_type_dev,hr_skill_level_intermediate employee_skill_niv_nosql,hr.employee_niv,hr_skill_nosql,hr_skill_type_dev,hr_skill_level_beginner -employee_skill_niv_flute,hr.employee_niv,hr_skill_flute,hr_skill_type_music,hr_skill_level_l4 -employee_skill_niv_singing,hr.employee_niv,hr_skill_singing,hr_skill_type_music,hr_skill_level_l4 employee_skill_stw_com,hr.employee_stw,hr_skill_com,hr_skill_type_marketing,hr_skill_level_ml4 employee_skill_stw_digital_ad,hr.employee_stw,hr_skill_digital_ad,hr_skill_type_marketing,hr_skill_level_ml2 employee_skill_chs_digital_ad,hr.employee_chs,hr_skill_digital_ad,hr_skill_type_marketing,hr_skill_level_ml3 employee_skill_chs_email,hr.employee_chs,hr_skill_email,hr_skill_type_marketing,hr_skill_level_ml3 employee_skill_chs_arabic,hr.employee_chs,hr_skill_arabic,hr_skill_type_lang,hr_skill_level_c1 -employee_skill_chs_piano,hr.employee_chs,hr_skill_piano,hr_skill_type_music,hr_skill_level_l4 employee_skill_qdp_com,hr.employee_qdp,hr_skill_com,hr_skill_type_marketing,hr_skill_level_ml4 employee_skill_qdp_email,hr.employee_qdp,hr_skill_email,hr_skill_type_marketing,hr_skill_level_ml4 employee_skill_qdp_analytics,hr.employee_qdp,hr_skill_analytics,hr_skill_type_marketing,hr_skill_level_ml2 employee_skill_qdp_nosql,hr.employee_qdp,hr_skill_nosql,hr_skill_type_dev,hr_skill_level_advanced employee_skill_qdp_js,hr.employee_qdp,hr_skill_js,hr_skill_type_dev,hr_skill_level_expert -employee_skill_qdp_flute,hr.employee_qdp,hr_skill_flute,hr_skill_type_music,hr_skill_level_l1 -employee_skill_qdp_violin,hr.employee_qdp,hr_skill_violin,hr_skill_type_music,hr_skill_level_l4 -employee_skill_qdp_singing,hr.employee_qdp,hr_skill_singing,hr_skill_type_music,hr_skill_level_l4 employee_skill_qdp_bengali,hr.employee_qdp,hr_skill_bengali,hr_skill_type_lang,hr_skill_level_b2 employee_skill_qdp_english,hr.employee_qdp,hr_skill_english,hr_skill_type_lang,hr_skill_level_b1 employee_skill_fme_spark,hr.employee_fme,hr_skill_spark,hr_skill_type_dev,hr_skill_level_beginner employee_skill_fme_com,hr.employee_fme,hr_skill_com,hr_skill_type_marketing,hr_skill_level_ml2 employee_skill_fpi_django,hr.employee_fpi,hr_skill_django,hr_skill_type_dev,hr_skill_level_expert -employee_skill_fpi_violin,hr.employee_fpi,hr_skill_violin,hr_skill_type_music,hr_skill_level_l1 -employee_skill_fpi_piano,hr.employee_fpi,hr_skill_piano,hr_skill_type_music,hr_skill_level_l1 -employee_skill_fpi_singing,hr.employee_fpi,hr_skill_singing,hr_skill_type_music,hr_skill_level_l4 -employee_skill_fpi_flute,hr.employee_fpi,hr_skill_flute,hr_skill_type_music,hr_skill_level_l2 employee_skill_fpi_cms,hr.employee_fpi,hr_skill_cms,hr_skill_type_marketing,hr_skill_level_ml1 employee_skill_jth_hadoop,hr.employee_jth,hr_skill_hadoop,hr_skill_type_dev,hr_skill_level_expert employee_skill_jth_nosql,hr.employee_jth,hr_skill_nosql,hr_skill_type_dev,hr_skill_level_elementary employee_skill_jth_c,hr.employee_jth,hr_skill_c,hr_skill_type_dev,hr_skill_level_intermediate -employee_skill_ngh_violin,hr.employee_ngh,hr_skill_violin,hr_skill_type_music,hr_skill_level_l4 -employee_skill_ngh_piano,hr.employee_ngh,hr_skill_piano,hr_skill_type_music,hr_skill_level_l1 -employee_skill_ngh_flute,hr.employee_ngh,hr_skill_flute,hr_skill_type_music,hr_skill_level_l4 employee_skill_vad_sql,hr.employee_vad,hr_skill_sql,hr_skill_type_dev,hr_skill_level_intermediate employee_skill_vad_js,hr.employee_vad,hr_skill_js,hr_skill_type_dev,hr_skill_level_elementary employee_skill_vad_spark,hr.employee_vad,hr_skill_spark,hr_skill_type_dev,hr_skill_level_expert employee_skill_vad_python,hr.employee_vad,hr_skill_python,hr_skill_type_dev,hr_skill_level_expert employee_skill_vad_french,hr.employee_vad,hr_skill_french,hr_skill_type_lang,hr_skill_level_a2 -employee_skill_vad_singing,hr.employee_vad,hr_skill_singing,hr_skill_type_music,hr_skill_level_l2 employee_skill_vad_public,hr.employee_vad,hr_skill_public,hr_skill_type_marketing,hr_skill_level_ml1 employee_skill_vad_cms,hr.employee_vad,hr_skill_cms,hr_skill_type_marketing,hr_skill_level_ml3 employee_skill_vad_analytics,hr.employee_vad,hr_skill_analytics,hr_skill_type_marketing,hr_skill_level_ml1 @@ -75,35 +53,20 @@ employee_skill_han_python,hr.employee_han,hr_skill_python,hr_skill_type_dev,hr_s employee_skill_han_react,hr.employee_han,hr_skill_react,hr_skill_type_dev,hr_skill_level_advanced employee_skill_han_analytics,hr.employee_han,hr_skill_analytics,hr_skill_type_marketing,hr_skill_level_ml1 employee_skill_han_digital_ad,hr.employee_han,hr_skill_digital_ad,hr_skill_type_marketing,hr_skill_level_ml4 -employee_skill_han_violin,hr.employee_han,hr_skill_violin,hr_skill_type_music,hr_skill_level_l1 -employee_skill_han_flute,hr.employee_han,hr_skill_flute,hr_skill_type_music,hr_skill_level_l1 -employee_skill_han_piano,hr.employee_han,hr_skill_piano,hr_skill_type_music,hr_skill_level_l3 employee_skill_jve_cms,hr.employee_jve,hr_skill_cms,hr_skill_type_marketing,hr_skill_level_ml1 employee_skill_jve_email,hr.employee_jve,hr_skill_email,hr_skill_type_marketing,hr_skill_level_ml1 employee_skill_jve_digital_ad,hr.employee_jve,hr_skill_digital_ad,hr_skill_type_marketing,hr_skill_level_ml1 employee_skill_jve_com,hr.employee_jve,hr_skill_com,hr_skill_type_marketing,hr_skill_level_ml4 -employee_skill_jve_violin,hr.employee_jve,hr_skill_violin,hr_skill_type_music,hr_skill_level_l2 -employee_skill_jve_singing,hr.employee_jve,hr_skill_singing,hr_skill_type_music,hr_skill_level_l3 -employee_skill_jve_flute,hr.employee_jve,hr_skill_flute,hr_skill_type_music,hr_skill_level_l4 -employee_skill_jve_piano,hr.employee_jve,hr_skill_piano,hr_skill_type_music,hr_skill_level_l3 employee_skill_jve_french,hr.employee_jve,hr_skill_french,hr_skill_type_lang,hr_skill_level_b1 employee_skill_jve_spark,hr.employee_jve,hr_skill_spark,hr_skill_type_dev,hr_skill_level_expert employee_skill_jve_c,hr.employee_jve,hr_skill_c,hr_skill_type_dev,hr_skill_level_elementary employee_skill_jve_js,hr.employee_jve,hr_skill_js,hr_skill_type_dev,hr_skill_level_expert employee_skill_jve_hadoop,hr.employee_jve,hr_skill_hadoop,hr_skill_type_dev,hr_skill_level_advanced -employee_skill_jep_piano,hr.employee_jep,hr_skill_piano,hr_skill_type_music,hr_skill_level_l1 -employee_skill_jep_flute,hr.employee_jep,hr_skill_flute,hr_skill_type_music,hr_skill_level_l4 -employee_skill_jep_singing,hr.employee_jep,hr_skill_singing,hr_skill_type_music,hr_skill_level_l4 -employee_skill_jep_violin,hr.employee_jep,hr_skill_violin,hr_skill_type_music,hr_skill_level_l4 -employee_skill_jod_singing,hr.employee_jod,hr_skill_singing,hr_skill_type_music,hr_skill_level_l4 -employee_skill_jod_violin,hr.employee_jod,hr_skill_violin,hr_skill_type_music,hr_skill_level_l4 employee_skill_jod_filipino,hr.employee_jod,hr_skill_filipino,hr_skill_type_lang,hr_skill_level_c1 employee_skill_jod_spark,hr.employee_jod,hr_skill_spark,hr_skill_type_dev,hr_skill_level_advanced employee_skill_jod_sql,hr.employee_jod,hr_skill_sql,hr_skill_type_dev,hr_skill_level_expert employee_skill_jod_analytics,hr.employee_jod,hr_skill_analytics,hr_skill_type_marketing,hr_skill_level_ml1 employee_skill_jod_public,hr.employee_jod,hr_skill_public,hr_skill_type_marketing,hr_skill_level_ml2 -employee_skill_jog_violin,hr.employee_jog,hr_skill_violin,hr_skill_type_music,hr_skill_level_l4 -employee_skill_jog_singing,hr.employee_jog,hr_skill_singing,hr_skill_type_music,hr_skill_level_l1 employee_skill_jog_public,hr.employee_jog,hr_skill_public,hr_skill_type_marketing,hr_skill_level_ml1 employee_skill_jog_cms,hr.employee_jog,hr_skill_cms,hr_skill_type_marketing,hr_skill_level_ml1 employee_skill_jog_filipino,hr.employee_jog,hr_skill_filipino,hr_skill_type_lang,hr_skill_level_c1 @@ -117,13 +80,9 @@ employee_skill_jgo_analytics,hr.employee_jgo,hr_skill_analytics,hr_skill_type_ma employee_skill_jgo_com,hr.employee_jgo,hr_skill_com,hr_skill_type_marketing,hr_skill_level_ml1 employee_skill_lur_english,hr.employee_lur,hr_skill_english,hr_skill_type_lang,hr_skill_level_c2 employee_skill_lur_french,hr.employee_lur,hr_skill_french,hr_skill_type_lang,hr_skill_level_a1 -employee_skill_lur_singing,hr.employee_lur,hr_skill_singing,hr_skill_type_music,hr_skill_level_l3 employee_skill_hne_spanish,hr.employee_hne,hr_skill_spanish,hr_skill_type_lang,hr_skill_level_c1 employee_skill_hne_cms,hr.employee_hne,hr_skill_cms,hr_skill_type_marketing,hr_skill_level_ml4 employee_skill_hne_public,hr.employee_hne,hr_skill_public,hr_skill_type_marketing,hr_skill_level_ml3 employee_skill_hne_com,hr.employee_hne,hr_skill_com,hr_skill_type_marketing,hr_skill_level_ml4 employee_skill_hne_digital_ad,hr.employee_hne,hr_skill_digital_ad,hr_skill_type_marketing,hr_skill_level_ml3 -employee_skill_hne_singing,hr.employee_hne,hr_skill_singing,hr_skill_type_music,hr_skill_level_l2 -employee_skill_hne_flute,hr.employee_hne,hr_skill_flute,hr_skill_type_music,hr_skill_level_l3 -employee_skill_hne_piano,hr.employee_hne,hr_skill_piano,hr_skill_type_music,hr_skill_level_l4 employee_skill_hne_sql,hr.employee_hne,hr_skill_sql,hr_skill_type_dev,hr_skill_level_expert diff --git a/addons/hr_skills/data/hr_resume_demo.xml b/addons/hr_skills/data/hr_resume_demo.xml index c83d2572486..a0c0c83decc 100644 --- a/addons/hr_skills/data/hr_resume_demo.xml +++ b/addons/hr_skills/data/hr_resume_demo.xml @@ -4,19 +4,24 @@ - Dev + Programming Languages - - Music + + IT Marketing + + Soft Skills + + A1 10 + 1 @@ -45,8 +50,10 @@ + Beginner + 1 15 @@ -71,29 +78,10 @@ - - L1 - 25 - - - - L2 - 50 - - - - L3 - 75 - - - - L4 - 100 - - - + L1 + 1 25 @@ -113,7 +101,63 @@ - + + + Beginner + 1 + 15 + + + + Elementary + 25 + + + + Intermediate + 50 + + + + Advanced + 80 + + + + Expert + 100 + + + + + + Beginner + 1 + 15 + + + + Elementary + 25 + + + + Intermediate + 50 + + + + Advanced + 80 + + + + Expert + 100 + + + + French @@ -143,8 +187,64 @@ Bengali + + Mandarin Chinese + + + + Wu Chinese + + + + Hindi + + + + Russian + + + + Portuguese + + + + Indonesian + + + + Urdu + + + + Japanese + + + + Punjabi + + + + Javanese + + + + Telugu + + + + Turkish + + + + Korean + + + + Marathi + + - + Javascript @@ -185,23 +285,69 @@ NoSQL - - - - Piano - + + Go + - - Violin - + + Java + - - Singing - + + Kotlin + - - Flute - + + PHP + + + + C# + + + + Swift + + + + R + + + + Ruby + + + + Matlab + + + + TypeScript + + + + Scala + + + + HTML + + + + CSS + + + + NoSQL + + + + Rust + + + + Perl + @@ -230,6 +376,146 @@ + + + Communication + + + + Teamwork + + + + Problem-Solving + + + + Time Management + + + + Critical Thinking + + + + Decision-Making + + + + Organizational + + + + Stress management + + + + Adaptability + + + + Conflict Management + + + + Leadership + + + + Creativity + + + + Resourcefulness + + + + Persuasion + + + + Openness to criticism + + + + + + Web Development + + + + Database Management + + + + Cloud computing + + + + Network administration + + + + Cybersecurity + + + + DevOps + + + + Machine Learning (AI) + + + + Data analysis/visualization + + + + Agile and Scrum methodologies + + + + Mobile app development + + + + Project Management + + + + System Administration (Linux, Windows) + + + + Virtualization and Containerization + + + + IT support + + + + IT infrastructure and architecture + + + + IT service management (ITSM) + + + + Big data technologies (Hadoop,Spark) + + + + IoT and embedded systems + + + + IT governance and compliance (GDPR,HIPAA,...) + + + diff --git a/addons/hr_skills/data/ir_actions_server_data.xml b/addons/hr_skills/data/ir_actions_server_data.xml index 3cfb4bffc18..067af206d41 100644 --- a/addons/hr_skills/data/ir_actions_server_data.xml +++ b/addons/hr_skills/data/ir_actions_server_data.xml @@ -1,17 +1,5 @@ - - Skill History Report - - - form - code - -action = env['ir.actions.act_window']._for_xml_id('hr_skills.action_hr_employee_skill_log_employee') -action['domain'] = [('employee_id', '=', record.id)] - - - Skill History Report diff --git a/addons/hr_skills/models/hr_employee_skill.py b/addons/hr_skills/models/hr_employee_skill.py index 0ed1635c854..7fa8b227178 100644 --- a/addons/hr_skills/models/hr_employee_skill.py +++ b/addons/hr_skills/models/hr_employee_skill.py @@ -15,7 +15,9 @@ class EmployeeSkill(models.Model): employee_id = fields.Many2one('hr.employee', required=True, ondelete='cascade') skill_id = fields.Many2one('hr.skill', compute='_compute_skill_id', store=True, domain="[('skill_type_id', '=', skill_type_id)]", readonly=False, required=True, ondelete='cascade') skill_level_id = fields.Many2one('hr.skill.level', compute='_compute_skill_level_id', domain="[('skill_type_id', '=', skill_type_id)]", store=True, readonly=False, required=True, ondelete='cascade') - skill_type_id = fields.Many2one('hr.skill.type', required=True, ondelete='cascade') + skill_type_id = fields.Many2one('hr.skill.type', + default=lambda self: self.env['hr.skill.type'].search([], limit=1), + required=True, ondelete='cascade') level_progress = fields.Integer(related='skill_level_id.level_progress') _sql_constraints = [ @@ -37,7 +39,9 @@ class EmployeeSkill(models.Model): @api.depends('skill_type_id') def _compute_skill_id(self): for record in self: - if record.skill_id.skill_type_id != record.skill_type_id: + if record.skill_type_id: + record.skill_id = record.skill_type_id.skill_ids[0] if record.skill_type_id.skill_ids else False + else: record.skill_id = False @api.depends('skill_id') diff --git a/addons/hr_skills/models/hr_skill_level.py b/addons/hr_skills/models/hr_skill_level.py index 332015a3b33..4053b4e8587 100644 --- a/addons/hr_skills/models/hr_skill_level.py +++ b/addons/hr_skills/models/hr_skill_level.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models, _ -from odoo.exceptions import ValidationError class SkillLevel(models.Model): @@ -29,28 +28,14 @@ class SkillLevel(models.Model): @api.model_create_multi def create(self, vals_list): - levels = super().create(vals_list) - levels.skill_type_id._set_default_level() - return levels + skill_levels = super().create(vals_list) + for level in skill_levels: + if level.default_level: + level.skill_type_id.skill_level_ids.filtered(lambda r: r.id != level.id).default_level = False + return skill_levels - def write(self, values): - levels = super().write(values) - self.skill_type_id._set_default_level() - return levels - - def unlink(self): - skill_types = self.skill_type_id - res = super().unlink() - skill_types._set_default_level() + def write(self, vals): + res = super().write(vals) + if vals.get('default_level'): + self.skill_type_id.skill_level_ids.filtered(lambda r: r.id != self.id).default_level = False return res - - @api.constrains('default_level', 'skill_type_id') - def _constrains_default_level(self): - for skill_type in set(self.mapped('skill_type_id')): - if len(skill_type.skill_level_ids.filtered('default_level')) > 1: - raise ValidationError(_('Only one default level is allowed per skill type.')) - - def action_set_default(self): - self.ensure_one() - self.skill_type_id.skill_level_ids.with_context(no_skill_level_check=True).default_level = False - self.default_level = True diff --git a/addons/hr_skills/models/hr_skill_type.py b/addons/hr_skills/models/hr_skill_type.py index 18e086d5cdd..e4ecca8d11a 100644 --- a/addons/hr_skills/models/hr_skill_type.py +++ b/addons/hr_skills/models/hr_skill_type.py @@ -12,11 +12,3 @@ class SkillType(models.Model): name = fields.Char(required=True) skill_ids = fields.One2many('hr.skill', 'skill_type_id', string="Skills") skill_level_ids = fields.One2many('hr.skill.level', 'skill_type_id', string="Levels") - - def _set_default_level(self): - if self.env.context.get('no_skill_level_check'): - return - - for types in self: - if not types.skill_level_ids.filtered('default_level'): - types.skill_level_ids[:1].default_level = True diff --git a/addons/hr_skills/report/hr_employee_skill_report_views.xml b/addons/hr_skills/report/hr_employee_skill_report_views.xml index aa9f133d0b4..ce163e5becc 100644 --- a/addons/hr_skills/report/hr_employee_skill_report_views.xml +++ b/addons/hr_skills/report/hr_employee_skill_report_views.xml @@ -15,7 +15,7 @@ hr.employee.skill.report - + diff --git a/addons/hr_skills/static/src/fields/auto_save_skill_type/auto_save_skill_type.js b/addons/hr_skills/static/src/fields/auto_save_skill_type/auto_save_skill_type.js new file mode 100644 index 00000000000..ddc6839e036 --- /dev/null +++ b/addons/hr_skills/static/src/fields/auto_save_skill_type/auto_save_skill_type.js @@ -0,0 +1,19 @@ +/** @odoo-module **/ + +import { registry } from "@web/core/registry"; +import { X2ManyField, x2ManyField } from "@web/views/fields/x2many/x2many_field"; + + +export class AutoSaveSkillTypeField extends X2ManyField { + async onAdd({ context, editable } = {}) { + await this.props.record.model.root.save(); + await super.onAdd({ context, editable }); + } +} + +export const autoSaveSkillTypeField = { + ...x2ManyField, + component: AutoSaveSkillTypeField, +}; + +registry.category("fields").add("auto_save_skill_type", autoSaveSkillTypeField); diff --git a/addons/hr_skills/static/src/fields/boolean_toggle_load/boolean_toggle_load.js b/addons/hr_skills/static/src/fields/boolean_toggle_load/boolean_toggle_load.js new file mode 100644 index 00000000000..3cd6d759054 --- /dev/null +++ b/addons/hr_skills/static/src/fields/boolean_toggle_load/boolean_toggle_load.js @@ -0,0 +1,18 @@ +/** @odoo-module */ + +import { registry } from '@web/core/registry'; +import { ListBooleanToggleField, listBooleanToggleField } from "@web/views/fields/boolean_toggle/list_boolean_toggle_field"; + +export class ListBooleanToggleLoadField extends ListBooleanToggleField { + async onChange(value) { + await super.onChange(value); + return this.env.model.load(); + } +} + +export const listBooleanToggleLoadField = { + ...listBooleanToggleField, + component: ListBooleanToggleLoadField, +}; + +registry.category("fields").add("boolean_toggle_load", listBooleanToggleLoadField); diff --git a/addons/hr_skills/static/src/fields/form_view_one2many/form_view_one2many.xml b/addons/hr_skills/static/src/fields/form_view_one2many/form_view_one2many.xml new file mode 100644 index 00000000000..4df68cd9125 --- /dev/null +++ b/addons/hr_skills/static/src/fields/form_view_one2many/form_view_one2many.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/addons/hr_skills/static/src/fields/resume_one2many.js b/addons/hr_skills/static/src/fields/resume_one2many/resume_one2many.js similarity index 85% rename from addons/hr_skills/static/src/fields/resume_one2many.js rename to addons/hr_skills/static/src/fields/resume_one2many/resume_one2many.js index 040c40c5bc1..1332fe08337 100644 --- a/addons/hr_skills/static/src/fields/resume_one2many.js +++ b/addons/hr_skills/static/src/fields/resume_one2many/resume_one2many.js @@ -4,8 +4,8 @@ import { registry } from "@web/core/registry"; import { formatDate } from "@web/core/l10n/dates"; -import { SkillsX2ManyField, skillsX2ManyField } from "./skills_one2many"; -import { CommonSkillsListRenderer } from "../views/skills_list_renderer"; +import { SkillsX2ManyField, skillsX2ManyField } from "../skills_one2many/skills_one2many"; +import { CommonSkillsListRenderer } from "../../views/skills_list_renderer"; export class ResumeListRenderer extends CommonSkillsListRenderer { get groupBy() { diff --git a/addons/hr_skills/static/src/fields/resume_one2many.scss b/addons/hr_skills/static/src/fields/resume_one2many/resume_one2many.scss similarity index 100% rename from addons/hr_skills/static/src/fields/resume_one2many.scss rename to addons/hr_skills/static/src/fields/resume_one2many/resume_one2many.scss diff --git a/addons/hr_skills/static/src/fields/resume_one2many.xml b/addons/hr_skills/static/src/fields/resume_one2many/resume_one2many.xml similarity index 82% rename from addons/hr_skills/static/src/fields/resume_one2many.xml rename to addons/hr_skills/static/src/fields/resume_one2many/resume_one2many.xml index bb5461bd32a..420fc243451 100644 --- a/addons/hr_skills/static/src/fields/resume_one2many.xml +++ b/addons/hr_skills/static/src/fields/resume_one2many/resume_one2many.xml @@ -4,6 +4,14 @@ + + + + + + @@ -11,6 +19,7 @@ + diff --git a/addons/hr_skills/static/src/fields/skills_one2many.js b/addons/hr_skills/static/src/fields/skills_one2many.js deleted file mode 100644 index 306be5e6d52..00000000000 --- a/addons/hr_skills/static/src/fields/skills_one2many.js +++ /dev/null @@ -1,49 +0,0 @@ -/** @odoo-module */ - -import { X2ManyField, x2ManyField } from "@web/views/fields/x2many/x2many_field"; -import { registry } from "@web/core/registry"; - -import { CommonSkillsListRenderer } from "../views/skills_list_renderer"; - - -export class SkillsListRenderer extends CommonSkillsListRenderer { - get groupBy() { - return 'skill_type_id'; - } - - calculateColumnWidth(column) { - if (column.name != 'skill_level_id') { - return { - type: 'absolute', - value: '90px', - } - } - - return super.calculateColumnWidth(column); - } -} -SkillsListRenderer.template = 'hr_skills.SkillsListRenderer'; - -export class SkillsX2ManyField extends X2ManyField { - async onAdd({ context, editable } = {}) { - const employeeId = this.props.record.resId; - return super.onAdd({ - editable, - context: { - ...context, - default_employee_id: employeeId, - } - }); - } -} -SkillsX2ManyField.components = { - ...X2ManyField.components, - ListRenderer: SkillsListRenderer, -}; - -export const skillsX2ManyField = { - ...x2ManyField, - component: SkillsX2ManyField, -}; - -registry.category("fields").add("skills_one2many", skillsX2ManyField); diff --git a/addons/hr_skills/static/src/fields/skills_one2many/skills_one2many.js b/addons/hr_skills/static/src/fields/skills_one2many/skills_one2many.js new file mode 100644 index 00000000000..3963b0a4f36 --- /dev/null +++ b/addons/hr_skills/static/src/fields/skills_one2many/skills_one2many.js @@ -0,0 +1,114 @@ +/** @odoo-module */ + +import { X2ManyField, x2ManyField } from "@web/views/fields/x2many/x2many_field"; +import { + useX2ManyCrud, + useOpenX2ManyRecord, +} from "@web/views/fields/relational_utils"; +import { registry } from "@web/core/registry"; +import { _t } from "@web/core/l10n/translation"; +import { CommonSkillsListRenderer } from "../../views/skills_list_renderer"; +import { useService } from '@web/core/utils/hooks'; +import { onWillStart } from "@odoo/owl"; + + +export class SkillsListRenderer extends CommonSkillsListRenderer { + setup() { + super.setup(); + this.orm = useService('orm'); + this.action = useService("action"); + + onWillStart(async () => { + const res = await this.orm.searchCount('hr.skill', []); + this.anySkills = res > 0; + }); + } + + get groupBy() { + return 'skill_type_id'; + } + + async skillTypesAction() { + return this.actionService.doAction("hr_skills.hr_skill_type_action"); + } + + async openSkillsReport() { + // fetch id through employee or public.employee + const id = this.env.model.root.data.id || this.env.model.root.data.employee_id[0]; +- this.actionService.doAction({ + type: "ir.actions.act_window", + name: _t("Skills Report"), + res_model: "hr.employee.skill.log", + view_mode: "graph,tree", + views: [[false, "graph"], [false, "tree"]], + context: { + 'fill_temporal': 0, + }, + target: "current", + domain: [['employee_id', '=', id]], + }); + } + + calculateColumnWidth(column) { + if (column.name != 'skill_level_id') { + return { + type: 'absolute', + value: '90px', + } + } + + return super.calculateColumnWidth(column); + } +} +SkillsListRenderer.template = 'hr_skills.SkillsListRenderer'; + +export class SkillsX2ManyField extends X2ManyField { + setup() { + super.setup() + const { saveRecord, updateRecord } = useX2ManyCrud( + () => this.list, + this.isMany2Many + ); + + const openRecord = useOpenX2ManyRecord({ + resModel: this.list.resModel, + activeField: this.activeField, + activeActions: this.activeActions, + getList: () => this.list, + saveRecord: async (record) => { + await saveRecord(record); + await this.props.record.save(); + }, + updateRecord: updateRecord, + withParentId: this.props.widget !== "many2many", + }); + + this._openRecord = (params) => { + params.title = _t("Select Skills"); + openRecord({...params}); + }; + } + + async onAdd({ context, editable } = {}) { + const employeeId = this.props.record.resId; + return super.onAdd({ + editable, + context: { + ...context, + default_employee_id: employeeId, + } + }); + } +} + +SkillsX2ManyField.components = { + ...X2ManyField.components, + ListRenderer: SkillsListRenderer, +}; + +export const skillsX2ManyField = { + ...x2ManyField, + component: SkillsX2ManyField, +}; + +registry.category("fields").add("skills_one2many", skillsX2ManyField); diff --git a/addons/hr_skills/static/src/fields/skills_one2many.scss b/addons/hr_skills/static/src/fields/skills_one2many/skills_one2many.scss similarity index 99% rename from addons/hr_skills/static/src/fields/skills_one2many.scss rename to addons/hr_skills/static/src/fields/skills_one2many/skills_one2many.scss index ffc3ff66e9b..a8a15a1bc10 100644 --- a/addons/hr_skills/static/src/fields/skills_one2many.scss +++ b/addons/hr_skills/static/src/fields/skills_one2many/skills_one2many.scss @@ -21,3 +21,4 @@ table.o_skill_table, .o_hr_skills_dialog_form { } } } + diff --git a/addons/hr_skills/static/src/fields/skills_one2many.xml b/addons/hr_skills/static/src/fields/skills_one2many/skills_one2many.xml similarity index 50% rename from addons/hr_skills/static/src/fields/skills_one2many.xml rename to addons/hr_skills/static/src/fields/skills_one2many/skills_one2many.xml index a86084bd450..0f768afe973 100644 --- a/addons/hr_skills/static/src/fields/skills_one2many.xml +++ b/addons/hr_skills/static/src/fields/skills_one2many/skills_one2many.xml @@ -7,11 +7,39 @@ visibility: collapse; + +
+ Skills +
+
- + +
+

+ There are no skills defined in the library.
+ Why not try adding some ? +

+ +
+
+ +
+

You can add skills from our library to the employee profile.
+ If skills are missing, they can be created by an HR officer.

+
+ +
+
+
diff --git a/addons/hr_skills/static/src/scss/hr_employee.scss b/addons/hr_skills/static/src/scss/hr_employee.scss index 141c0117f16..7eb99e79f25 100644 --- a/addons/hr_skills/static/src/scss/hr_employee.scss +++ b/addons/hr_skills/static/src/scss/hr_employee.scss @@ -10,3 +10,33 @@ overflow-x: hidden!important; } } + +.o_hr_skill_type_form { + th[data-name="level_progress"] div span { + text-align: left !important; + } +} + +.o_list_renderer { + .o_list_table { + .o_data_row:not(.o_selected_row) .o_data_cell { + &.o_boolean_toggle_load_cell { + > .o_field_widget:not(.o_readonly_modifier) .form-check { + pointer-events: auto; + } + } + } + } +} + +.o_skill_level_tree{ + .o_list_renderer .o_list_table thead .o_list_number_th{ + text-align: start !important; + } + .o_progressbar_value .o_input { + width: 0 !important; + } + .flex-row-reverse { + flex-direction: inherit !important; + } +} diff --git a/addons/hr_skills/static/tests/tours/skills_tour.js b/addons/hr_skills/static/tests/tours/skills_tour.js index 7af9a9eb203..3868a532e57 100644 --- a/addons/hr_skills/static/tests/tours/skills_tour.js +++ b/addons/hr_skills/static/tests/tours/skills_tour.js @@ -73,7 +73,7 @@ registry.category("web_tour.tours").add('hr_skills_tour', { }, { content: "Add a new Skill", - trigger: ".o_field_skills_one2many button:contains('Create a new entry')", + trigger: ".o_field_skills_one2many button:contains('Pick a skill from the list')", }, { content: "Select Music", diff --git a/addons/hr_skills/views/hr_views.xml b/addons/hr_skills/views/hr_views.xml index 2025531f942..e2281b987cb 100644 --- a/addons/hr_skills/views/hr_views.xml +++ b/addons/hr_skills/views/hr_views.xml @@ -83,13 +83,12 @@
- - + - +
@@ -124,10 +123,10 @@
- - + + - + @@ -159,7 +158,7 @@ - +
@@ -167,7 +166,7 @@ - + @@ -224,11 +223,10 @@ hr.skill.level.tree hr.skill.level - + - - -