Initial commit: Core packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:45 +02:00
commit 12c29a983b
9512 changed files with 8379910 additions and 0 deletions

View file

@ -0,0 +1,27 @@
/** @odoo-module */
import { CharField } from "@web/views/fields/char/char_field";
import { registry } from "@web/core/registry";
const { useEffect, useRef } = owl;
class DescriptionPageField extends CharField {
setup() {
super.setup();
const inputRef = useRef("input");
useEffect(
(input) => {
if (input) {
input.classList.add("col");
}
},
() => [inputRef.el]
);
}
onExternalBtnClick() {
this.env.openRecord(this.props.record);
}
}
DescriptionPageField.template = "survey.DescriptionPageField";
registry.category("fields").add("survey_description_page", DescriptionPageField);

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="survey.DescriptionPageField" t-inherit="web.CharField" owl="1">
<xpath expr="//t[@t-else='']" position="replace">
<t t-else="">
<div class="input-group">
<t t-call="web.CharField"/>
<button type="button" title="Open section" class="btn oe_edit_only o_icon_button" t-on-click.stop="onExternalBtnClick">
<i class="fa fa-fw o_button_icon fa-external-link"/>
</button>
</div>
</t>
</xpath>
</t>
</templates>

View file

@ -0,0 +1,115 @@
/** @odoo-module */
import { makeContext } from "@web/core/context";
import { ListRenderer } from "@web/views/list/list_renderer";
const { useEffect } = owl;
export class QuestionPageListRenderer extends ListRenderer {
setup() {
super.setup();
this.discriminant = "is_page";
this.fieldsToShow = ["random_questions_count"];
this.titleField = "title";
useEffect(
(table) => {
if (table) {
table.classList.add("o_section_list_view");
}
},
() => [this.tableRef.el]
);
}
add(params) {
let editable = false;
if (params.context && !this.env.isSmall) {
const evaluatedContext = makeContext([params.context]);
if (evaluatedContext[`default_${this.discriminant}`]) {
editable = this.props.editable;
}
}
super.add({ ...params, editable });
}
getColumns(record) {
const columns = super.getColumns(record);
if (this.isSection(record)) {
return this.getSectionColumns(columns);
}
return columns;
}
getRowClass(record) {
const classNames = super.getRowClass(record).split(" ");
if (this.isSection(record)) {
classNames.push(`o_is_section`, `fw-bold`);
}
return classNames.join(" ");
}
getSectionColumns(columns) {
let titleColumnIndex = 0;
let found = false;
let colspan = 1
for (let index = 0; index < columns.length; index++) {
const col = columns[index];
if (!found && col.name !== this.titleField) {
continue;
}
if (!found) {
found = true;
titleColumnIndex = index;
continue;
}
if (col.type !== "field" || this.fieldsToShow.includes(col.name)) {
break;
}
colspan += 1;
}
const sectionColumns = columns.slice(0, titleColumnIndex + 1).concat(columns.slice(titleColumnIndex + colspan));
sectionColumns[titleColumnIndex] = {...sectionColumns[titleColumnIndex], colspan};
return sectionColumns;
}
isInlineEditable(record) {
return this.isSection(record) && this.props.editable;
}
isSection(record) {
return record.data[this.discriminant];
}
/**
*
* Overriding the method in order to identify the requested column based on its `name`
* instead of the exact object passed. This is necessary for section rows because the
* column object could have been replaced in `getSectionColumns` to add a `colspan`
* attribute.
*
* @override
*/
focusCell(column, forward = true) {
const actualColumn = column.name ? this.state.columns.find(
(col) => col.name === column.name
) : column;
super.focusCell(actualColumn, forward);
}
onCellKeydownEditMode(hotkey) {
switch (hotkey) {
case "enter":
case "tab":
case "shift+tab": {
this.props.list.unselectRecord(true);
return true;
}
}
return super.onCellKeydownEditMode(...arguments);
}
}

View file

@ -0,0 +1,26 @@
/** @odoo-module */
import { QuestionPageListRenderer } from "./question_page_list_renderer";
import { registry } from "@web/core/registry";
import { X2ManyField } from "@web/views/fields/x2many/x2many_field";
const { useSubEnv } = owl;
class QuestionPageOneToManyField extends X2ManyField {
setup() {
super.setup();
useSubEnv({
openRecord: (record) => this.openRecord(record),
});
}
}
QuestionPageOneToManyField.components = {
...X2ManyField.components,
ListRenderer: QuestionPageListRenderer,
};
QuestionPageOneToManyField.defaultProps = {
...X2ManyField.defaultProps,
editable: "bottom",
};
QuestionPageOneToManyField.additionalClasses = ['o_field_one2many'];
registry.category("fields").add("question_page_one2many", QuestionPageOneToManyField);