kpi fix
This commit is contained in:
parent
fa01ac0106
commit
8a2020d893
|
|
@ -27,7 +27,7 @@ export class KpiFormulaField extends Component {
|
||||||
onWillStart(async () => {
|
onWillStart(async () => {
|
||||||
try {
|
try {
|
||||||
// Load draggabilly library
|
// Load draggabilly library
|
||||||
await loadJS("kpi_scorecard/static/lib/draggabilly/draggabilly.pkgd.js");
|
await loadJS("/kpi_scorecard/static/lib/draggabilly/draggabilly.pkgd.js");
|
||||||
await this.loadFormulaData();
|
await this.loadFormulaData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error loading KPI formula:", error);
|
console.error("Error loading KPI formula:", error);
|
||||||
|
|
@ -51,12 +51,14 @@ export class KpiFormulaField extends Component {
|
||||||
|
|
||||||
async loadFormulaData() {
|
async loadFormulaData() {
|
||||||
try {
|
try {
|
||||||
|
const fieldValue = this.props.record.data[this.props.name] || "";
|
||||||
|
|
||||||
if (this.props.readonly) {
|
if (this.props.readonly) {
|
||||||
// Load formula parts for readonly display
|
// Load formula parts for readonly display
|
||||||
this.state.formulaParts = await this.orm.call(
|
this.state.formulaParts = await this.orm.call(
|
||||||
"kpi.item",
|
"kpi.item",
|
||||||
"action_render_formula",
|
"action_render_formula",
|
||||||
[this.props.value || ""]
|
[fieldValue]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Load variables for edit mode
|
// Load variables for edit mode
|
||||||
|
|
@ -65,13 +67,14 @@ export class KpiFormulaField extends Component {
|
||||||
this.state.variables = await this.orm.call(
|
this.state.variables = await this.orm.call(
|
||||||
"kpi.item",
|
"kpi.item",
|
||||||
"action_return_measures",
|
"action_return_measures",
|
||||||
[[recordId], this.props.value || ""]
|
[[recordId], fieldValue]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.state.isLoaded = true;
|
this.state.isLoaded = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error loading formula data:", error);
|
console.error("Error loading formula data:", error);
|
||||||
|
this.state.isLoaded = true; // Set to true even on error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +131,8 @@ export class KpiFormulaField extends Component {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.props.update(formula.trim());
|
// Update using Odoo 18 method
|
||||||
|
this.props.record.update({ [this.props.name]: formula.trim() });
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearch(ev) {
|
onSearch(ev) {
|
||||||
|
|
@ -176,5 +180,7 @@ export class KpiFormulaField extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the field widget
|
// ✅ الطريقة الصحيحة للتسجيل في Odoo 18
|
||||||
registry.category("fields").add("kpi_formula", KpiFormulaField);
|
registry.category("fields").add("kpi_formula", {
|
||||||
|
component: KpiFormulaField,
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@
|
||||||
<templates>
|
<templates>
|
||||||
<t t-name="kpi_scorecard.KpiFormulaField">
|
<t t-name="kpi_scorecard.KpiFormulaField">
|
||||||
<div class="o_field_kpi_formula" t-ref="formula">
|
<div class="o_field_kpi_formula" t-ref="formula">
|
||||||
|
<!-- Readonly Mode -->
|
||||||
<t t-if="props.readonly">
|
<t t-if="props.readonly">
|
||||||
<div class="formula-readonly">
|
<div class="formula-readonly">
|
||||||
<t t-if="state.formulaParts and state.formulaParts.length">
|
<t t-if="state.formulaParts and state.formulaParts.length">
|
||||||
<t t-foreach="state.formulaParts" t-as="part" t-key="part_index">
|
<t t-foreach="state.formulaParts" t-as="part" t-key="part_index">
|
||||||
<span t-att-class="'formula-part ' + (part.type || '').toLowerCase()"
|
<span t-att-class="'formula-part ' + (part.type || '').toLowerCase()"
|
||||||
t-att-title="part.name">
|
t-att-title="part.name"
|
||||||
<t t-esc="part.name"/>
|
t-esc="part.name"/>
|
||||||
</span>
|
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
<t t-else="">
|
<t t-else="">
|
||||||
|
|
@ -17,51 +17,74 @@
|
||||||
</t>
|
</t>
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
|
|
||||||
|
<!-- Edit Mode -->
|
||||||
<t t-else="">
|
<t t-else="">
|
||||||
<div class="formula-editor" t-if="state.isLoaded">
|
<div class="formula-editor" t-if="state.isLoaded">
|
||||||
|
<!-- Search Input -->
|
||||||
<div class="formula-search mb-2">
|
<div class="formula-search mb-2">
|
||||||
<input type="text"
|
<input type="text"
|
||||||
class="kpi-search-input form-control"
|
class="kpi-search-input form-control"
|
||||||
placeholder="Search..."
|
placeholder="Search..."
|
||||||
t-on-keyup="onSearch"/>
|
t-on-input="onSearch"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<!-- Left Column: Variables and Operators -->
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
<!-- Variables Section -->
|
||||||
<div class="formula-variables" t-if="state.variables">
|
<div class="formula-variables" t-if="state.variables">
|
||||||
<t t-foreach="state.variables.sections || []" t-as="section" t-key="section_index">
|
<t t-if="state.variables.sections">
|
||||||
<div class="variable-section mb-3">
|
<t t-foreach="state.variables.sections" t-as="section" t-key="section_index">
|
||||||
<h6 t-esc="section.name" class="text-primary"/>
|
<div class="variable-section mb-3">
|
||||||
<div class="variable-items">
|
<h6 t-esc="section.name" class="text-primary"/>
|
||||||
<t t-foreach="section.items || []" t-as="item" t-key="item_index">
|
<div class="variable-items">
|
||||||
<div class="formula-item draggable btn btn-sm btn-outline-secondary m-1"
|
<t t-if="section.items">
|
||||||
t-att-data-formula="item.formula"
|
<t t-foreach="section.items" t-as="item" t-key="item_index">
|
||||||
t-att-data-part-id="item.id">
|
<div class="formula-item draggable btn btn-sm btn-outline-secondary m-1"
|
||||||
<span t-esc="item.name"/>
|
t-att-data-formula="item.formula"
|
||||||
<button class="btn btn-sm btn-danger ms-1"
|
t-att-data-part-id="item.id">
|
||||||
t-on-click="() => onDeletePart(item.id)"
|
<span t-esc="item.name"/>
|
||||||
type="button">
|
<button class="btn btn-sm btn-danger ms-1"
|
||||||
<i class="fa fa-times"/>
|
t-on-click.stop="(ev) => this.onDeletePart(item.id)"
|
||||||
</button>
|
type="button">
|
||||||
</div>
|
<i class="fa fa-times"/>
|
||||||
</t>
|
</button>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Operators Section -->
|
||||||
<div class="formula-operators mb-3">
|
<div class="formula-operators mb-3">
|
||||||
<h6 class="text-primary">Operators</h6>
|
<h6 class="text-primary">Operators</h6>
|
||||||
<button t-foreach="['+', '-', '*', '/', '(', ')']"
|
<div class="d-flex flex-wrap gap-1">
|
||||||
t-as="op"
|
<button class="btn btn-secondary btn-sm"
|
||||||
t-key="op"
|
t-on-click="() => this.onAddOperator('+')"
|
||||||
class="btn btn-secondary btn-sm m-1"
|
type="button">+</button>
|
||||||
t-on-click="() => onAddOperator(op)"
|
<button class="btn btn-secondary btn-sm"
|
||||||
type="button">
|
t-on-click="() => this.onAddOperator('-')"
|
||||||
<t t-esc="op"/>
|
type="button">-</button>
|
||||||
</button>
|
<button class="btn btn-secondary btn-sm"
|
||||||
|
t-on-click="() => this.onAddOperator('*')"
|
||||||
|
type="button">*</button>
|
||||||
|
<button class="btn btn-secondary btn-sm"
|
||||||
|
t-on-click="() => this.onAddOperator('/')"
|
||||||
|
type="button">/</button>
|
||||||
|
<button class="btn btn-secondary btn-sm"
|
||||||
|
t-on-click="() => this.onAddOperator('(')"
|
||||||
|
type="button">(</button>
|
||||||
|
<button class="btn btn-secondary btn-sm"
|
||||||
|
t-on-click="() => this.onAddOperator(')')"
|
||||||
|
type="button">)</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Number Input Section -->
|
||||||
<div class="formula-number mb-3">
|
<div class="formula-number mb-3">
|
||||||
<h6 class="text-primary">Number</h6>
|
<h6 class="text-primary">Number</h6>
|
||||||
<input type="number"
|
<input type="number"
|
||||||
|
|
@ -71,6 +94,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Right Column: Formula Builder -->
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h6 class="text-primary">Formula Builder</h6>
|
<h6 class="text-primary">Formula Builder</h6>
|
||||||
<div class="formula-drop-zone border rounded p-3 mb-3"
|
<div class="formula-drop-zone border rounded p-3 mb-3"
|
||||||
|
|
@ -82,16 +106,117 @@
|
||||||
<label class="form-label">Current Formula:</label>
|
<label class="form-label">Current Formula:</label>
|
||||||
<input type="text"
|
<input type="text"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
t-att-value="props.value || ''"
|
t-att-value="props.record.data[props.name] || ''"
|
||||||
readonly="readonly"/>
|
readonly="readonly"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Loading State -->
|
||||||
<div t-else="" class="text-center text-muted p-3">
|
<div t-else="" class="text-center text-muted p-3">
|
||||||
|
<i class="fa fa-spinner fa-spin me-2"/>
|
||||||
Loading formula editor...
|
Loading formula editor...
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
</templates>
|
</templates>
|
||||||
|
|
||||||
|
<!--<?xml version="1.0" encoding="UTF-8"?>-->
|
||||||
|
<!--<templates>-->
|
||||||
|
<!-- <t t-name="kpi_scorecard.KpiFormulaField">-->
|
||||||
|
<!-- <div class="o_field_kpi_formula" t-ref="formula">-->
|
||||||
|
<!-- <t t-if="props.readonly">-->
|
||||||
|
<!-- <div class="formula-readonly">-->
|
||||||
|
<!-- <t t-if="state.formulaParts and state.formulaParts.length">-->
|
||||||
|
<!-- <t t-foreach="state.formulaParts" t-as="part" t-key="part_index">-->
|
||||||
|
<!-- <span t-att-class="'formula-part ' + (part.type || '').toLowerCase()"-->
|
||||||
|
<!-- t-att-title="part.name">-->
|
||||||
|
<!-- <t t-esc="part.name"/>-->
|
||||||
|
<!-- </span>-->
|
||||||
|
<!-- </t>-->
|
||||||
|
<!-- </t>-->
|
||||||
|
<!-- <t t-else="">-->
|
||||||
|
<!-- <span class="text-muted">No formula defined</span>-->
|
||||||
|
<!-- </t>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </t>-->
|
||||||
|
<!-- <t t-else="">-->
|
||||||
|
<!-- <div class="formula-editor" t-if="state.isLoaded">-->
|
||||||
|
<!-- <div class="formula-search mb-2">-->
|
||||||
|
<!-- <input type="text"-->
|
||||||
|
<!-- class="kpi-search-input form-control"-->
|
||||||
|
<!-- placeholder="Search..."-->
|
||||||
|
<!-- t-on-keyup="onSearch"/>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div class="row">-->
|
||||||
|
<!-- <div class="col-md-6">-->
|
||||||
|
<!-- <div class="formula-variables" t-if="state.variables">-->
|
||||||
|
<!-- <t t-foreach="state.variables.sections || []" t-as="section" t-key="section_index">-->
|
||||||
|
<!-- <div class="variable-section mb-3">-->
|
||||||
|
<!-- <h6 t-esc="section.name" class="text-primary"/>-->
|
||||||
|
<!-- <div class="variable-items">-->
|
||||||
|
<!-- <t t-foreach="section.items || []" t-as="item" t-key="item_index">-->
|
||||||
|
<!-- <div class="formula-item draggable btn btn-sm btn-outline-secondary m-1"-->
|
||||||
|
<!-- t-att-data-formula="item.formula"-->
|
||||||
|
<!-- t-att-data-part-id="item.id">-->
|
||||||
|
<!-- <span t-esc="item.name"/>-->
|
||||||
|
<!-- <button class="btn btn-sm btn-danger ms-1"-->
|
||||||
|
<!-- t-on-click="() => onDeletePart(item.id)"-->
|
||||||
|
<!-- type="button">-->
|
||||||
|
<!-- <i class="fa fa-times"/>-->
|
||||||
|
<!-- </button>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </t>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </t>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div class="formula-operators mb-3">-->
|
||||||
|
<!-- <h6 class="text-primary">Operators</h6>-->
|
||||||
|
<!-- <button t-foreach="['+', '-', '*', '/', '(', ')']"-->
|
||||||
|
<!-- t-as="op"-->
|
||||||
|
<!-- t-key="op"-->
|
||||||
|
<!-- class="btn btn-secondary btn-sm m-1"-->
|
||||||
|
<!-- t-on-click="() => onAddOperator(op)"-->
|
||||||
|
<!-- type="button">-->
|
||||||
|
<!-- <t t-esc="op"/>-->
|
||||||
|
<!-- </button>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div class="formula-number mb-3">-->
|
||||||
|
<!-- <h6 class="text-primary">Number</h6>-->
|
||||||
|
<!-- <input type="number"-->
|
||||||
|
<!-- class="kpi-number-input form-control"-->
|
||||||
|
<!-- placeholder="Enter number..."-->
|
||||||
|
<!-- t-on-change="onChangeNumber"/>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div class="col-md-6">-->
|
||||||
|
<!-- <h6 class="text-primary">Formula Builder</h6>-->
|
||||||
|
<!-- <div class="formula-drop-zone border rounded p-3 mb-3"-->
|
||||||
|
<!-- style="min-height: 100px; background-color: #f8f9fa;">-->
|
||||||
|
<!-- <small class="text-muted">Drag formula parts here</small>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div class="current-formula">-->
|
||||||
|
<!-- <label class="form-label">Current Formula:</label>-->
|
||||||
|
<!-- <input type="text"-->
|
||||||
|
<!-- class="form-control"-->
|
||||||
|
<!-- t-att-value="props.value || ''"-->
|
||||||
|
<!-- readonly="readonly"/>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <div t-else="" class="text-center text-muted p-3">-->
|
||||||
|
<!-- Loading formula editor...-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </t>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </t>-->
|
||||||
|
<!--</templates>-->
|
||||||
Loading…
Reference in New Issue