英文:
Odoo 15 - Create widget based on hr_org_chart - SCSS don't visible od res.partner
问题
你的问题可能是由于SCSS文件的路径或命名问题导致的。请确保你的Odoo模块正确配置了SCSS文件的路径,以便在res.partner
模型中加载它们。
首先,确保company_chart
模块已经正确安装和启用。
然后,检查以下几个地方是否存在问题:
-
SCSS文件路径:确保
variables.scss
和company_chart.scss
文件位于正确的路径下,也就是在company_chart
模块的static/src/scss/
目录中。 -
SCSS文件命名:确保文件名的大小写和拼写与模块中的引用保持一致。比如,
variables.scss
应该与"company_chart/static/src/scss/variables.scss"
中的路径一致。 -
Manifest文件:在你的
__manifest__.py
文件中,确保'web.assets_backend'
部分包含了正确的SCSS文件路径:'web.assets_backend': [ 'company_chart/static/src/scss/company_chart.scss', # ... ],
同样,确保
'web._assets_primary_variables'
包含正确的variables.scss
路径:'web._assets_primary_variables': [ 'company_chart/static/src/scss/variables.scss', # ... ],
-
重新加载模块:如果你已经更正了文件路径和命名,并且
company_chart
模块已启用,请确保在Odoo中重新加载该模块,以确保新的SCSS文件能够生效。
如果仍然存在问题,可能需要检查Odoo日志以查看是否有与SCSS文件加载相关的错误消息。如果日志中没有错误消息,那么问题可能涉及到其他方面,需要更详细的调试和分析。
最后,确保在浏览器中清除缓存,以确保新的SCSS文件能够加载并应用到res.partner
模型中的小部件中。
英文:
I try to create widget to show company structure in odoo so i base on hr_org_chart (https://github.com/odoo/odoo/tree/15.0/addons/hr_org_chart), because it work as i want, with one thing show users but i want to see companies.
It start working me but on res.parner
my widget don't use scss:
when i use hr_org_widget in that same model (res.partner
) i also don't have scss:
in hr.employee
show properly:
My __manifest__.py
:
"depends": [
"partner_multi_relation",
"partner_multi_relation_customization",
],
"auto_install": True,
'data': [
"views/res_partner_views.xml",
],
"assets": {
"web._assets_primary_variables": [
"company_chart/static/src/scss/variables.scss",
],
"web.assets_backend": [
"company_chart/static/src/scss/company_chart.scss",
"company_chart/static/src/js/company_chart.js",
],
"web.assets_qweb": [
"company_chart/static/src/xml/**/*",
],
},
"license": "LGPL-3",
}
variables.scss
:
$o-hr-org-chart-bg: white;
$o-hr-org-chart-border-color: $o-brand-secondary;
$o-hr-org-chart-entry-v-gap: 6px;
$o-hr-org-chart-entry-pic-size: 46px;
$o-hr-org-chart-entry-line-w: 1px;
$o-hr-org-chart-entry-border-color: darken($o-hr-org-chart-bg, 25%);
// MIXINS
@mixin o-hr-org-chart-line {
content: "";
background-color: $o-hr-org-chart-bg;
border: 0px solid $o-hr-org-chart-entry-border-color;
}
company_chart.scss
:
// MOBILE LAYOUT CUSTOMIZATIONS
@include media-breakpoint-down(sm) {
#o_employee_right {
.o_org_chart_title {
font-size: 20px;
padding: 5px 0;
border-bottom: 1px solid $o-hr-org-chart-border-color;
}
}
}
// SMALL DESKTOP LAYOUT
@include media-breakpoint-up(md) {
#o_work_employee_container {
display: flex;
width: 100%;
}
#o_work_employee_main {
flex: 1 1 60%;
}
#o_employee_right {
flex: 0 1 35%;
margin-left: 2%;
padding-left: 2%;
border-left: 1px solid $o-hr-org-chart-border-color;
.o_org_chart_title {
color: gray("600");
}
}
}
// MEDIUM DESKTOP LAYOUT
@include media-breakpoint-up(lg) {
#o_employee_right {
flex: 0 1 33%;
}
}
// LARGE DESKTOP LAYOUT
@include media-breakpoint-up(xl) {
#o_employee_right {
flex: 0 1 30%;
}
}
#o_employee_right {
$tmp-gap-base: $o-hr-org-chart-entry-pic-size * 0.7;
// ORGANIGRAM LINES
.o_field_widget,
.o_org_chart_group_up,
.o_org_chart_group_down {
position: relative;
width: 100%;
}
.o_org_chart_group_up {
&:before {
@include o-hr-org-chart-line;
border-left-width: $o-hr-org-chart-entry-line-w;
height: calc(100% + #{$o-hr-org-chart-entry-pic-size * 0.5});
@include o-position-absolute(
$top: $o-hr-org-chart-entry-pic-size * 0.1 + 5px,
$left: $o-hr-org-chart-entry-pic-size * 0.5 -
$o-hr-org-chart-entry-line-w * 0.5
);
}
.o_org_chart_entry:last-of-type {
&:before {
@include o-hr-org-chart-line;
border-width: 0 0 $o-hr-org-chart-entry-line-w
$o-hr-org-chart-entry-line-w;
@include size(
($o-hr-org-chart-entry-pic-size * 0.5) -
($o-hr-org-chart-entry-v-gap * 2),
$o-hr-org-chart-entry-pic-size * 0.5 + $o-hr-org-chart-entry-v-gap * 2
);
@include o-position-absolute(
$left: $o-hr-org-chart-entry-pic-size * 0.5 -
$o-hr-org-chart-entry-line-w * 0.5,
$top: 100%
);
}
}
}
.o_org_chart_group_up + .o_org_chart_entry_self {
margin-left: $tmp-gap-base;
& + .o_org_chart_group_down {
padding-left: $tmp-gap-base * 2;
&:before {
margin-left: $tmp-gap-base;
}
}
}
.o_org_chart_group_down {
padding-left: $tmp-gap-base;
&:before {
@include o-hr-org-chart-line;
border-left-width: $o-hr-org-chart-entry-line-w;
height: 100%;
@include o-position-absolute(
$top: $o-hr-org-chart-entry-v-gap * -1,
$left: $tmp-gap-base * 0.5 + $o-hr-org-chart-entry-pic-size * 0.1 +
$o-hr-org-chart-entry-line-w * 0.5
);
}
.o_org_chart_entry {
&:before {
@include o-hr-org-chart-line;
border-top-width: $o-hr-org-chart-entry-line-w;
@include size($tmp-gap-base, 0);
@include o-position-absolute(
$left: $tmp-gap-base * -0.5 + $o-hr-org-chart-entry-pic-size * 0.1 +
$o-hr-org-chart-entry-line-w * 0.5,
$top: $o-hr-org-chart-entry-pic-size * 0.5
);
}
&:last-of-type {
&:before {
height: 50%;
}
}
&.o_org_chart_more {
margin-top: $o-hr-org-chart-entry-v-gap;
&:before {
top: 15px;
}
}
}
}
// ORGANIGRAM DESIGN
.o_org_chart_entry {
margin-bottom: $o-hr-org-chart-entry-v-gap;
overflow: visible;
margin-top: 0;
&,
.o_media_left,
.media-body {
position: relative;
}
.o_media_left {
padding-right: 10px;
}
.media-body {
vertical-align: middle;
.badge {
float: right;
cursor: pointer;
margin-right: 5px;
color: gray("600");
background: $o-hr-org-chart-bg;
border: 1px solid gray("600");
&:hover {
color: $o-brand-primary;
border-color: $o-brand-primary;
}
&:focus {
outline: none;
}
}
strong {
display: block;
line-height: 1.2;
font-size: 11px;
color: lighten(gray("600"), 15%);
}
}
.o_media_object {
display: block;
width: $o-hr-org-chart-entry-pic-size * 0.8;
height: $o-hr-org-chart-entry-pic-size * 0.8;
margin: $o-hr-org-chart-entry-pic-size * 0.1;
box-shadow: 0 0 0 $o-hr-org-chart-entry-line-w
darken($o-hr-org-chart-bg, 20%);
background-size: cover;
background-position: center center;
background-color: $o-view-background-color;
&.card {
height: 20px;
box-shadow: none;
border-color: transparent;
padding: 0;
position: relative;
color: $body-color;
.o_org_chart_show_more {
line-height: 13px;
}
&:hover {
border-color: $o-hr-org-chart-entry-border-color;
color: $o-brand-primary;
}
}
}
&.o_org_chart_entry_manager,
&.o_org_chart_entry_sub {
.o_media_left {
padding-right: 0;
}
.media-body > a {
padding-left: 10px;
max-width: 100%;
display: block;
.o_media_heading {
color: lighten(gray("600"), 5%);
font-size: 13px;
}
}
&:hover {
.o_media_object {
box-shadow: 0 0 0 $o-hr-org-chart-entry-line-w * 2
rgba($o-brand-primary, 0.6);
}
.media-body > a {
.o_media_heading {
color: $o-brand-primary;
}
strong {
color: lighten(gray("600"), 5%);
}
}
}
}
&.o_org_chart_entry_self {
&:not(:first-child) {
margin-top: $o-hr-org-chart-entry-v-gap * 1.5;
}
strong {
color: $text-muted;
}
.o_media_object {
width: $o-hr-org-chart-entry-pic-size;
height: $o-hr-org-chart-entry-pic-size;
margin: 0;
border: $o-hr-org-chart-entry-line-w * 2 solid $o-brand-primary;
box-shadow: inset 0 0 0 $o-hr-org-chart-entry-line-w * 2 white;
}
.media-body {
opacity: 1;
}
}
}
}
// POP OVER
.o_org_chart_popup.popover {
max-width: 400px;
margin-right: 5px;
.popover-header {
height: 47px;
line-height: 33px;
padding-right: 50px;
> a {
@include o-position-absolute($right: 14px);
}
span {
@include size(30px, 30px);
margin-right: 10px;
border-radius: 100%;
background-position: center;
background-size: cover;
float: left;
box-shadow: 0 1px 1px;
}
}
.table {
margin-bottom: 0;
}
}
// Right to Left specific style to flip the popover arrow
.o_rtl {
.o_org_chart_popup.popover .arrow {
left: 100%;
-webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
-moz-transform: matrix(-1, 0, 0, 1, 0, 0);
-o-transform: matrix(-1, 0, 0, 1, 0, 0);
transform: matrix(-1, 0, 0, 1, 0, 0);
}
}
company_chart.js
:
odoo.define("web.CompanyChart", function (require) {
"use strict";
var AbstractField = require("web.AbstractField");
var concurrency = require("web.concurrency");
var core = require("web.core");
var field_registry = require("web.field_registry");
var session = require("web.session");
var QWeb = core.qweb;
var _t = core._t;
var CompanyChart = AbstractField.extend({
events: {
"click .o_employee_redirect": "_onEmployeeRedirect",
"click .o_employee_sub_redirect": "_onEmployeeSubRedirect",
"click .o_employee_more_managers": "_onEmployeeMoreManager",
},
/**
* @constructor
* @override
*/
init: function (parent, options) {
this._super.apply(this, arguments);
this.dm = new concurrency.DropMisordered();
this.employee = null;
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Get the chart data through a rpc call.
*
* @private
* @param {integer} employee_id
* @returns {Promise}
*/
_getOrgData: function () {
var self = this;
return this.dm
.add(
this._rpc({
route: "/company/get_org_chart",
params: {
employee_id: this.employee,
context: session.user_context,
},
})
)
.then(function (data) {
return data;
});
},
/**
* Get subordonates of an employee through a rpc call.
*
* @private
* @param {integer} employee_id
* @returns {Promise}
*/
_getSubordinatesData: function (employee_id, type) {
return this.dm.add(
this._rpc({
route: "/company/get_subordinates",
params: {
employee_id: employee_id,
subordinates_type: type,
context: session.user_context,
},
})
);
},
/**
* @override
* @private
*/
_render: function () {
if (!this.recordData.id) {
return this.$el.html(
QWeb.render("company_chart", {
managers: [],
children: [],
})
);
} else if (!this.employee) {
// the widget is either dispayed in the context of a res.partner form or a res.users form
this.employee =
this.recordData.employee_ids !== undefined
? this.recordData.employee_ids.res_ids[0]
: this.recordData.id;
}
var self = this;
return this._getOrgData().then(function (orgData) {
if (_.isEmpty(orgData)) {
orgData = {
managers: [],
children: [],
};
}
orgData.view_employee_id = self.recordData.id;
console.log(orgData)
self.$el.html(QWeb.render("company_chart", orgData));
self.$('[data-toggle="popover"]').each(function () {
$(this).popover({
html: true,
title: function () {
var $title = $(
QWeb.render("company_chart_emp_popover_title", {
employee: {
name: $(this).data("emp-name"),
id: $(this).data("emp-id"),
},
})
);
$title.on(
"click",
".o_employee_redirect",
_.bind(self._onEmployeeRedirect, self)
);
return $title;
},
container: this,
placement: "left",
trigger: "focus",
content: function () {
var $content = $(
QWeb.render("company_chart_emp_popover_content", {
employee: {
id: $(this).data("emp-id"),
name: $(this).data("emp-name"),
direct_sub_count: parseInt(
$(this).data("emp-dir-subs"),
10
),
indirect_sub_count: parseInt(
$(this).data("emp-ind-subs"),
10
),
},
})
);
$content.on(
"click",
".o_employee_sub_redirect",
_.bind(self._onEmployeeSubRedirect, self)
);
return $content;
},
template: QWeb.render("company_chart_emp_popover", {}),
});
});
});
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
_onEmployeeMoreManager: function (event) {
event.preventDefault();
this.employee = parseInt($(event.currentTarget).data("employee-id"), 10);
this._render();
},
/**
* Redirect to the employee form view.
*
* @private
* @param {MouseEvent} event
* @returns {Promise} action loaded
*/
_onEmployeeRedirect: function (event) {
var self = this;
event.preventDefault();
var employee_id = parseInt(
$(event.currentTarget).data("employee-id"),
10
);
return this._rpc({
model: "res.partner",
method: "get_formview_action",
args: [employee_id],
}).then(function (action) {
return self.do_action(action);
});
},
/**
* Redirect to the sub employee form view.
*
* @private
* @param {MouseEvent} event
* @returns {Promise} action loaded
*/
_onEmployeeSubRedirect: function (event) {
event.preventDefault();
var employee_id = parseInt(
$(event.currentTarget).data("employee-id"),
10
);
var employee_name = $(event.currentTarget).data("employee-name");
var type = $(event.currentTarget).data("type") || "direct";
var self = this;
if (employee_id) {
this._getSubordinatesData(employee_id, type).then(function (data) {
var domain = [["id", "in", data]];
return self
._rpc({
model: "res.partner",
method: "get_formview_action",
args: [employee_id],
})
.then(function (action) {
action = _.extend(action, {
name: _t("Team"),
view_mode: "kanban,list,form",
views: [
[false, "kanban"],
[false, "list"],
[false, "form"],
],
domain: domain,
context: {
default_parent_id: employee_id,
},
});
delete action.res_id;
return self.do_action(action);
});
});
}
},
});
field_registry.add("company_chart", CompanyChart);
return CompanyChart;
});
What i do wrong that scss from assets don't load at my widget in res.partner
?
答案1
得分: 0
我忘记在XML中添加了以下内容:<div id="o_employee_right">
在表单视图中:
<div id="o_employee_right">
<h4 class="o_org_chart_title mb16 mt0">组织图表</h4>
<field name="partner_relations" widget="company_chart"/>
</div>
现在它可以工作了!
英文:
Ok i forgot to add in xml : <div id="o_employee_right">
in form view:
<div id="o_employee_right">
<h4 class="o_org_chart_title mb16 mt0">Organization Chart</h4>
<field name="partner_relations" widget="company_chart"/>
</div>
Now it works!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论