Initial commit: Hr packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:50 +02:00
commit 62531cd146
2820 changed files with 1432848 additions and 0 deletions

View file

@ -0,0 +1,40 @@
/** @odoo-module */
import { registry } from "@web/core/registry";
import { formatDate } from "@web/core/l10n/dates";
import { SkillsX2ManyField } from "./skills_one2many";
import { CommonSkillsListRenderer } from "../views/skills_list_renderer";
export class ResumeListRenderer extends CommonSkillsListRenderer {
get groupBy() {
return 'line_type_id';
}
get colspan() {
if (this.props.activeActions) {
return 3;
}
return 2;
}
formatDate(date) {
return formatDate(date);
}
setDefaultColumnWidths() {}
}
ResumeListRenderer.template = 'hr_skills.ResumeListRenderer';
ResumeListRenderer.rowsTemplate = "hr_skills.ResumeListRenderer.Rows";
ResumeListRenderer.recordRowTemplate = "hr_skills.ResumeListRenderer.RecordRow";
export class ResumeX2ManyField extends SkillsX2ManyField {}
ResumeX2ManyField.components = {
...SkillsX2ManyField.components,
ListRenderer: ResumeListRenderer,
};
registry.category("fields")
.add("resume_one2many", ResumeX2ManyField);

View file

@ -0,0 +1,50 @@
.o_field_resume_one2many {
$o-hrs-timeline-entry-padding: .5rem;
$o-hrs-timeline-dot-size: .6rem;
.o_data_row {
border-bottom: none;
}
.o_data_row td {
padding: $o-hrs-timeline-entry-padding;
&.o_resume_timeline_cell {
div {
width: $o-hrs-timeline-dot-size;
height: $o-hrs-timeline-dot-size;
}
&:before {
@include o-position-absolute(0, $left: ($o-hrs-timeline-dot-size * .5 + $o-hrs-timeline-entry-padding));
width: 1px;
height: 100%;
margin-left: 2.1rem;
background-color: $border-color;
content: "";
}
}
}
.o_resume_line_title, .o_resume_line_desc {
white-space: normal;
}
.o_resume_line_title, .o_resume_line_dates {
line-height: 1;
}
.o_resume_group_header + .o_data_row .o_resume_timeline_cell:before {
top: $o-hrs-timeline-entry-padding;
}
.o_data_row.o_data_row_last {
.o_resume_line_desc {
margin-bottom: $headings-margin-bottom;
}
.o_resume_timeline_cell:before {
height: $o-hrs-timeline-entry-padding;
}
}
}

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<t t-name="hr_skills.ResumeListRenderer" owl="1" t-inherit-mode="primary" t-inherit="hr_skills.SkillsListRenderer">
<xpath expr="//table" position="attributes">
<attribute name="t-attf-class" add="table-borderless {{ !showTable ? 'd-none' : ''}}" remove="table-striped" separator=" "/>
</xpath>
<xpath expr="//thead/tr" position="replace">
<tr>
<th style="width: 32px; min-width: 32px;"></th>
<th class="w-100"></th>
<th t-if="isEditable" class="o_list_actions_header" style="width: 32px; min-width: 32px"></th>
</tr>
</xpath>
</t>
<t t-name="hr_skills.ResumeListRenderer.Rows" owl="1" t-inherit-mode="primary" t-inherit="hr_skills.SkillsListRenderer.Rows">
<xpath expr="//tr" position="attributes">
<attribute name="class" add="o_resume_group_header" separator=" "/>
</xpath>
<xpath expr="//th[hasclass('o_group_name')]" position="after">
<th></th>
</xpath>
</t>
<t t-name="hr_skills.ResumeListRenderer.RecordRow" owl="1" t-inherit-mode="primary" t-inherit="web.ListRenderer.RecordRow">
<xpath expr="//t[@t-foreach='getColumns(record)']" position="replace">
<t t-set="data" t-value="record.data"/>
<t t-if="data.display_type === 'classic'" id='row'>
<td class="o_resume_timeline_cell position-relative pe-lg-2" id='hiii'>
<div class="rounded-circle bg-info position-relative"/>
</td>
<td class="o_data_cell pt-0" t-on-click="(ev) => this.onCellClicked(record, null, ev)">
<div t-attf-class="o_resume_line {{data.display_type == 'certification' ? 'o_resume_line_display_certification' : ''}}" t-att-data-id="id">
<small class="o_resume_line_dates fw-bold">
<t t-out="formatDate(data.date_start)"/> -
<t t-if="data.date_end" t-out="formatDate(data.date_end)"/>
<t t-else="">Current</t>
</small>
<h4 class="o_resume_line_title mt-2" t-esc="data.name"/>
<p t-if="data.description" class="o_resume_line_desc" t-out="data.description" t-ref="link-target-blank"/>
</div>
</td>
</t>
</xpath>
</t>
</odoo>

View file

@ -0,0 +1,44 @@
/** @odoo-module */
import { 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,
};
registry.category("fields").add("skills_one2many", SkillsX2ManyField);

View file

@ -0,0 +1,23 @@
.o_field_skills_one2many, .o_field_resume_one2many {
.o_progress {
background: $gray-300;
border: 0;
height: 5px;
}
.o_progressbar_value {
font-size: $font-size-sm;
font-weight: bold;
}
}
table.o_skill_table, .o_hr_skills_dialog_form {
.o_progressbar {
display: flex;
align-items: center;
.o_progressbar_value input {
width: auto;
}
}
}

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<t t-name="hr_skills.SkillsListRenderer" owl="1" t-inherit-mode="primary" t-inherit="web.ListRenderer">
<xpath expr="//table" position="attributes">
<attribute name="t-attf-class" add="mb-1 {{ !isEditable ? 'cursor-default' : '' }} {{ !showTable ? 'd-none' : ''}} o_skill_table" separator=" "/>
</xpath>
<xpath expr="//thead" position="attributes">
<attribute name="style">visibility: collapse;</attribute>
</xpath>
<xpath expr="//table" position="after">
<t t-if="!showTable">
<button t-on-click="props.onAdd" class="btn btn-secondary ms-4 mt-3" role="button" t-if="isEditable">
Create a new entry
</button>
</t>
</xpath>
</t>
<t t-name="hr_skills.SkillsListRenderer.Rows" owl="1">
<t t-foreach="Object.entries(groupedList)" t-as="skill_group" t-key="skill_group[0]">
<tr class="o_group_has_content o_group_header">
<th tabindex="-1" class="o_group_name" t-att-colspan="colspan">
<div class="d-flex justify-content-between align-items-center">
<span t-esc="skill_group[1].name"/>
<button class="btn btn-secondary btn-sm"
t-if="isEditable"
t-on-click="() => props.onAdd({ context: { default_skill_type_id: skill_group[1].id }})"
role="button">ADD</button>
</div>
</th>
</tr>
<t t-foreach="skill_group[1].list.records" t-as="record" t-key="record.id">
<t t-set="group" t-value="skill_group[1]"/>
<t t-call="{{ constructor.recordRowTemplate }}"/>
</t>
</t>
</t>
</odoo>