mirror of
https://github.com/bringout/oca-ocb-hr.git
synced 2026-04-26 13:31:59 +02:00
Initial commit: Hr packages
This commit is contained in:
commit
62531cd146
2820 changed files with 1432848 additions and 0 deletions
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
.o_hr_skills_group {
|
||||
padding: 0 calc(var(--gutter-x) * 1)!important;
|
||||
&:first-child {
|
||||
padding-left: calc(var(--gutter-x) * .5)!important;
|
||||
}
|
||||
&:last-child {
|
||||
padding-right: calc(var(--gutter-x) * .5)!important;
|
||||
}
|
||||
.o_list_renderer {
|
||||
overflow-x: hidden!important;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { GraphRenderer } from "@web/views/graph/graph_renderer";
|
||||
import { graphView } from "@web/views/graph/graph_view";
|
||||
|
||||
export class SkillsGraphRenderer extends GraphRenderer {
|
||||
getScaleOptions() {
|
||||
const scaleOptions = super.getScaleOptions();
|
||||
|
||||
if ('yAxes' in scaleOptions) {
|
||||
scaleOptions['yAxes'][0]['ticks']['suggestedMax'] = 100;
|
||||
}
|
||||
|
||||
return scaleOptions;
|
||||
}
|
||||
}
|
||||
|
||||
export const skillsGraphView = {
|
||||
...graphView,
|
||||
Renderer: SkillsGraphRenderer,
|
||||
};
|
||||
|
||||
registry.category("views").add("skills_graph", skillsGraphView);
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { ListRenderer } from "@web/views/list/list_renderer";
|
||||
|
||||
export class CommonSkillsListRenderer extends ListRenderer {
|
||||
get colspan() {
|
||||
const span = this.allColumns.length;
|
||||
if (this.isEditable) {
|
||||
return span + 1;
|
||||
}
|
||||
|
||||
return span;
|
||||
}
|
||||
|
||||
get groupBy() {
|
||||
return '';
|
||||
}
|
||||
|
||||
get groupedList() {
|
||||
const grouped = {};
|
||||
|
||||
for (const record of this.list.records) {
|
||||
const data = record.data;
|
||||
const group = data[this.groupBy];
|
||||
|
||||
if (grouped[group[1]] === undefined) {
|
||||
grouped[group[1]] = {
|
||||
id: parseInt(group[0]),
|
||||
name: group[1] || this.env._t('Other'),
|
||||
list: {
|
||||
records: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
grouped[group[1]].list.records.push(record);
|
||||
}
|
||||
return grouped;
|
||||
}
|
||||
|
||||
get showTable() {
|
||||
return this.props.list.records.length;
|
||||
}
|
||||
|
||||
get isEditable() {
|
||||
return this.props.editable !== false;
|
||||
}
|
||||
|
||||
async onCellClicked(record, column, ev) {
|
||||
if (!this.isEditable) {
|
||||
return;
|
||||
}
|
||||
|
||||
return await super.onCellClicked(record, column, ev);
|
||||
}
|
||||
}
|
||||
CommonSkillsListRenderer.rowsTemplate = "hr_skills.SkillsListRenderer.Rows";
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="hr_resume_data_row">
|
||||
<tr class="o_data_row cursor-default" t-attf-class="o_data_row #{is_last? 'o_data_row_last' : ''}" t-att-data-id="id">
|
||||
<t t-if="data.display_type === 'classic'">
|
||||
<td class="o_resume_timeline_cell position-relative pe-lg-2">
|
||||
<div class="rounded-circle bg-info position-relative"/>
|
||||
</td>
|
||||
<td class="o_data_cell pt-0 w-100">
|
||||
<div class="o_resume_line" t-att-data-id="id">
|
||||
<small class="o_resume_line_dates">
|
||||
<b t-esc="data.date_start"/> - <b t-esc="data.date_end"/>
|
||||
</small>
|
||||
<h4 class="o_resume_line_title mt-2" t-esc="data.name"/>
|
||||
<p t-if="data.description" class="o_resume_line_desc" t-esc="data.description"/>
|
||||
</div>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<t t-name="hr_trash_button">
|
||||
<td class="o_list_record_remove pe-3">
|
||||
<button name="delete" arial-label="Delete row" class="btn btn-link text-danger">
|
||||
<i class="fa fa-trash"/>
|
||||
</button>
|
||||
</td>
|
||||
</t>
|
||||
|
||||
<t t-name="hr_resume_group_row">
|
||||
<tr class="o_resume_group_header">
|
||||
<td class="o_group_name" colspan="100%"><span class="o_horizontal_separator my-0" t-esc="display_name"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<t t-name="group_add_item">
|
||||
<t t-set="empty" t-value="Object.keys(context).length == 2"/>
|
||||
|
||||
<div t-attf-class="o_field_x2many_list_row_add #{empty? 'd-block w-100' : 'd-inline float-end'}">
|
||||
<a href="#"
|
||||
role="button"
|
||||
t-attf-class="btn btn-secondary o-kanban-button-new #{empty? 'btn-primary mt-3' : 'btn-secondary btn-sm'}"
|
||||
t-attf-data-context="{{ context }}">
|
||||
<t t-if="empty">CREATE A NEW ENTRY</t>
|
||||
<t t-else="">ADD</t>
|
||||
</a>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="hr_skill_data_row">
|
||||
<tr class="o_data_row cursor-default" t-att-data-id="id">
|
||||
<td class="o_data_cell o_skill_cell w-100">
|
||||
<t t-esc="data.skill_id.data.display_name"/>
|
||||
</td>
|
||||
<td class="o_data_cell o_skill_cell pe-3">
|
||||
<t t-esc="data.skill_level_id.data.display_name"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<t t-name="hr_default_group_row">
|
||||
<tr class="o_group_header o_group_has_content">
|
||||
<td class="o_group_name border-0 pe-2" colspan="99">
|
||||
<b t-esc="display_name"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
|
||||
</templates>
|
||||
Loading…
Add table
Add a link
Reference in a new issue