update modules
|
|
@ -10,14 +10,12 @@
|
|||
#################################################################################
|
||||
{
|
||||
'name': 'Advanced Web Domain Widget',
|
||||
'version': '14.0.2.0.0',
|
||||
'version': '14.0.3.0.0',
|
||||
'summary': 'Set all relational fields domain by selecting its records unsing `in, not in` operator.',
|
||||
'sequence': 1,
|
||||
'author': 'Terabits Technolab',
|
||||
'category': 'Odex25-base',
|
||||
|
||||
'license': 'OPL-1',
|
||||
'website': 'https://www.terabits.xyz',
|
||||
'website': 'https://www.terabits.xyz/apps/14.0/advanced_web_domain_widget',
|
||||
'description':"""
|
||||
|
||||
""",
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
from . import domain_prepare
|
||||
from . import models
|
||||
|
|
@ -5,11 +5,9 @@ class BaseModel(models.AbstractModel):
|
|||
_inherit = 'base'
|
||||
|
||||
@api.model
|
||||
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, **read_kwargs):
|
||||
res = super().search_read(domain, fields, offset, limit, order, **read_kwargs)
|
||||
if self._context.get('web_domain_widget') and hasattr(self, 'company_id'):
|
||||
for rec in res:
|
||||
rec.update({'company_name': self.browse(rec.get('id')).company_id.name})
|
||||
|
||||
return res
|
||||
def get_widget_name(self, domain=None, fields=None, offset=0, limit=None, order=None, **read_kwargs):
|
||||
return self.sudo().search_read(domain, ['id', 'display_name'], offset, limit, order)
|
||||
|
||||
@api.model
|
||||
def get_widget_count(self, args):
|
||||
return self.sudo().search_count(args)
|
||||
|
Before Width: | Height: | Size: 401 KiB After Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 202 KiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 307 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 701 KiB |
|
After Width: | Height: | Size: 182 KiB |
|
After Width: | Height: | Size: 389 B |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 1.2 MiB |
|
|
@ -26,238 +26,140 @@
|
|||
|
||||
<div id="module-description">
|
||||
<!-- Keep From Here -->
|
||||
|
||||
<img class="img img-responsive center-block" style="border-top-left-radius:10px; border-top-right-radius:10px" src="https://www.terabits.xyz/index/img/advanced_web_domain_widget/14.0/img.png">
|
||||
<div class="container">
|
||||
<div class="oe_styling_v8">
|
||||
|
||||
<!-- Nav START -->
|
||||
<div class="position-relative my-5">
|
||||
<div class="row no-gutters shadow-sm" style="border-radius: 14px">
|
||||
<nav class="
|
||||
navbar navbar-expand-lg navbar-light
|
||||
bg-light
|
||||
overflow-hidden
|
||||
w-100
|
||||
" style="
|
||||
background-color: #fff !important;
|
||||
border-radius: 14px;
|
||||
padding: 0px;
|
||||
border: 1px solid rgb(0 0 0 / 12%);
|
||||
">
|
||||
<span class="navbar-brand" style="
|
||||
background-color: #0A0A0A;
|
||||
padding: 18px 20px 11px 20px;
|
||||
color:white;
|
||||
height: 100%;
|
||||
">
|
||||
Terabits
|
||||
</span>
|
||||
<!-- elearning post starts -->
|
||||
|
||||
<section class="blog_post_01">
|
||||
<div class="position-relative w-100" style="display: inline-grid;">
|
||||
<img src="img/screens/domain_bg_img_01.png"
|
||||
class="img-responsive img img-fluid w-100 h-100 img img-fluid position-absolute left_0" />
|
||||
|
||||
<div class="ml-auto text-right" id="navbarNav">
|
||||
<ul class="nav navbar-nav ml-auto text-right">
|
||||
<div class="position-relative row justify-content-center align-items-center"
|
||||
style="padding: 20px 10px 40px 10px;">
|
||||
<div class="col-12 my-3 px-5">
|
||||
<div class="header-img">
|
||||
<img src="img/screens/domain_header_img.png" class="img img-fluid w-100"
|
||||
style="width: 100% !important;" />
|
||||
</div>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="blg-01-content text-center my-5">
|
||||
<h1
|
||||
style="font-family: 'Inter', sans-serif; font-size: 45px; font-weight: 700;line-height: 51px;color: #151765;">
|
||||
Advanced web domian widget
|
||||
</h1>
|
||||
<h3
|
||||
style="font-family: 'Inter', sans-serif; font-size: 22px; font-weight: 600;line-height: 31px; color: #1947AE;margin-top: 10px;">
|
||||
"Now use the feature of select any models record in domain while using any relational field."
|
||||
</h3>
|
||||
<p
|
||||
style="font-family: 'Inter', sans-serif; font-size: 18px; font-weight: 500;line-height: 27px; color: #000000; margin-top: 20px;">
|
||||
Odoo base domain widget allows you to only match value or id while user wants to create <br/>
|
||||
domain using any relational fields. So, user confused when model has multiple record's id <br/>
|
||||
and he/she does't remembered. So, we have simplified that by showing models record to <br/>
|
||||
the user. so, he/she can select by finding record and select it. our module will autometic <br/>
|
||||
adds ids of selected records in domain. To select related model's record and create <br/>
|
||||
domain, we allowed additional two domain operators ('in', 'not in').
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="ml-auto text-right" id="navbarNav">
|
||||
<ul class="nav navbar-nav ml-auto text-right">
|
||||
|
||||
|
||||
|
||||
<li class="nav-item" style="padding: 17px 10px">
|
||||
<span class="badge badge-pill badge-primary" style="
|
||||
background-color: #7c7bad;
|
||||
border: 1px solid #7c7bbb4f;
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
margin: 3px;
|
||||
padding-left: 23px;
|
||||
">
|
||||
<i class="fa fa-check-circle position-absolute" style="
|
||||
font-size: 16px;
|
||||
margin-left: -17px;
|
||||
margin-top: -2px;
|
||||
"></i>
|
||||
Community
|
||||
</span>
|
||||
<span class="badge badge-pill badge-primary" style="
|
||||
background-color: #660066;
|
||||
border: 1px solid rgb(144 90 123 / 29%);
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
margin: 3px;
|
||||
padding-left: 23px;
|
||||
">
|
||||
<i class="fa fa-check-circle position-absolute" style="
|
||||
font-size: 16px;
|
||||
margin-left: -17px;
|
||||
margin-top: -2px;
|
||||
"></i>
|
||||
Enterprise
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<span class="badge badge-pill badge-primary" style="
|
||||
background-color: #330033;
|
||||
border: 1px solid rgb(144 90 123 / 29%);
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
margin: 3px;
|
||||
padding-left: 23px;
|
||||
">
|
||||
<i class="fa fa-check-circle position-absolute" style="
|
||||
font-size: 16px;
|
||||
margin-left: -17px;
|
||||
margin-top: -2px;
|
||||
"></i>
|
||||
Odoo.sh
|
||||
</span>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Nav END -->
|
||||
|
||||
<!-- main intro -->
|
||||
<div class="position-relative">
|
||||
<div class="row pb32 pt32 align-items-center bg-white my-5 shadow" style="border-radius: 14px">
|
||||
<div class="col-12">
|
||||
<h2 class="oe_slogan"
|
||||
style="color:#660066; font-family:Montserrat; font-weight:700; text-align:center; text-transform:uppercase; margin-bottom:18px; margin-top:18px">
|
||||
Advanced Web Domain Widget
|
||||
</h2>
|
||||
<img class="img img-responsive center-block"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="https://www.terabits.xyz/index/img/advanced_web_domain_widget/14.0/img.png">
|
||||
<h3 style="color: #3c4858;text-align: center;margin-bottom:18px;">
|
||||
<span style="color: #000066">
|
||||
"Now use the feature of select any models record in domain while using any
|
||||
relational field."
|
||||
</span>
|
||||
</h3>
|
||||
|
||||
<p class="mb16 text-black-dark px-3"
|
||||
style="font-family:Roboto; text-align: justify; font-weight:normal; color:#11335b; font-size:16px">
|
||||
Odoo base domain widget allows you to only match value or id while user wants to create
|
||||
domain using any relational fields. So, user confused when model has multiple record's
|
||||
id and he/she does't remembered. So, we have simplified that by showing models
|
||||
record to the user. so, he/she can select by finding record and select it. our module
|
||||
will autometic adds ids of selected records in domain. To select related model's record
|
||||
and create domain, we allowed additional
|
||||
two domain operators ('in', 'not in').
|
||||
|
||||
</p>
|
||||
|
||||
<!-- <section id="ah_module_heading" style="padding-top:30px">
|
||||
<div class="container">
|
||||
<div class="ah_center text-center">
|
||||
<h2 align="center">
|
||||
<a style="background-color:#EF233C; color:white; border-color:#EF233C;
|
||||
box-shadow: 0 3px 6px 0px #df4a4f75; padding:1%; text-decoration:none; border-radius:6px; display:inline-block" class="btn btn-success btn-lg" href="https://youtu.be/rgW9rnD0sJM" target="_blank" savefrom_lm_index="0" savefrom_lm="1"><span class="o_ripple d-block position-absolute rounded-circle" style="height:398px; width:398px"></span>How it works? click here to watch a demo
|
||||
</a><span style="padding: 0; margin: 0; margin-left: 5px;"></span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section> -->
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- elearning post end -->
|
||||
|
||||
<!-- features highlight -->
|
||||
<section class="oe_container pb-5">
|
||||
<div class="mt64 mb64">
|
||||
<h2 style="color:#660066; font-family:'Montserrat'; text-align:center; margin:25px auto; text-transform:uppercase"
|
||||
class="oe_slogan">
|
||||
<b>Highlights</b>
|
||||
</h2>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-sm-12 mt32">
|
||||
<div class="container shadow"
|
||||
style="border-radius:10px; padding:10px 0px;height: 100%;">
|
||||
<div class="col-md-3" style="float:left">
|
||||
<img class="img img-responsive" src="img/feature2.png">
|
||||
</div>
|
||||
<div class="col-md-9" style="padding-left:0; float:left; width:70%">
|
||||
<h3 class="mt16 mb0"
|
||||
style="font-family:Roboto; font-weight:500; font-size:20px">Select any
|
||||
models records</h3>
|
||||
<p class=" mt8" style="font-family:Roboto">
|
||||
Easy to create domain of relational fields by selecting any models record in
|
||||
domain. We provide additional operators ('in' and 'not in') to create
|
||||
relational fields domain.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-sm-12 mt32">
|
||||
<div class="container shadow"
|
||||
style="border-radius:10px; padding:10px 0px;height: 100%;">
|
||||
<div class="col-md-3" style="float:left">
|
||||
<img class="img img-responsive" src="img/feature7.png">
|
||||
</div>
|
||||
<div class="col-md-9" style="padding-left:0; float:left; width:70%">
|
||||
<h3 class="mt16 mb0"
|
||||
style="font-family:Roboto; font-weight:500; font-size:20px">Autometic id add
|
||||
in domain</h3>
|
||||
<p class=" mt8" style="font-family:Roboto">
|
||||
When user select models records from popup, there will generate tags of
|
||||
record's names and add records id in domain.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="domain_features_02">
|
||||
<div class="position-relative w-100" style="display: inline-grid;">
|
||||
<img src="img/screens/domain_bg_img_02.png" class="img-responsive w-100 h-100 img img-fluid position-absolute left_0"/>
|
||||
|
||||
<div class="position-relative row justify-content-center align-items-center" style="padding: 20px 10px 40px 10px;">
|
||||
<div class="col-12 my-3 px-5">
|
||||
<div class="title text-center">
|
||||
<h2 style="font-family: 'Inter', sans-serif; font-size: 45px; font-weight: 700;line-height: 61px;color: #151765;">
|
||||
Features
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-around align-items-center mt-4">
|
||||
<div style="background-color: #F1F7FF; padding: 20px 40px 20px 25px; border-radius: 8px; width: 45% !important; height: 100% !important;" class="shadow-sm">
|
||||
<h6 style="font-family: 'Inter', sans-serif; font-size: 25px; font-weight: 600;line-height: 36px;color: #151765;">
|
||||
Select any models records
|
||||
</h6>
|
||||
<div class="mt-3">
|
||||
<p style="font-family: 'Inter', sans-serif; font-size: 17px; font-weight: 500;line-height: 24px;color: #151765;">
|
||||
Easy to create domain of relational fields by <br/>
|
||||
selecting any models record in domain. We <br/>
|
||||
provide additional operators ('in' and 'not in') <br/>
|
||||
to create relational fields domain.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="background-color: #F1F7FF; padding: 32px 40px 32px 25px; border-radius: 8px; width: 45% !important; height: 100% !important;" class="shadow-sm">
|
||||
<h6 style="font-family: 'Inter', sans-serif; font-size: 25px; font-weight: 600;line-height: 36px;color: #151765;">
|
||||
Autometic id add in domain
|
||||
</h6>
|
||||
<div class="mt-3">
|
||||
<p style="font-family: 'Inter', sans-serif; font-size: 17px; font-weight: 500;line-height: 24px;color: #151765;">
|
||||
When user select models records from popup, <br/>
|
||||
there will generate tags of record's names and <br/>
|
||||
add records id in domain.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- features highlight -->
|
||||
|
||||
<!-- tabs -->
|
||||
<section class="info-tabs">
|
||||
<section class="info-tabs mt-5">
|
||||
<div>
|
||||
<div class="tabs">
|
||||
<div class="justify-content-center d-flex">
|
||||
<!-- Nav pills -->
|
||||
<ul class="nav my-3 o_tab_nav justify-content-center"
|
||||
style="border-radius:6px 6px; background-color:transparent">
|
||||
<li class="nav-item mx-1" style="border-radius:6px 0 0 6px">
|
||||
<a class="nav-link px-md-4 list-group-item-default list-group-item-action"
|
||||
id="v-guide-tab" data-bs-toggle="pill" aria-controls="v-guide" href="#pills-guide"
|
||||
style="border-radius:6px; opacity:1; padding:16px">USERGUIDE</a>
|
||||
<ul class="nav nav-tabs justify-content-center" style="border-radius: 6px 6px; background-color: #ededed; padding:9px 14px 8px 14px;" role="tablist" data-tabs="tabs">
|
||||
<li class="nav-item">
|
||||
<a class="show "
|
||||
id="v-guide-tab" data-bs-toggle="pill" aria-controls="v-guide" href="#pills-guide" aria-expanded="true" style="padding: 11px 12px 8px 12px !important;">
|
||||
<span class="m-0" style="font-weight: 600; font-family: 'Inter', sans-serif; color: #1c29da;font-size: 19px; line-height: 23px;">USERGUIDE</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item mx-1">
|
||||
<a class="nav-link px-md-4 list-group-item-default list-group-item-action active"
|
||||
id="v-ss-tab" data-bs-toggle="pill" aria-controls="v-ss" href="#pills-screenshot"
|
||||
style="border-radius:6px; opacity:1; padding:16px">SCREENSHOTS</a>
|
||||
<a class="show active"
|
||||
id="v-demo-tab" data-bs-toggle="pill" aria-controls="v-ss" href="#pills-screenshot" aria-expanded="true" style="padding: 11px 12px 8px 12px !important;">
|
||||
<span class="m-0" style="font-weight: 600; font-family: 'Inter', sans-serif; color: #1c29da;font-size: 19px; line-height: 23px">DEMO</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item mx-1">
|
||||
<a class="nav-link px-md-4 list-group-item-default list-group-item-action"
|
||||
id="v-faqs-tab" data-bs-toggle="pill" aria-controls="v-faqs" href="#pills-faqs"
|
||||
style="border-radius:6px; opacity:1; padding:16px">FAQs</a>
|
||||
<a class="show"
|
||||
id="v-faqs-tab" data-bs-toggle="pill" aria-controls="v-faqs" href="#pills-faqs" aria-expanded="true" style="padding: 11px 12px 8px 12px !important;">
|
||||
<span class="m-0" style="font-weight: 600; font-family: 'Inter', sans-serif; color: #1c29da;font-size: 19px; line-height: 23px">FAQS</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item mx-1">
|
||||
<a class="nav-link px-md-4 list-group-item-default list-group-item-action"
|
||||
id="v-release-tab" data-bs-toggle="pill" aria-controls="v-release" href="#pills-release"
|
||||
style="border-radius:6px; opacity:1; padding:16px">RELEASES</a>
|
||||
<li class="nav-item ">
|
||||
<a class="show"
|
||||
id="v-release-tab" data-bs-toggle="pill" aria-controls="v-release" href="#pills-release" aria-expanded="true" style="padding: 11px 12px 8px 12px !important;">
|
||||
<span class="m-0" style="font-weight: 600; font-family: 'Inter', sans-serif; color: #1c29da;font-size: 19px; line-height: 23px">RELEASES</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-content shadow" style="border-radius: 10px;padding: 10px 0px;"
|
||||
<div class="tab-content" style="border-radius: 10px;"
|
||||
id="pills-tabContent">
|
||||
<!-- user-guide -->
|
||||
<div class="tab-pane fade" id="pills-guide" role="tabpanel" aria-labelledby="v-guide-tab"
|
||||
aria-labelledby="pills-guide-tab">
|
||||
<div class="tab-pane fade py-3 shadow" id="pills-guide" role="tabpanel"
|
||||
aria-labelledby="v-guide-tab" aria-labelledby="pills-guide-tab">
|
||||
|
||||
<div class="screenshot-description" style="margin: 1% 3%;">
|
||||
<div style="border-radius: 10px;background-color: #f9f9f9;text-align:center;">
|
||||
|
|
@ -287,68 +189,127 @@
|
|||
</div>
|
||||
|
||||
<!-- screenshots tab -->
|
||||
<div class="tab-pane fade text-center active show" id="pills-screenshot" role="tabpanel" aria-labelledby="v-ss-tab"
|
||||
aria-labelledby="pills-screenshot-tab">
|
||||
<div class="screenshot-description" style="margin: 1% 3%;">
|
||||
<div style="border-radius: 10px;background-color: #f9f9f9;">
|
||||
<h4 style='font-weight: 600;padding: 20px;'>Here is odoo's 'domain' widget
|
||||
for domain creation.</h4>
|
||||
<div class="tab-pane fade text-center active show" id="pills-screenshot" role="tabpanel"
|
||||
aria-labelledby="v-ss-tab" aria-labelledby="pills-screenshot-tab">
|
||||
|
||||
<!-- 01 -->
|
||||
|
||||
<section class="blog_post_01">
|
||||
<div class="position-relative w-100" style="display: inline-grid;">
|
||||
<img src="img/screens/domain_bg_img_03.png"
|
||||
class="img-responsive w-100 h-100 img img-fluid position-absolute left_0" />
|
||||
|
||||
<div class="position-relative row justify-content-center align-items-center"
|
||||
style="padding: 20px 20px 40px 20px;">
|
||||
<div class="col-12 my-3 px-5">
|
||||
|
||||
<div class="mt-2">
|
||||
<div class="content-note d-flex">
|
||||
<div class="icon-img">
|
||||
<img src="img/screens/icon_img.png"
|
||||
class="img img-fluid" />
|
||||
</div>
|
||||
<div class="content"
|
||||
style="margin-left: 15px !important;">
|
||||
<p
|
||||
style="font-family: 'Inter', sans-serif; font-size: 20px; font-weight: 500;line-height: 26px;color: #151765;">
|
||||
Here is odoo's 'domain' widget for domain creation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-img text-center mt-3 mx-5">
|
||||
<img src="img/screens/ss1.png"
|
||||
class="img img-fluid img-responsive" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="content-note d-flex ">
|
||||
<div class="icon-img">
|
||||
<img src="img/screens/icon_img.png"
|
||||
class="img img-fluid" />
|
||||
</div>
|
||||
<div class="content"
|
||||
style="margin-left: 15px !important;">
|
||||
<p
|
||||
style="font-family: 'Inter', sans-serif; font-size: 20px; font-weight: 500;line-height: 26px;color: #151765;">
|
||||
Here is customized 'terabits_domain' widget for domain creation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-img text-center mt-3 mx-5">
|
||||
<img src="img/screens/ss2.png"
|
||||
class="img img-fluid img-responsive" />
|
||||
</div>
|
||||
<div class="content-img text-center mt-4 mx-5">
|
||||
<img src="img/screens/ss3.png"
|
||||
class="img img-fluid img-responsive" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="content-note d-flex ">
|
||||
<div class="icon-img">
|
||||
<img src="img/screens/icon_img.png"
|
||||
class="img img-fluid" />
|
||||
</div>
|
||||
<div class="content"
|
||||
style="margin-left: 15px !important;">
|
||||
<p
|
||||
style="font-family: 'Inter', sans-serif; font-size: 20px; font-weight: 500;line-height: 26px;color: #151765;">
|
||||
Here is customized 'date and filter' widget for domain creation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-img text-center mt-3 mx-5">
|
||||
<img src="img/screens/date_filter_ss4.png"
|
||||
class="img img-fluid img-responsive" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="content-note d-flex ">
|
||||
<div class="icon-img">
|
||||
<img src="img/screens/icon_img.png"
|
||||
class="img img-fluid" />
|
||||
</div>
|
||||
<div class="content"
|
||||
style="margin-left: 15px !important;">
|
||||
<p
|
||||
style="font-family: 'Inter', sans-serif; font-size: 20px; font-weight: 500;line-height: 26px;color: #151765;">
|
||||
Here is how you can select environment company and user.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-img text-center mt-3 mx-5">
|
||||
<img src="img/screens/date_filter_ss5.png"
|
||||
class="img img-fluid img-responsive" />
|
||||
</div>
|
||||
<div class="content-img text-center mt-4 mx-5">
|
||||
<img src="img/screens/date_filter_ss6.png"
|
||||
class="img img-fluid img-responsive" />
|
||||
</div>
|
||||
<div class="content-img text-center mt-4 mx-5">
|
||||
<img src="img/screens/date_filter_ss7.png"
|
||||
class="img img-fluid img-responsive" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="screenshot" style="text-align: center;">
|
||||
<img class="img img-fluid oe_screenshot" style="width: 90%;margin: 2%;"
|
||||
src="img/screens/ss1.png" alt="Odoo domain widget" />
|
||||
</div>
|
||||
<div class="screenshot-description" style="margin: 1% 3%;">
|
||||
<div style="border-radius: 10px;background-color: #f9f9f9;">
|
||||
<h4 style='font-weight: 600;padding: 20px;'>Here is customized
|
||||
'terabits_domain' widget for domain creation.</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="screenshot" style="text-align: center;">
|
||||
<img class="img img-fluid oe_screenshot" style="width: 90%;margin: 2%;"
|
||||
src="img/screens/ss2.png" alt="Terabits domain widget" />
|
||||
</div>
|
||||
<div class="screenshot" style="text-align: center;">
|
||||
<img class="img img-fluid oe_screenshot" style="width: 90%;margin: 2%;"
|
||||
src="img/screens/ss3.png" alt="Terabits domain widget" />
|
||||
</div>
|
||||
<div class="screenshot-description" style="margin: 1% 3%;">
|
||||
<div style="border-radius: 10px;background-color: #f9f9f9;">
|
||||
<h4 style='font-weight: 600;padding: 20px;'>Here is customized 'date and
|
||||
filter'
|
||||
widget for domain creation.</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="screenshot" style="text-align: center;">
|
||||
<img class="img img-fluid oe_screenshot" style="width: 90%;margin: 2%;"
|
||||
src="img/screens/date_filter_ss4.png" alt="Odoo domain widget" />
|
||||
</div>
|
||||
<div class="screenshot-description" style="margin: 1% 3%;">
|
||||
<div style="border-radius: 10px;background-color: #f9f9f9;">
|
||||
<h4 style='font-weight: 600;padding: 20px;'>Here is how you can select
|
||||
environment company and user.</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="screenshot" style="text-align: center;">
|
||||
<img class="img img-fluid oe_screenshot" style="width: 90%;margin: 2%;"
|
||||
src="img/screens/date_filter_ss5.png" alt="Odoo domain widget" />
|
||||
</div>
|
||||
<div class="screenshot" style="text-align: center;">
|
||||
<img class="img img-fluid oe_screenshot" style="width: 90%;margin: 2%;"
|
||||
src="img/screens/date_filter_ss6.png" alt="Odoo domain widget" />
|
||||
</div>
|
||||
<div class="screenshot" style="text-align: center;">
|
||||
<img class="img img-fluid oe_screenshot" style="width: 90%;margin: 2%;"
|
||||
src="img/screens/date_filter_ss7.png" alt="Odoo domain widget" />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- faq tab -->
|
||||
<div class="tab-pane fade" id="pills-faqs" role="tabpanel" aria-labelledby="v-faqs-tab"
|
||||
<div class="tab-pane fade shadow py-3" id="pills-faqs" role="tabpanel" aria-labelledby="v-faqs-tab"
|
||||
aria-labelledby="pills-faqs-tab">
|
||||
<div class="s_faq mt32 mb32"
|
||||
style="background-color: transparent !important;padding: 0px 50px;">
|
||||
style="background-color: transparent !important;padding: 40px 50px;">
|
||||
<div class="panel-group" id="accordion" role="tablist"
|
||||
aria-multiselectable="true">
|
||||
|
||||
|
|
@ -360,9 +321,9 @@
|
|||
style="border:1px solid transparent !important">
|
||||
<h4 class="panel-title" style="margin: 0;">
|
||||
<a class="collapsed"
|
||||
style="color: #000;font-size: 20px;font-weight: 500;font-family: Roboto;padding: 15px 15px 15px 50px;line-height: 158%;"
|
||||
data-bs-toggle="collapse" href="#collapse1" aria-expanded="false">
|
||||
<span class="panelcontent">
|
||||
data-bs-toggle="collapse" href="#collapse1"
|
||||
aria-expanded="false">
|
||||
<span class="panelcontent" style="font-family: 'Inter', sans-serif;font-size: 20px;font-weight: 500;line-height: 25px;color: #000;">
|
||||
Why should I use this app?
|
||||
</span>
|
||||
</a>
|
||||
|
|
@ -373,7 +334,8 @@
|
|||
class="panel-collapse collapse">
|
||||
<div>
|
||||
<p class="mb0"
|
||||
style="height: auto;font-family: Roboto;padding-left: 2%;margin-left: 2%;">
|
||||
style="font-family: 'Inter', sans-serif;font-size: 16px;font-weight: 400;line-height: 25px;
|
||||
color: #000; padding-left:2%; margin-left:2%">
|
||||
This module provides domains with an additional feature
|
||||
to select any models record while using any relational
|
||||
field and create a domain after selecting it. for that,
|
||||
|
|
@ -395,10 +357,9 @@
|
|||
style="border:1px solid transparent !important">
|
||||
<h4 class="panel-title" style="margin: 0;">
|
||||
<a class="collapsed"
|
||||
style="color: #000;font-size: 20px;font-weight: 500;font-family: Roboto;padding: 15px 15px 15px 50px;line-height: 158%;"
|
||||
data-bs-toggle="collapse" href="#collapse2"
|
||||
aria-expanded="false">
|
||||
<span class="panelcontent">
|
||||
<span class="panelcontent" style="font-family: 'Inter', sans-serif;font-size: 20px;font-weight: 500;line-height: 25px;color: #000;">
|
||||
What is user's main benifit ?
|
||||
</span>
|
||||
</a>
|
||||
|
|
@ -409,7 +370,8 @@
|
|||
class="panel-collapse collapse">
|
||||
<div>
|
||||
<p class="mb0"
|
||||
style="height: auto;font-family: Roboto;padding-left: 2%;margin-left: 2%;">
|
||||
style="font-family: 'Inter', sans-serif;font-size: 16px;font-weight: 400;line-height: 25px;
|
||||
color: #000; padding-left:2%; margin-left:2%">
|
||||
User's main benifit is that, he/she does not have to
|
||||
remember models record id while he/she have to create
|
||||
domain based on relational fields, because we direct
|
||||
|
|
@ -429,10 +391,9 @@
|
|||
style="border:1px solid transparent !important">
|
||||
<h4 class="panel-title" style="margin: 0;">
|
||||
<a class="collapsed"
|
||||
style="color: #000;font-size: 20px;font-weight: 500;font-family: Roboto;padding: 15px 15px 15px 50px;line-height: 158%;"
|
||||
data-bs-toggle="collapse" href="#collapse3"
|
||||
aria-expanded="false">
|
||||
<span class="panelcontent">
|
||||
<span class="panelcontent" style="font-family: 'Inter', sans-serif;font-size: 20px;font-weight: 500;line-height: 25px;color: #000;">
|
||||
Need some customization in this app, whom can I
|
||||
contact?
|
||||
</span>
|
||||
|
|
@ -444,7 +405,8 @@
|
|||
class="panel-collapse collapse">
|
||||
<div>
|
||||
<p class="mb0"
|
||||
style="height: auto;font-family: Roboto;padding-left: 2%;margin-left: 2%;">
|
||||
style="font-family: 'Inter', sans-serif;font-size: 16px;font-weight: 400;line-height: 25px;
|
||||
color: #000; padding-left:2%; margin-left:2%">
|
||||
Please drop an email at info@terabits.xyz or raise a
|
||||
ticket through the Odoo store itself.
|
||||
|
||||
|
|
@ -461,10 +423,9 @@
|
|||
style="border:1px solid transparent !important">
|
||||
<h4 class="panel-title" style="margin: 0;">
|
||||
<a class="collapsed"
|
||||
style="color: #000;font-size: 20px;font-weight: 500;font-family: Roboto;padding: 15px 15px 15px 50px;line-height: 158%;"
|
||||
data-bs-toggle="collapse" href="#collapse4"
|
||||
aria-expanded="false">
|
||||
<span class="panelcontent">
|
||||
<span class="panelcontent" style="font-family: 'Inter', sans-serif;font-size: 20px;font-weight: 500;line-height: 25px;color: #000;">
|
||||
Do you provide any free support?
|
||||
</span>
|
||||
</a>
|
||||
|
|
@ -475,7 +436,8 @@
|
|||
class="panel-collapse collapse">
|
||||
<div>
|
||||
<p class="mb0"
|
||||
style="height: auto;font-family: Roboto;padding-left: 2%;margin-left: 2%;">
|
||||
style="font-family: 'Inter', sans-serif;font-size: 16px;font-weight: 400;line-height: 25px;
|
||||
color: #000; padding-left:2%; margin-left:2%">
|
||||
Yes, I do provide free support for 90 days for any
|
||||
queries or any bug/issue fixing.
|
||||
|
||||
|
|
@ -492,10 +454,9 @@
|
|||
style="border:1px solid transparent !important">
|
||||
<h4 class="panel-title" style="margin: 0;">
|
||||
<a class="collapsed"
|
||||
style="color: #000;font-size: 20px;font-weight: 500;font-family: Roboto;padding: 15px 15px 15px 50px;line-height: 158%;"
|
||||
data-bs-toggle="collapse" href="#collapse5"
|
||||
aria-expanded="false">
|
||||
<span class="panelcontent">
|
||||
<span class="panelcontent" style="font-family: 'Inter', sans-serif;font-size: 20px;font-weight: 500;line-height: 25px;color: #000;">
|
||||
What is Support Policy of this Module?
|
||||
</span>
|
||||
</a>
|
||||
|
|
@ -506,7 +467,8 @@
|
|||
class="panel-collapse collapse">
|
||||
<div>
|
||||
<p class="mb0"
|
||||
style="height: auto;font-family: Roboto;padding-left: 2%;margin-left: 2%;">
|
||||
style="font-family: 'Inter', sans-serif;font-size: 16px;font-weight: 400;line-height: 25px;
|
||||
color: #000; padding-left:2%; margin-left:2%">
|
||||
In case of if any bug raised in the listed features of
|
||||
this module, I am committed to providing support free of
|
||||
cost. You will need to provide me server ssh access or
|
||||
|
|
@ -522,42 +484,34 @@
|
|||
</div>
|
||||
|
||||
<!-- release tab -->
|
||||
<div class="tab-pane px-0 px-sm-5 fade" id="pills-release" aria-labelledby="v-release-tab"
|
||||
style="padding-top: 0.25rem !important;" role="tabpanel"
|
||||
aria-labelledby="pills-release-tab">
|
||||
<div class="tab-pane px-0 px-sm-5 shadow fade" id="pills-release" aria-labelledby="v-release-tab" style="padding-top: 0.25rem !important;" role="tabpanel" aria-labelledby="pills-release-tab">
|
||||
|
||||
<div class="row my-4 p-3 pb-2 position-relative">
|
||||
<div class="col-12 p-4 shadow-sm bg-white">
|
||||
<h2>Changelog(s)</h2>
|
||||
<div class="row my-2 p-4 position-relative">
|
||||
<div class="col-12 px-0 bg-white">
|
||||
<h2 style="font-family: 'Inter', sans-serif;font-size: 35px;color: #000;font-weight: 600;">Changelog(s)</h2>
|
||||
<hr class="mb-4 mt-0">
|
||||
<!-- v14.0.1.0.2 -->
|
||||
<h2 class="h4 pb-2">
|
||||
<span style="color:#00B5DB" class="pr-2">v14.0.1.0.2</span>-<span
|
||||
class="pl-2">December
|
||||
10, 2022</span>
|
||||
<span style=" font-family: 'Inter', sans-serif; color:#00B5DB;font-size: 22px;font-weight: 600;" class="pe-2">v14.0.1.0.2</span>
|
||||
<span>-</span>
|
||||
<span class="ps-2" style="font-family: 'Inter', sans-serif;font-size: 23px;font-weight: 500;color: #000;">December 10, 2022</span>
|
||||
</h2>
|
||||
<ul class="list-unstyled">
|
||||
<li class="d-flex align-items-start mb-3">
|
||||
Minor bug fix.
|
||||
</li>
|
||||
</ul>
|
||||
<p style="font-family: 'Inter', sans-serif;color: #000;font-size: 18px; font-weight: 500; line-height: 28px;">
|
||||
Minor bug fix.
|
||||
</p>
|
||||
<!-- v14.0.0.0.0 -->
|
||||
<h2 class="h4 pb-2">
|
||||
<span style="color:#00B5DB" class="pr-2">v14.0.0.0.0</span>-<span
|
||||
class="pl-2">November
|
||||
23, 2022</span>
|
||||
<span style=" font-family: 'Inter', sans-serif; color:#00B5DB;font-size: 22px;font-weight: 600;" class="pe-2">v14.0.0.0.0</span>
|
||||
<span>-</span>
|
||||
<span class="ps-2" style="font-family: 'Inter', sans-serif;font-size: 23px;font-weight: 500;color: #000;">November 23, 2022</span>
|
||||
</h2>
|
||||
<ul class="list-unstyled">
|
||||
<li class="d-flex align-items-start mb-3">
|
||||
Initial release for v14
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p style="font-family: 'Inter', sans-serif;color: #000;font-size: 18px; font-weight: 500; line-height: 28px;">
|
||||
Initial release for v14
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
55
odex25_base/advanced_web_domain_widget/static/src/js/fields/basic_fields.js
Normal file → Executable file
|
|
@ -12,7 +12,7 @@ var config = require('web.config');
|
|||
var core = require('web.core');
|
||||
var Domain = require('web.Domain');
|
||||
var DomainSelector = require('advanced_web_domain_widget.TerabitsDomainSelector');
|
||||
var DomainSelectorDialog = require('advanced_web_domain_widget.DomainSelectorDialog');
|
||||
var {DomainSelectorDialog, DomainSelectorDialog2} = require('advanced_web_domain_widget.DomainSelectorDialog');
|
||||
var view_dialogs = require('web.view_dialogs');
|
||||
|
||||
require("web.zoomodoo");
|
||||
|
|
@ -439,8 +439,61 @@ var TerabitsFieldDomain = AbstractField.extend({
|
|||
},
|
||||
});
|
||||
|
||||
var TerabitsFieldDomain2 = TerabitsFieldDomain.extend({
|
||||
_replaceContent: function () {
|
||||
if (this._$content) {
|
||||
this._$content.remove();
|
||||
}
|
||||
this._$content = $(qweb.render("TerabitsFieldDomain.content2", {
|
||||
hasModel: !!this._domainModel,
|
||||
isValid: !!this._isValidForModel,
|
||||
nbRecords: this.record.specialData[this.name].nbRecords || 0,
|
||||
inDialogEdit: this.inDialog && this.mode === "edit",
|
||||
isDateFilter: this.value[0] && this.value[0]?.length>0? this.value[0][1] == "date_filter": false
|
||||
}));
|
||||
this._$content.appendTo(this.$el);
|
||||
},
|
||||
|
||||
_render: function () {
|
||||
// If there is no model, only change the non-domain-selector content
|
||||
if (!this._domainModel) {
|
||||
this._replaceContent();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Convert char value to array value
|
||||
var value = this.value || "[]";
|
||||
|
||||
// Create the domain selector or change the value of the current one...
|
||||
var def;
|
||||
|
||||
if (!this.domainSelector) {
|
||||
this.domainSelector = new DomainSelector.TerabitsDomainSelector2(this, this._domainModel, value, {
|
||||
readonly: this.mode === "readonly" || this.inDialog,
|
||||
filters: this.fsFilters,
|
||||
debugMode: config.isDebug(),
|
||||
});
|
||||
def = this.domainSelector.prependTo(this.$el);
|
||||
} else {
|
||||
def = this.domainSelector.setDomain(value);
|
||||
}
|
||||
// ... then replace the other content (matched records, etc)
|
||||
return def.then(this._replaceContent.bind(this));
|
||||
},
|
||||
|
||||
_onDialogEditButtonClick: function (e) {
|
||||
e.preventDefault();
|
||||
new DomainSelectorDialog2(this, this._domainModel, this.value || "[]", {
|
||||
readonly: this.mode === "readonly",
|
||||
filters: this.fsFilters,
|
||||
debugMode: config.isDebug(),
|
||||
}).open();
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
TerabitsFieldDomain: TerabitsFieldDomain,
|
||||
TerabitsFieldDomain2: TerabitsFieldDomain2
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
|||
2
odex25_base/advanced_web_domain_widget/static/src/js/fields/basic_model.js
Normal file → Executable file
|
|
@ -239,7 +239,7 @@ BasicModel.include({
|
|||
});
|
||||
self._rpc({
|
||||
model: domainModel,
|
||||
method: 'search_count',
|
||||
method: 'get_widget_count',
|
||||
args: [newDomain],
|
||||
context: context
|
||||
})
|
||||
|
|
|
|||
1
odex25_base/advanced_web_domain_widget/static/src/js/fields/terabits_fields_registry.js
Normal file → Executable file
|
|
@ -6,6 +6,7 @@ odoo.define('advanced_web_domain_widget._terabits_field_registry', function (req
|
|||
|
||||
// Basic fields
|
||||
fieldRegistry.add('terabits_domain', basic_fields.TerabitsFieldDomain);
|
||||
fieldRegistry.add('terabits_field_domain', basic_fields.TerabitsFieldDomain2);
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
320
odex25_base/advanced_web_domain_widget/static/src/js/widget/TerabitsDomainSelector.js
Normal file → Executable file
|
|
@ -5,7 +5,7 @@ odoo.define("advanced_web_domain_widget.TerabitsDomainSelector", function (requi
|
|||
var datepicker = require("web.datepicker");
|
||||
var Domain = require("web.Domain");
|
||||
var field_utils = require("web.field_utils");
|
||||
var ModelFieldSelector = require("advanced_web_domain_widget.ModelFieldSelector");
|
||||
var {ModelFieldSelector, ModelFieldSelector2} = require("advanced_web_domain_widget.ModelFieldSelector");
|
||||
var ModelRecordSelector = require("advanced_web_domain_widget.ModelRecordSelector");
|
||||
var Widget = require("web.Widget");
|
||||
var _t = core._t;
|
||||
|
|
@ -451,6 +451,33 @@ odoo.define("advanced_web_domain_widget.TerabitsDomainSelector", function (requi
|
|||
},
|
||||
});
|
||||
|
||||
var TerabitsDomainTree2 = TerabitsDomainTree.extend({
|
||||
_addChild: function (domain, afterNode) {
|
||||
var i = afterNode ? _.indexOf(this.children, afterNode) : this.children.length;
|
||||
if (i < 0) return false;
|
||||
|
||||
this.children.splice(i + 1, 0, instantiateNode2(this, this.model, domain, this.options));
|
||||
this.trigger_up("domain_changed", { child: this });
|
||||
return true;
|
||||
},
|
||||
|
||||
_addFlattenedChildren: function (domain) {
|
||||
var node = instantiateNode2(this, this.model, domain, this.options);
|
||||
if (node === null) {
|
||||
return;
|
||||
}
|
||||
if (!node.children || node.operator !== this.operator) {
|
||||
this.children.push(node);
|
||||
return;
|
||||
}
|
||||
_.each(node.children, (function (child) {
|
||||
child.setParent(this);
|
||||
this.children.push(child);
|
||||
}).bind(this));
|
||||
node.destroy();
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* The TerabitsDomainSelector widget can be used to build prefix char domain. It is the
|
||||
* TerabitsDomainTree specialization to use to have a fully working widget.
|
||||
|
|
@ -611,6 +638,154 @@ odoo.define("advanced_web_domain_widget.TerabitsDomainSelector", function (requi
|
|||
},
|
||||
});
|
||||
|
||||
var TerabitsDomainSelector2 = TerabitsDomainTree2.extend({
|
||||
template: "TerabitsDomainSelector",
|
||||
events: _.extend({}, TerabitsDomainTree.prototype.events, {
|
||||
"click .o_domain_add_first_node_button": "_onAddFirstButtonClick",
|
||||
"change .o_domain_debug_input": "_onDebugInputChange",
|
||||
}),
|
||||
custom_events: _.extend({}, TerabitsDomainTree.prototype.custom_events, {
|
||||
domain_changed: "_onDomainChange",
|
||||
}),
|
||||
|
||||
start: function () {
|
||||
var self = this;
|
||||
return this._super.apply(this, arguments).then(function () {
|
||||
if (self.invalidDomain) {
|
||||
var msg = _t("This domain is not supported.");
|
||||
self.$el.html(msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Changes the internal domain value and forces a reparsing and rerendering.
|
||||
* If the internal domain value was already equal to the given one, this
|
||||
* does nothing.
|
||||
*
|
||||
* @param {string} domain
|
||||
* @returns {Promise} resolved when the rerendering is finished
|
||||
*/
|
||||
setDomain: function (domain) {
|
||||
if (domain === Domain.prototype.arrayToString(this.getDomain())) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
var parsedDomain = this._parseDomain(domain);
|
||||
if (parsedDomain) {
|
||||
return this._redraw(parsedDomain);
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @see TerabitsDomainTree._initialize
|
||||
*/
|
||||
_initialize: function (domain) {
|
||||
// Check if the domain starts with implicit "&" operators and make them
|
||||
// explicit. As the TerabitsDomainSelector is a specialization of a TerabitsDomainTree,
|
||||
// it is waiting for a tree and not a leaf. So [] and [A] will be made
|
||||
// explicit with ["&"], ["&", A] so that tree parsing is made correctly.
|
||||
// Note: the domain is considered to be a valid one
|
||||
if (domain.length > 1) {
|
||||
Domain.prototype.normalizeArray(domain);
|
||||
} else {
|
||||
domain = ["&"].concat(domain);
|
||||
}
|
||||
return this._super(domain);
|
||||
},
|
||||
/**
|
||||
* @see TerabitsDomainTree._postRender
|
||||
* Warns the user if the domain is not valid after rendering.
|
||||
*/
|
||||
_postRender: function () {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
// Display technical domain if in debug mode
|
||||
this.$debugInput = this.$(".o_domain_debug_input");
|
||||
if (this.$debugInput.length) {
|
||||
this.$debugInput.val(Domain.prototype.arrayToString(this.getDomain()));
|
||||
}
|
||||
|
||||
// Warn the user if the domain is not valid after rendering
|
||||
if (!this._isValid) {
|
||||
this.do_warn(false, _t("Domain not supported"));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* This method is ugly but achieves the right behavior without flickering.
|
||||
*
|
||||
* @param {Array|string} domain
|
||||
* @returns {Promise}
|
||||
*/
|
||||
_redraw: function (domain) {
|
||||
var oldChildren = this.children.slice();
|
||||
this._initialize(domain || this.getDomain());
|
||||
return this._renderChildrenTo($("<div/>")).then((function () {
|
||||
_.each(oldChildren, function (child) { child.destroy(); });
|
||||
this.renderElement();
|
||||
this._postRender();
|
||||
_.each(this.children, (function (child) {
|
||||
if(child.$el){
|
||||
child.$el.appendTo(this.$childrenContainer);
|
||||
}
|
||||
}).bind(this));
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when the "add a filter" button is clicked -> adds a first domain
|
||||
* node
|
||||
*/
|
||||
_onAddFirstButtonClick: function () {
|
||||
this._addChild(this.options.default || [["id", "=", 1]]);
|
||||
},
|
||||
/**
|
||||
* Called when the debug input value is changed -> constructs the tree
|
||||
* representation if valid or warn the user if invalid.
|
||||
*
|
||||
* @param {Event} e
|
||||
*/
|
||||
_onDebugInputChange: function (e) {
|
||||
// When the debug input changes, the string prefix domain is read. If it
|
||||
// is syntax-valid the widget is re-rendered and notifies the parents.
|
||||
// If not, a warning is shown to the user and the input is ignored.
|
||||
var domain;
|
||||
try {
|
||||
domain = Domain.prototype.stringToArray($(e.currentTarget).val());
|
||||
} catch (err) { // If there is a syntax error, just ignore the change
|
||||
this.do_warn(_t("Syntax error"), _t("Domain not properly formed"));
|
||||
return;
|
||||
}
|
||||
this._redraw(domain).then((function () {
|
||||
this.trigger_up("domain_changed", { child: this, alreadyRedrawn: true });
|
||||
}).bind(this));
|
||||
},
|
||||
/**
|
||||
* Called when a (child's) domain has changed -> redraw the entire tree
|
||||
* representation if necessary
|
||||
*
|
||||
* @param {OdooEvent} e
|
||||
*/
|
||||
_onDomainChange: function (e) {
|
||||
// If a subdomain notifies that it underwent some modifications, the
|
||||
// TerabitsDomainSelector catches the message and performs a full re-rendering.
|
||||
if (!e.data.alreadyRedrawn) {
|
||||
this._redraw();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* TerabitsDomainNode which handles a domain which cannot be split in another
|
||||
* subdomains, i.e. composed of a field chain, an operator and a value.
|
||||
|
|
@ -711,13 +886,21 @@ odoo.define("advanced_web_domain_widget.TerabitsDomainSelector", function (requi
|
|||
const ids = (this.value) ? this.value : [];
|
||||
wDefs.push(this._rpc({
|
||||
model: model_rel,
|
||||
method: 'search_read',
|
||||
method: 'get_widget_name',
|
||||
kwargs: {
|
||||
domain: [['id', 'in', ids]],
|
||||
fields: ['id', 'display_name'],
|
||||
},
|
||||
}).then(function (data) {
|
||||
self.value = [];
|
||||
if(model_rel == 'res.users' && _.contains(ids,0)){
|
||||
self.tagsvalues.push([0, 'Environment User']);
|
||||
self.value.push(0);
|
||||
}
|
||||
if(model_rel == 'res.company' && _.contains(ids,0)){
|
||||
self.tagsvalues.push([0, 'Environment Company']);
|
||||
self.value.push(0);
|
||||
}
|
||||
_.each(data, function (rec, index) {
|
||||
self.tagsvalues.push([rec.id, rec.display_name]);
|
||||
// to remove invalid id which is not in records
|
||||
|
|
@ -1065,6 +1248,126 @@ odoo.define("advanced_web_domain_widget.TerabitsDomainSelector", function (requi
|
|||
},
|
||||
});
|
||||
|
||||
var TerabitsDomainLeaf2 = TerabitsDomainLeaf.extend({
|
||||
willStart: function () {
|
||||
var defs = [this._super.apply(this, arguments)];
|
||||
|
||||
// In edit mode, instantiate a field selector. This is done here in
|
||||
// willStart and prepared by appending it to a dummy element because the
|
||||
// TerabitsDomainLeaf rendering need some information which cannot be computed
|
||||
// before the ModelFieldSelector is fully rendered (TODO).
|
||||
|
||||
this.fieldSelector = new ModelFieldSelector2(
|
||||
this,
|
||||
this.model,
|
||||
this.chain !== undefined ? this.chain.toString().split(".") : [],
|
||||
this.options
|
||||
);
|
||||
defs.push(this.fieldSelector.appendTo($("<div/>")).then((function () {
|
||||
var wDefs = [];
|
||||
var selectedField = this.fieldSelector.getSelectedField() || {};
|
||||
if ((this.operator == 'in' && _.contains(['many2one', 'many2many', 'one2many'], selectedField.type) || selectedField.name == "id") && typeof (this.currentDomain[0][2][0]) == 'string') {
|
||||
this.value = [];
|
||||
} else {
|
||||
this.value = this.currentDomain[0][2];
|
||||
}
|
||||
this.title = selectedField.string;
|
||||
this.recordReader = new ModelRecordSelector(
|
||||
this,
|
||||
selectedField.relation,
|
||||
this.chain !== undefined ? this.chain.toString().split(".") : [],
|
||||
this.options,
|
||||
this.title
|
||||
);
|
||||
if (!this.readonly) {
|
||||
// Set list of operators according to field type
|
||||
this.displayValue = this.value;
|
||||
this.operators = this._getOperatorsFromType(selectedField.type, selectedField.name);
|
||||
if (_.contains(["child_of", "parent_of", "like", "not like", "=like", "=ilike"], this.operator)) {
|
||||
// In case user entered manually or from demo data
|
||||
this.operators[this.operator] = operator_mapping[this.operator];
|
||||
} else if (!this.operators[this.operator]) {
|
||||
// In case the domain uses an unsupported operator for the
|
||||
// field type
|
||||
this.operators[this.operator] = "?";
|
||||
}
|
||||
// Set list of values according to field type
|
||||
|
||||
this.selectionChoices = null;
|
||||
if (selectedField.type === "boolean") {
|
||||
this.selectionChoices = [["1", _t("set (true)")], ["0", _t("not set (false)")]];
|
||||
} else if (selectedField.type === "selection") {
|
||||
this.selectionChoices = selectedField.selection;
|
||||
}
|
||||
else if ((_.contains(['many2one', 'many2many', 'one2many'], selectedField.type) || selectedField.name == "id") && (_.contains(['in', 'not in'], this.operator))) {
|
||||
var model_rel = selectedField.name == "id"? selectedField.model: selectedField.relation
|
||||
// var def = this.get_rec(model_rel)
|
||||
// var model_rel = selectedField.relation
|
||||
this.selectionChoices = null
|
||||
// this.recordReader.appendTo($("<div/>"))
|
||||
var self = this;
|
||||
const ids = (this.value) ? this.value : [];
|
||||
wDefs.push(this._rpc({
|
||||
model: model_rel,
|
||||
method: 'get_widget_name',
|
||||
kwargs: {
|
||||
domain: [['id', 'in', ids]],
|
||||
fields: ['id', 'display_name'],
|
||||
},
|
||||
}).then(function (data) {
|
||||
self.value = [];
|
||||
if(model_rel == 'res.users' && _.contains(ids,0)){
|
||||
self.tagsvalues.push([0, 'Environment User']);
|
||||
self.value.push(0);
|
||||
}
|
||||
if(model_rel == 'res.company' && _.contains(ids,0)){
|
||||
self.tagsvalues.push([0, 'Environment Company']);
|
||||
self.value.push(0);
|
||||
}
|
||||
_.each(data, function (rec, index) {
|
||||
self.tagsvalues.push([rec.id, rec.display_name]);
|
||||
// to remove invalid id which is not in records
|
||||
self.value.push(rec.id);
|
||||
|
||||
})
|
||||
}));
|
||||
|
||||
wDefs.push(this.recordReader.appendTo($('<div/>')).then((function () {
|
||||
this.displayValue = [];
|
||||
// this.value = [];
|
||||
}).bind(this)));
|
||||
}
|
||||
// Adapt display value and operator for rendering
|
||||
|
||||
try {
|
||||
if (selectedField && !selectedField.relation && !_.isArray(this.value)) {
|
||||
this.displayValue = field_utils.format[selectedField.type](this.value, selectedField);
|
||||
}
|
||||
} catch (err) {/**/ }
|
||||
this.displayOperator = this.operator;
|
||||
if (selectedField.type === "boolean") {
|
||||
this.displayValue = this.value ? "1" : "0";
|
||||
} else if ((this.operator === "!=" || this.operator === "=") && this.value === false) {
|
||||
this.displayOperator = this.operator === "!=" ? "set" : "not set";
|
||||
}
|
||||
// TODO the value could be a m2o input, etc...
|
||||
if (_.contains(["date", "datetime"], selectedField.type)) {
|
||||
this.valueWidget = new (selectedField.type === "datetime" ? datepicker.DateTimeWidget : datepicker.DateWidget)(this);
|
||||
wDefs.push(this.valueWidget.appendTo("<div/>").then((function () {
|
||||
this.valueWidget.$el.addClass("o_domain_leaf_value_input");
|
||||
this.valueWidget.setValue(moment(this.value));
|
||||
this.valueWidget.on("datetime_changed", this, function () {
|
||||
this._changeValue(this.valueWidget.getValue());
|
||||
});
|
||||
}).bind(this)));
|
||||
}
|
||||
return Promise.all(wDefs);
|
||||
}
|
||||
}).bind(this)));
|
||||
|
||||
return Promise.all(defs);
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -1086,8 +1389,19 @@ odoo.define("advanced_web_domain_widget.TerabitsDomainSelector", function (requi
|
|||
return null
|
||||
}
|
||||
|
||||
function instantiateNode2(parent, model, domain, options) {
|
||||
if (domain.length > 1) {
|
||||
return new TerabitsDomainTree2(parent, model, domain, options);
|
||||
} else if (domain.length === 1) {
|
||||
return new TerabitsDomainLeaf2(parent, model, domain, options);
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
TerabitsDomainSelector:TerabitsDomainSelector,
|
||||
TerabitsDomainLeaf:TerabitsDomainLeaf
|
||||
TerabitsDomainSelector2:TerabitsDomainSelector2,
|
||||
TerabitsDomainLeaf:TerabitsDomainLeaf,
|
||||
TerabitsDomainLeaf2:TerabitsDomainLeaf2,
|
||||
};
|
||||
});
|
||||
|
|
|
|||
37
odex25_base/advanced_web_domain_widget/static/src/js/widget/domain_selector_dialog.js
Normal file → Executable file
|
|
@ -10,7 +10,7 @@ odoo.define("advanced_web_domain_widget.DomainSelectorDialog", function (require
|
|||
/**
|
||||
* @class DomainSelectorDialog
|
||||
*/
|
||||
return Dialog.extend({
|
||||
var DomainSelectorDialog = Dialog.extend({
|
||||
init: function (parent, model, domain, options) {
|
||||
this.model = model;
|
||||
this.options = _.extend({
|
||||
|
|
@ -51,5 +51,40 @@ odoo.define("advanced_web_domain_widget.DomainSelectorDialog", function (require
|
|||
]);
|
||||
},
|
||||
});
|
||||
|
||||
var DomainSelectorDialog2 = DomainSelectorDialog.extend({
|
||||
init: function (parent, model, domain, options) {
|
||||
this.model = model;
|
||||
this.options = _.extend({
|
||||
readonly: true,
|
||||
debugMode: false,
|
||||
}, options || {});
|
||||
|
||||
var buttons;
|
||||
if (this.options.readonly) {
|
||||
buttons = [
|
||||
{text: _t("Close"), close: true},
|
||||
];
|
||||
} else {
|
||||
buttons = [
|
||||
{text: _t("Save"), classes: "btn-primary", close: true, click: function () {
|
||||
this.trigger_up("domain_selected", {domain: this.domainSelector.getDomain()});
|
||||
}},
|
||||
{text: _t("Discard"), close: true},
|
||||
];
|
||||
}
|
||||
|
||||
this._super(parent, _.extend({}, {
|
||||
title: _t("Domain"),
|
||||
buttons: buttons,
|
||||
}, options || {}));
|
||||
|
||||
this.domainSelector = new DomainSelector.TerabitsDomainSelector2(this, model, domain, options);
|
||||
},
|
||||
})
|
||||
return {
|
||||
DomainSelectorDialog: DomainSelectorDialog,
|
||||
DomainSelectorDialog2: DomainSelectorDialog2
|
||||
}
|
||||
});
|
||||
|
||||
61
odex25_base/advanced_web_domain_widget/static/src/js/widget/model_field_selector.js
Normal file → Executable file
|
|
@ -586,7 +586,66 @@ var TerabitsModelFieldSelector = Widget.extend({
|
|||
}
|
||||
});
|
||||
|
||||
return TerabitsModelFieldSelector;
|
||||
var TerabitsModelFieldSelector2 = TerabitsModelFieldSelector.extend({
|
||||
_render: function () {
|
||||
|
||||
// Render the chain value
|
||||
this.$value.html(core.qweb.render(this.template + ".value", {
|
||||
chain: this.chain,
|
||||
pages: this.pages,
|
||||
}));
|
||||
|
||||
// Toggle the warning message
|
||||
this.$valid.toggleClass('d-none', !!this.isValid());
|
||||
|
||||
// Adapt the popover content
|
||||
var page = _.last(this.pages);
|
||||
var title = "";
|
||||
if (this.pages.length > 1) {
|
||||
var prevField = _.findWhere(this.pages[this.pages.length - 2], {
|
||||
name: (this.chain.length === this.pages.length) ? this.chain[this.chain.length - 2] : _.last(this.chain),
|
||||
});
|
||||
if (prevField) title = prevField.string;
|
||||
}
|
||||
this.$(".o_field_selector_popover_header .o_field_selector_title").text(title);
|
||||
|
||||
var lines = _.filter(page, this.options.filter);
|
||||
if (this.searchValue) {
|
||||
var matches = fuzzy.filter(this.searchValue, _.pluck(lines, 'string'));
|
||||
lines = _.map(_.pluck(matches, 'index'), function (i) {
|
||||
return lines[i];
|
||||
});
|
||||
}
|
||||
|
||||
this.$(".o_field_selector_page").replaceWith(core.qweb.render(this.template + ".page2", {
|
||||
lines: lines,
|
||||
followRelations: this.options.followRelations,
|
||||
debug: this.options.debugMode,
|
||||
}));
|
||||
this.$input.val(this.chain.join("."));
|
||||
},
|
||||
|
||||
|
||||
_pushPageData: function (model) {
|
||||
var def;
|
||||
if (this.model === model && this.options.fields) {
|
||||
def = Promise.resolve(sortFields(this.options.fields, model, this.options.order));
|
||||
} else {
|
||||
def = this._getModelFieldsFromCache(model, this.options.filters);
|
||||
}
|
||||
return def.then((function (fields) {
|
||||
if(this.pages.length <= 0)
|
||||
this.pages.push(fields);
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
|
||||
_onPrevPageClick: function () {
|
||||
// this._goToPrevPage();
|
||||
},
|
||||
})
|
||||
return {ModelFieldSelector: TerabitsModelFieldSelector,
|
||||
ModelFieldSelector2: TerabitsModelFieldSelector2};
|
||||
|
||||
/**
|
||||
* Allows to transform a mapping field name -> field info in an array of the
|
||||
|
|
|
|||
8
odex25_base/advanced_web_domain_widget/static/src/js/widget/model_record_selector.js
Normal file → Executable file
|
|
@ -104,7 +104,7 @@ odoo.define("advanced_web_domain_widget.ModelRecordSelector", function (require)
|
|||
;
|
||||
var def = this._rpc({
|
||||
model: model,
|
||||
method: 'search_read',
|
||||
method: 'get_widget_name',
|
||||
kwargs: {
|
||||
domain: [],
|
||||
fields: ['id', 'display_name'],
|
||||
|
|
@ -113,6 +113,12 @@ odoo.define("advanced_web_domain_widget.ModelRecordSelector", function (require)
|
|||
if (data) {
|
||||
this.records = data
|
||||
}
|
||||
if(model == 'res.users'){
|
||||
this.records.push({'id': 0, 'display_name': 'Environment User'})
|
||||
}
|
||||
if(model == 'res.company'){
|
||||
this.records.push({'id': 0, 'display_name': 'Environment Company'})
|
||||
}
|
||||
// if(model == 'res.users'){
|
||||
// this.records.push({'id':0,'display_name':'Environment User'})
|
||||
// }
|
||||
|
|
|
|||
28
odex25_base/advanced_web_domain_widget/static/src/xml/domain_base.xml
Normal file → Executable file
|
|
@ -16,6 +16,22 @@
|
|||
</div>
|
||||
<div t-else="">Select a model to add a filter.</div>
|
||||
</t>
|
||||
|
||||
<t t-name="TerabitsFieldDomain.content2">
|
||||
<div t-if="hasModel" class="o_field_domain_panel">
|
||||
<!-- <i class="fa fa-arrow-right" role="img" aria-label="Domain" title="Domain"/>
|
||||
|
||||
<button t-if="isValid" class="btn btn-sm btn-secondary o_domain_show_selection_button" type="button">
|
||||
<t t-esc="nbRecords"/> record(s)
|
||||
</button> -->
|
||||
<t t-if="!isValid">
|
||||
<span class="text-warning" role="alert"><i class="fa fa-exclamation-triangle" role="img" aria-label="Warning" title="Warning"/> Invalid domain</span>
|
||||
</t>
|
||||
|
||||
<button t-if="inDialogEdit" class="btn btn-sm btn-primary o_field_domain_dialog_button">Edit Domain</button>
|
||||
</div>
|
||||
<div t-else="">Select a model to add a filter.</div>
|
||||
</t>
|
||||
<t t-name="TerabitsDomainNode.ControlPanel">
|
||||
<div t-if="!widget.readonly && !widget.noControlPanel" class="o_domain_node_control_panel" role="toolbar" aria-label="Domain node">
|
||||
<button class="btn o_domain_delete_node_button" title="Delete node" aria-label="Delete node"><i class="fa fa-times"/></button>
|
||||
|
|
@ -259,6 +275,18 @@
|
|||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
|
||||
<ul t-name="TerabitsModelFieldSelector.page2" class="o_field_selector_page">
|
||||
<t t-foreach="lines" t-as="line">
|
||||
<t t-set="relationToFollow" t-value="followRelations(line) && line.relation"/>
|
||||
<li t-attf-class="o_field_selector_item #{relationToFollow and 'o_field_selector_next_page' or 'o_field_selector_select_button'}#{line_index == 0 and ' active' or ''}"
|
||||
t-att-data-name="line.name">
|
||||
<t t-esc="line.string"/>
|
||||
<div t-if="debug" class="text-muted o_field_selector_item_title"><t t-esc="line.name"/> (<t t-esc="line.type"/>)</div>
|
||||
<!-- <i t-if="relationToFollow" class="fa fa-chevron-right o_field_selector_relation_icon" role="img" aria-label="Relation to follow" title="Relation to follow"/> -->
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
<ul t-name="TerabitsModelRecordSelector.page" class="o_record_selector_page">
|
||||
<t t-foreach="lines" t-as="line">
|
||||
<!-- <t t-set="relationToFollow" t-value="followRelations(line) && line.relation"/> -->
|
||||
|
|
|
|||
|
|
@ -14,5 +14,4 @@ def post_install_action_dup_hook(cr, registry):
|
|||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
action_data_obj = env['action.data']
|
||||
for action in env['ir.actions.actions'].search([]):
|
||||
print(action.name,"===================")
|
||||
action_data_obj.create({'name':action.name,'action_id':action.id})
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#################################################################################
|
||||
# Author : Terabits Technolab (<www.terabits.xyz>)
|
||||
# Copyright(c): 2021-23
|
||||
# Copyright(c): 2023-24
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This module is copyright property of the author mentioned above.
|
||||
|
|
@ -11,12 +11,12 @@
|
|||
|
||||
{
|
||||
'name': 'Simplify Access Management',
|
||||
'version': '14.0.11.4.5',
|
||||
'version': '14.0.12.8.5',
|
||||
'sequence': 5,
|
||||
'author': 'Terabits Technolab',
|
||||
'license': 'OPL-1',
|
||||
'category': 'Odex25-base',
|
||||
'website': 'https://www.terabits.xyz/r/SNS',
|
||||
'category': 'Services',
|
||||
'website': 'https://www.terabits.xyz/apps/14.0/simplify_access_management',
|
||||
'summary': """All In One Access Management App for setting the correct access rights for fields, models, menus, views for any module and for any user.
|
||||
All in one access management App,
|
||||
Easier then Record rules setup,
|
||||
|
|
@ -160,11 +160,11 @@
|
|||
|
||||
""",
|
||||
"images": ["static/description/banner.gif"],
|
||||
"price": "370.99",
|
||||
"price": "280.99",
|
||||
"currency": "USD",
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'security/res_groups.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'data/view_data.xml',
|
||||
'views/access_management_view.xml',
|
||||
'views/assets.xml',
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# from . import main
|
||||
from . import action
|
||||
|
||||
from . import export
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
from odoo import http
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.addons.web.controllers.main import Export
|
||||
from odoo.http import request
|
||||
|
||||
class Export(Export):
|
||||
|
||||
def fields_get(self, model):
|
||||
fields=super().fields_get(model)
|
||||
invisible_field_ids = request.env['hide.field'].sudo().search(
|
||||
[('access_management_id.company_ids', 'in', request.env.company.id),
|
||||
('model_id.model', '=', model), ('access_management_id.active', '=', True),
|
||||
('access_management_id.user_ids', 'in', request.env.user.id),
|
||||
('invisible','=',True)])
|
||||
if not invisible_field_ids:
|
||||
return fields
|
||||
else :
|
||||
for key, value in list(fields.items()):
|
||||
for invisible_field in invisible_field_ids.field_id:
|
||||
if key == invisible_field.name and key != "id":
|
||||
del fields[key]
|
||||
return fields
|
||||
|
|
@ -10,14 +10,15 @@ class access_domain_ah(models.Model):
|
|||
'ir.model', string='Model', index=True, required=True, ondelete='cascade')
|
||||
model_name = fields.Char(string='Model Name', related='model_id.model', readonly=True, store=True)
|
||||
apply_domain = fields.Boolean('Apply Filter')
|
||||
domain = fields.Char(string='Filter', default='[]')
|
||||
domain = fields.Char(string='Filter', default='[]',
|
||||
help="The create customised domain rule where we can customise rule by selecting specific fields and records")
|
||||
|
||||
access_management_id = fields.Many2one('access.management','Access Management')
|
||||
|
||||
read_right = fields.Boolean('Read',default=True)
|
||||
create_right = fields.Boolean('Create')
|
||||
write_right = fields.Boolean('Write')
|
||||
delete_right = fields.Boolean('Delete')
|
||||
read_right = fields.Boolean('Read',default=True, help="The set 'Read' access of the selected model for the specified users")
|
||||
create_right = fields.Boolean('Create', help="The set 'Create' access of the selected model for the specified users")
|
||||
write_right = fields.Boolean('Write', help="The set 'Write' access of the selected model for the specified users")
|
||||
delete_right = fields.Boolean('Delete', help="The set 'Delete' access of the selected model for the specified users")
|
||||
|
||||
@api.onchange('apply_domain')
|
||||
def _check_domain(self):
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ class access_management(models.Model):
|
|||
active = fields.Boolean('Active', default=True)
|
||||
|
||||
hide_menu_ids = fields.Many2many('ir.ui.menu', 'access_management_menu_rel_ah', 'access_management_id', 'menu_id',
|
||||
'Hide Menu')
|
||||
'Hide Menu',
|
||||
help="The menu or submenu added on above list will be hidden from the defined users.")
|
||||
hide_field_ids = fields.One2many('hide.field', 'access_management_id', 'Hide Field', copy=True)
|
||||
|
||||
remove_action_ids = fields.One2many('remove.action', 'access_management_id', 'Remove Action', copy=True)
|
||||
|
|
@ -32,16 +33,21 @@ class access_management(models.Model):
|
|||
# Chatter
|
||||
hide_chatter_ids = fields.One2many('hide.chatter', 'access_management_id', 'Hide Chatter', copy=True)
|
||||
|
||||
hide_chatter = fields.Boolean('Hide Chatter')
|
||||
hide_send_mail = fields.Boolean('Hide Send Message')
|
||||
hide_log_notes = fields.Boolean('Hide Log Notes')
|
||||
hide_schedule_activity = fields.Boolean('Hide Schedule Activity')
|
||||
hide_chatter = fields.Boolean('Hide Chatter',
|
||||
help="The Chatter will be hidden in all model from the specified users.")
|
||||
hide_send_mail = fields.Boolean('Hide Send Message',
|
||||
help="The Send Message button will be hidden in chatter of all model from the specified users.")
|
||||
hide_log_notes = fields.Boolean('Hide Log Notes',
|
||||
help="The Log Notes button will be hidden in chatter of all model from the specified users.")
|
||||
hide_schedule_activity = fields.Boolean('Hide Schedule Activity',
|
||||
help="The Schedule Activity button will be hidden in chatter of all model from the specified users.")
|
||||
|
||||
hide_export = fields.Boolean()
|
||||
hide_import = fields.Boolean()
|
||||
disable_login = fields.Boolean('Disable Login')
|
||||
hide_export = fields.Boolean(help="The Export button will be hidden in all model from the specified users.")
|
||||
hide_import = fields.Boolean(help="The Import button will be hidden in all model from the specified users.")
|
||||
disable_login = fields.Boolean('Disable Login',help="The Users can not login if this button is chek.")
|
||||
|
||||
disable_debug_mode = fields.Boolean('Disable Developer Mode')
|
||||
disable_debug_mode = fields.Boolean('Disable Developer Mode',
|
||||
help="Developer mode will be hidden from the defined users.")
|
||||
|
||||
company_ids = fields.Many2many('res.company', 'access_management_comapnay_rel', 'access_management_id',
|
||||
'company_id', 'Companies', required=True, default=lambda self: self.env.company)
|
||||
|
|
@ -49,6 +55,7 @@ class access_management(models.Model):
|
|||
hide_filters_groups_ids = fields.One2many('hide.filters.groups', 'access_management_id', 'Hide Filters/Group By',
|
||||
copy=True)
|
||||
|
||||
is_apply_on_without_company = fields.Boolean()
|
||||
def _count_total_rules(self):
|
||||
for rec in self:
|
||||
rule = 0
|
||||
|
|
@ -110,7 +117,7 @@ class access_management(models.Model):
|
|||
return res
|
||||
|
||||
def get_remove_options(self, model):
|
||||
restrict_export = self.env['access.management'].search([('company_ids', 'in', self.env.company.id),
|
||||
restrict_export = self.env['access.management'].sudo().search([('company_ids', 'in', self.env.company.id),
|
||||
('active', '=', True),
|
||||
('user_ids', 'in', self.env.user.id),
|
||||
('hide_export', '=', True)], limit=1).id
|
||||
|
|
@ -158,7 +165,7 @@ class access_management(models.Model):
|
|||
hide_schedule_activity = False
|
||||
|
||||
if model and hide_send_mail or hide_log_notes or hide_schedule_activity:
|
||||
hide_ids = self.env['hide.chatter'].search([('access_management_id.company_ids', 'in', company_id),
|
||||
hide_ids = self.env['hide.chatter'].sudo().search([('access_management_id.company_ids', 'in', company_id),
|
||||
('access_management_id.active', '=', True),
|
||||
('access_management_id.user_ids', 'in', user_id),
|
||||
('model_id.model', '=', model)])
|
||||
|
|
@ -192,9 +199,23 @@ class access_management(models.Model):
|
|||
break
|
||||
|
||||
if not hide_export and model:
|
||||
if self.env['remove.action'].search([('access_management_id', 'in', access_ids.ids),
|
||||
if self.env['remove.action'].sudo().search([('access_management_id', 'in', access_ids.ids),
|
||||
('model_id.model', '=', model),
|
||||
('restrict_export', '=', True)]):
|
||||
hide_export = True
|
||||
|
||||
return hide_export
|
||||
|
||||
def get_hidden_field(self, model=False):
|
||||
if model:
|
||||
hidden_fields = []
|
||||
hide_field_obj = self.env['hide.field'].sudo()
|
||||
for hide_field in hide_field_obj.search(
|
||||
[('access_management_id.company_ids', 'in', self.env.company.id),
|
||||
('model_id.model', '=', model), ('access_management_id.active', '=', True),
|
||||
('access_management_id.user_ids', 'in', self._uid), ('invisible', '=', True)]):
|
||||
for field in hide_field.field_id:
|
||||
if field.name:
|
||||
hidden_fields.append(field.name)
|
||||
return hidden_fields
|
||||
return []
|
||||
|
|
@ -9,7 +9,9 @@ class hide_chatter(models.Model):
|
|||
access_management_id = fields.Many2one('access.management', 'Access Management')
|
||||
model_id = fields.Many2one('ir.model', 'Model')
|
||||
|
||||
hide_chatter = fields.Boolean('Chatter')
|
||||
hide_send_mail = fields.Boolean('Send Message')
|
||||
hide_log_notes = fields.Boolean('Log Notes')
|
||||
hide_schedule_activity = fields.Boolean('Schedule Activity')
|
||||
hide_chatter = fields.Boolean('Chatter'
|
||||
,help="The Chatter will be hidden in selected model from the specified users.")
|
||||
hide_send_mail = fields.Boolean('Send Message'
|
||||
,help="The Send Message button will be hidden in chatter of selected model from the specified users.")
|
||||
hide_log_notes = fields.Boolean('Log Notes', help="The Log Notes button will be hidden in chatter of selected model from the specified users.")
|
||||
hide_schedule_activity = fields.Boolean('Schedule Activity',help="The Schedule Activity button will be hidden in chatter of selected model from the specified users.")
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ class hide_field(models.Model):
|
|||
|
||||
field_id = fields.Many2many('ir.model.fields', 'hide_field_ir_model_fields_rel', 'hide_field_id', 'ir_field_id', 'Field')
|
||||
|
||||
invisible = fields.Boolean('Invisible')
|
||||
readonly = fields.Boolean('Read-Only')
|
||||
required = fields.Boolean('Required')
|
||||
external_link = fields.Boolean('Remove External Link')
|
||||
invisible = fields.Boolean('Invisible', help="Selected Field will be hidden in selected model from the defined users.")
|
||||
readonly = fields.Boolean('Read-Only', help="Selected Field will be Read only in selected model from the defined users.")
|
||||
required = fields.Boolean('Required', help="Selected Field will be set as required for selected model from the defined users.")
|
||||
external_link = fields.Boolean('Remove External Link',help="External Link will be hidden for relational fields in selected model from the defined users.")
|
||||
|
||||
|
|
|
|||
|
|
@ -9,9 +9,11 @@ class hide_filters_groups(models.Model):
|
|||
model_name = fields.Char(string='Model Name', related='model_id.model', readonly=True, store=True)
|
||||
|
||||
filters_store_model_nodes_ids = fields.Many2many('store.filters.groups', 'filters_hide_filters_groups_store_filters_groups_rel',
|
||||
'hide_id', 'store_id', string='Hide Filters', domain="[('node_option','=','filter')]")
|
||||
'hide_id', 'store_id', string='Hide Filters', domain="[('node_option','=','filter')]",
|
||||
help="The Defalut filter are added on list will be hidden in search view of selected model from the specified users.")
|
||||
groups_store_model_nodes_ids = fields.Many2many('store.filters.groups', 'groups_hide_filters_groups_store_filters_groups_rel',
|
||||
'hide_id', 'store_id', string='Hide Groups', domain="[('node_option','=','group')]")
|
||||
'hide_id', 'store_id', string='Hide Groups', domain="[('node_option','=','group')]",
|
||||
help="The Defalut Group are added on list will be hidden in search view of selected model from the specified users.")
|
||||
|
||||
access_management_id = fields.Many2one('access.management', 'Access Management')
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,12 @@ class hide_view_nodes(models.Model):
|
|||
|
||||
model_name = fields.Char(string='Model Name', related='model_id.model', readonly=True, store=True)
|
||||
|
||||
btn_store_model_nodes_ids = fields.Many2many('store.model.nodes','btn_hide_view_nodes_store_model_nodes_rel','hide_id','store_id',string='Hide Button',domain="[('node_option','=','button')]")
|
||||
page_store_model_nodes_ids = fields.Many2many('store.model.nodes','page_hide_view_nodes_store_model_nodes_rel','hide_id','store_id',string='Hide Tab/Page',domain="[('node_option','=','page')]")
|
||||
link_store_model_nodes_ids = fields.Many2many('store.model.nodes','link_hide_view_nodes_store_model_nodes_rel','hide_id','store_id',string='Hide Kanban Link',domain="[('node_option','=','link')]")
|
||||
btn_store_model_nodes_ids = fields.Many2many('store.model.nodes','btn_hide_view_nodes_store_model_nodes_rel','hide_id','store_id',string='Hide Button',domain="[('node_option','=','button')]",
|
||||
help="The Buttons are added on list will be hidden in selected model from the defined users.")
|
||||
page_store_model_nodes_ids = fields.Many2many('store.model.nodes','page_hide_view_nodes_store_model_nodes_rel','hide_id','store_id',string='Hide Tab/Page',domain="[('node_option','=','page')]",
|
||||
help="The Tabs(pages) are added on list will be hidden in selected model from the defined users.")
|
||||
link_store_model_nodes_ids = fields.Many2many('store.model.nodes','link_hide_view_nodes_store_model_nodes_rel','hide_id','store_id',string='Hide Kanban Link',domain="[('node_option','=','link')]",
|
||||
help="The Kanban view action are added on list will be hidden in selected model from the defined users.")
|
||||
|
||||
access_management_id = fields.Many2one('access.management','Access Management')
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
from odoo.http import request
|
||||
from odoo import api, fields, models, tools, _
|
||||
from odoo.exceptions import Warning, ValidationError, AccessError
|
||||
from odoo import api, fields, models, tools,_
|
||||
from odoo.exceptions import Warning, ValidationError,AccessError
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ir_model_access(models.Model):
|
||||
_inherit = 'ir.model.access'
|
||||
|
||||
|
||||
|
||||
# The context parameter is useful when the method translates error messages.
|
||||
# But as the method raises an exception in that case, the key 'lang' might
|
||||
# not be really necessary as a cache key, unless the `ormcache_context`
|
||||
|
|
@ -31,6 +32,7 @@ class ir_model_access(models.Model):
|
|||
|
||||
self.flush(self._fields)
|
||||
|
||||
|
||||
"""
|
||||
This part is writen to by pass base access rule and apply dynamic rule of access management rule,
|
||||
In case of any record found in access management.
|
||||
|
|
@ -41,7 +43,7 @@ class ir_model_access(models.Model):
|
|||
if model:
|
||||
self._cr.execute("SELECT id FROM ir_model WHERE model='" + model + "'")
|
||||
model_numeric_id = self._cr.fetchone()[0]
|
||||
if model_numeric_id and isinstance(model_numeric_id, int) and self.env.user:
|
||||
if model_numeric_id and isinstance(model_numeric_id,int) and self.env.user:
|
||||
try:
|
||||
self._cr.execute("""
|
||||
SELECT dm.id
|
||||
|
|
@ -53,13 +55,14 @@ class ir_model_access(models.Model):
|
|||
IN (SELECT amusr.access_management_id
|
||||
FROM access_management_users_rel_ah as amusr
|
||||
WHERE amusr.user_id=%s))
|
||||
""", [model_numeric_id, self.env.user.id])
|
||||
""",[model_numeric_id, self.env.user.id])
|
||||
except:
|
||||
pass
|
||||
access_domain_ah_ids = self.env['access.domain.ah'].browse(row[0] for row in self._cr.fetchall()).filtered(lambda line: self.env.company in line.access_management_id.company_ids)
|
||||
access_domain_ah_ids = self.env['access.domain.ah'].sudo().browse(row[0] for row in self._cr.fetchall()).filtered(lambda line: self.env.company in line.access_management_id.company_ids)
|
||||
if access_domain_ah_ids:
|
||||
return True
|
||||
|
||||
|
||||
# We check if a specific rule exists
|
||||
self._cr.execute("""SELECT MAX(CASE WHEN perm_{mode} THEN 1 ELSE 0 END)
|
||||
FROM ir_model_access a
|
||||
|
|
@ -88,7 +91,7 @@ class ir_model_access(models.Model):
|
|||
msg_heads = {
|
||||
# Messages are declared in extenso so they are properly exported in translation terms
|
||||
'read': _("You are not allowed to access '%(document_kind)s' (%(document_model)s) records.", document_kind=document_kind, document_model=model),
|
||||
'write': _("You are not allowed to modify '%(document_kind)s' (%(document_model)s) records.", document_kind=document_kind, document_model=model),
|
||||
'write': _("You are not allowed to modify '%(document_kind)s' (%(document_model)s) records.", document_kind=document_kind, document_model=model),
|
||||
'create': _("You are not allowed to create '%(document_kind)s' (%(document_model)s) records.", document_kind=document_kind, document_model=model),
|
||||
'unlink': _("You are not allowed to delete '%(document_kind)s' (%(document_model)s) records.", document_kind=document_kind, document_model=model),
|
||||
}
|
||||
|
|
@ -102,7 +105,11 @@ class ir_model_access(models.Model):
|
|||
resolution_info = _("Contact your administrator to request access if necessary.")
|
||||
|
||||
_logger.info('Access Denied by ACLs for operation: %s, uid: %s, model: %s', mode, self._uid, model)
|
||||
msg = """{operation_error} {group_info} {resolution_info}""".format(
|
||||
msg = """{operation_error}
|
||||
|
||||
{group_info}
|
||||
|
||||
{resolution_info}""".format(
|
||||
operation_error=operation_error,
|
||||
group_info=group_info,
|
||||
resolution_info=resolution_info)
|
||||
|
|
@ -116,18 +123,15 @@ class ir_model_access(models.Model):
|
|||
if data and data[0] != 'installed':
|
||||
read_value = False
|
||||
if self.env.user.id and read_value:
|
||||
company_id = request.httprequest.cookies.get('cids') and request.httprequest.cookies.get('cids').split(',')[0] or request.env.company.id
|
||||
a = "select access_management_id from access_management_comapnay_rel where company_id = " + company_id
|
||||
if not company_id:
|
||||
a = "select access_management_id from access_management_comapnay_rel where company_id = NULL"
|
||||
a = "select access_management_id from access_management_comapnay_rel where company_id = " + str(request.httprequest.cookies.get('cids') and request.httprequest.cookies.get('cids').split(',')[0] or request.env.company.id)
|
||||
self._cr.execute(a)
|
||||
a = self._cr.fetchall()
|
||||
if a:
|
||||
a = "select access_management_id from access_management_users_rel_ah where user_id = " + str(self.env.user.id) + " AND access_management_id in " + str(tuple([i[0] for i in a] + [0]))
|
||||
a = "select access_management_id from access_management_users_rel_ah where user_id = " + str(self.env.user.id) + " AND access_management_id in " + str(tuple([i[0] for i in a]+[0]))
|
||||
self._cr.execute(a)
|
||||
a = self._cr.fetchall()
|
||||
if a:
|
||||
a = "SELECT id FROM access_management WHERE active='t' AND id in " + str(tuple([i[0] for i in a] + [0])) + " and readonly = True"
|
||||
a = "SELECT id FROM access_management WHERE active='t' AND id in " + str(tuple([i[0] for i in a]+[0])) + " and readonly = True"
|
||||
self._cr.execute(a)
|
||||
a = self._cr.fetchall()
|
||||
if bool(a):
|
||||
|
|
@ -136,4 +140,5 @@ class ir_model_access(models.Model):
|
|||
except:
|
||||
pass
|
||||
|
||||
|
||||
return bool(r)
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ class ir_rule(models.Model):
|
|||
model_list = ['mail.activity','res.users.log','res.users','mail.channel','mail.alias','bus.presence','res.lang']
|
||||
if self.env.user.id and read_value and not all_data:
|
||||
if model_name not in model_list:
|
||||
# self._cr.execute("""SELECT am.id FROM access_management as am
|
||||
# WHERE active='t' AND readonly = True AND am.id
|
||||
# IN (SELECT au.access_management_id
|
||||
# FROM access_management_users_rel_ah as au
|
||||
# WHERE user_id = %s AND am.id
|
||||
# IN (SELECT ac.access_management_id
|
||||
# FROM access_management_comapnay_rel as ac
|
||||
# WHERE ac.company_id=%s))"""%(self.env.user.id, self.env.company.id))
|
||||
self._cr.execute("""SELECT am.id FROM access_management as am
|
||||
WHERE active='t' AND readonly = True AND am.id
|
||||
IN (SELECT au.access_management_id
|
||||
FROM access_management_users_rel_ah as au
|
||||
WHERE user_id = %s AND am.id
|
||||
IN (SELECT ac.access_management_id
|
||||
FROM access_management_comapnay_rel as ac
|
||||
WHERE ac.company_id=%s))"""%(self.env.user.id, self.env.company.id))
|
||||
# a = "select access_management_id from access_management_comapnay_rel where company_id = " + str(self.env.company.id)
|
||||
# self._cr.execute(a)
|
||||
# a = self._cr.fetchall()
|
||||
|
|
@ -85,11 +85,13 @@ class ir_rule(models.Model):
|
|||
""", [model_numeric_id, self.env.user.id])
|
||||
except:
|
||||
pass
|
||||
access_domain_ah_ids = self.env['access.domain.ah'].browse(
|
||||
access_domain_ah_ids = self.env['access.domain.ah'].sudo().browse(
|
||||
row[0] for row in self._cr.fetchall()).filtered(
|
||||
lambda line: self.env.company in line.access_management_id.company_ids)
|
||||
# access_domain_ah_ids = access_domain_ah_ids.filtered(lambda line: self.env.company in line.access_management_id.company_ids)
|
||||
if access_domain_ah_ids:
|
||||
all_company = self.env['res.company'].sudo().search([]).ids
|
||||
company_domain = []
|
||||
domain_list = []
|
||||
if model_name == 'res.partner':
|
||||
# jo aya user related jetala partner 6 ana access alag thi apididha 6 error no ave atle
|
||||
|
|
@ -99,8 +101,23 @@ class ir_rule(models.Model):
|
|||
eval_context = self._eval_context()
|
||||
# only domain records
|
||||
length = len(access_domain_ah_ids.sudo()) if access_domain_ah_ids.sudo() else 0
|
||||
com_domain=[]
|
||||
for access in access_domain_ah_ids.sudo():
|
||||
dom = safe_eval(access.domain, eval_context) if access.domain else []
|
||||
if not dom and isinstance(dom,list):
|
||||
if length>1:
|
||||
domain_list.insert(0,'|')
|
||||
domain_list += [('id', '!=', False)]
|
||||
length -= 1
|
||||
company_domain=[]
|
||||
if self.env[model_name]._fields.get('company_id'):
|
||||
if res:
|
||||
for domain_tuple in res:
|
||||
|
||||
if isinstance(domain_tuple,tuple) and domain_tuple[0] == 'company_id':
|
||||
all_company = self.env['res.company'].sudo().browse(domain_tuple[2]).ids
|
||||
company_domain_tuple = ('company_id','in',access.access_management_id.company_ids.ids)
|
||||
company_domain.append(company_domain_tuple)
|
||||
if dom:
|
||||
dom = expression.normalize_domain(dom)
|
||||
for dom_tuple in dom:
|
||||
|
|
@ -138,14 +155,49 @@ class ir_rule(models.Model):
|
|||
right_value[zero_index] = self.env.company.id
|
||||
if operator_value == 'date_filter':
|
||||
domain_list += prepare_domain_v2(dom_tuple)
|
||||
domain_list.insert(0,'&')
|
||||
domain_list+= company_domain
|
||||
else:
|
||||
domain_list.append(dom_tuple)
|
||||
if company_domain:
|
||||
company_domain.append(dom_tuple)
|
||||
domain_list.insert(0,'&')
|
||||
domain_list+= company_domain
|
||||
|
||||
else:
|
||||
domain_list.append(dom_tuple)
|
||||
else:
|
||||
domain_list.append(dom_tuple)
|
||||
if length > 1:
|
||||
domain_list.insert(0, '|')
|
||||
length -= 1
|
||||
|
||||
if self.env[model_name]._fields.get('company_id'):
|
||||
if res:
|
||||
for domain_tuple in res:
|
||||
dom = domain_tuple
|
||||
if isinstance(dom,tuple):
|
||||
if domain_tuple[0] == 'company_id':
|
||||
if len(all_company)>1:
|
||||
for company in access.access_management_id.company_ids.ids:
|
||||
if company in all_company:
|
||||
all_company.remove(company)
|
||||
if all_company and False not in all_company:
|
||||
if access.access_management_id.is_apply_on_without_company:
|
||||
domain = ('company_id','in',all_company+[False])
|
||||
else:
|
||||
domain = ('company_id','in',all_company)
|
||||
if domain not in com_domain:
|
||||
com_domain.append(('company_id','in',all_company))
|
||||
else:
|
||||
if isinstance(domain_tuple[2],list):
|
||||
if domain_tuple[2][0] not in access.access_management_id.company_ids.ids:
|
||||
com_domain.append(domain_tuple)
|
||||
else:
|
||||
com_domain.append(domain_tuple)
|
||||
if domain_list:
|
||||
if com_domain:
|
||||
domain_list.insert(0, '|')
|
||||
domain_list+=com_domain
|
||||
return domain_list
|
||||
|
||||
return res
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ class ir_ui_view(models.Model):
|
|||
hide_button_obj = self.env['hide.view.nodes']
|
||||
if name_manager.Model._name == 'res.config.settings' and node.tag == 'div' and node.get('string'):
|
||||
for setting_tab in hide_button_obj.sudo().search([('access_management_id.company_ids','in',self.env.company.id),('model_id.model','=',name_manager.Model._name),('access_management_id.active','=',True),('access_management_id.user_ids','in',self._uid)]).mapped('page_store_model_nodes_ids'):
|
||||
if node.get('string') == setting_tab.attribute_string and node.get('data-key') == setting_tab.attribute_name:
|
||||
if node.get('data-key') == setting_tab.attribute_name:
|
||||
node_info['modifiers']['invisible'] = True
|
||||
node.set('invisible', '1')
|
||||
if node.tag == 'a':
|
||||
if node.text and '\n' not in node.text and 'type' in node.attrib.keys() and node.attrib['type'] and 'name' in node.attrib.keys() and node.attrib['name']:
|
||||
if hide_view_node_obj.search([
|
||||
if hide_view_node_obj.sudo().search([
|
||||
('model_id.model','=',name_manager.Model._name),
|
||||
('access_management_id.active','=',True),
|
||||
('access_management_id.company_ids','in',self.env.company.id),
|
||||
|
|
@ -38,7 +38,7 @@ class ir_ui_view(models.Model):
|
|||
if hide_field.external_link:
|
||||
options_dict = {}
|
||||
if 'widget' in node.attrib.keys():
|
||||
if node.attrib['widget'] == 'product_configurator':
|
||||
if node.attrib['widget'] == 'product_configurator' or node.attrib['widget'] == 'many2one_avatar_user':
|
||||
del node.attrib['widget']
|
||||
if 'options' in node.attrib.keys():
|
||||
options_dict = ast.literal_eval(node.attrib['options'])
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class BaseModel(models.AbstractModel):
|
|||
@api.model
|
||||
def load_views(self, views, options=None):
|
||||
actions_and_prints = []
|
||||
for access in self.env['remove.action'].search([('access_management_id.company_ids', 'in', self.env.company.id),
|
||||
for access in self.env['remove.action'].sudo().search([('access_management_id.company_ids', 'in', self.env.company.id),
|
||||
('access_management_id', 'in',
|
||||
self.env.user.access_management_ids.ids),
|
||||
('model_id.model', '=', self._name)]):
|
||||
|
|
@ -49,13 +49,13 @@ class BaseModel(models.AbstractModel):
|
|||
res = super().fields_view_get(view_id, view_type, toolbar, submenu)
|
||||
access_management_obj = self.env['access.management']
|
||||
cids = request.httprequest.cookies.get('cids') and request.httprequest.cookies.get('cids').split(',')[0] or request.env.company.id
|
||||
readonly_access_id = access_management_obj.search([('company_ids','in',int(cids)),('active','=',True),('user_ids','in',self.env.user.id),('readonly','=',True)])
|
||||
readonly_access_id = access_management_obj.sudo().search([('company_ids','in',int(cids)),('active','=',True),('user_ids','in',self.env.user.id),('readonly','=',True)])
|
||||
|
||||
access_recs = self.env['access.domain.ah'].search([('access_management_id.company_ids','in',self.env.company.id),('access_management_id.user_ids','in',self.env.user.id),('access_management_id.active','=',True),('model_id.model','=',res['model'])])
|
||||
access_model_recs = self.env['remove.action'].search([('access_management_id.company_ids','in',self.env.company.id),('access_management_id.user_ids','in',self.env.user.id),('access_management_id.active','=',True),('model_id.model','=',res['model'])])
|
||||
access_recs = self.env['access.domain.ah'].sudo().search([('access_management_id.company_ids','in',self.env.company.id),('access_management_id.user_ids','in',self.env.user.id),('access_management_id.active','=',True),('model_id.model','=',res['model'])])
|
||||
access_model_recs = self.env['remove.action'].sudo().search([('access_management_id.company_ids','in',self.env.company.id),('access_management_id.user_ids','in',self.env.user.id),('access_management_id.active','=',True),('model_id.model','=',res['model'])])
|
||||
|
||||
if view_type == 'form':
|
||||
access_management_id = access_management_obj.search([('company_ids', 'in', self.env.company.id),
|
||||
access_management_id = access_management_obj.sudo().search([('company_ids', 'in', self.env.company.id),
|
||||
('active', '=', True),
|
||||
('user_ids', 'in', self.env.user.id),
|
||||
('hide_chatter', '=', True)],
|
||||
|
|
@ -66,7 +66,7 @@ class BaseModel(models.AbstractModel):
|
|||
div.getparent().remove(div)
|
||||
res['arch'] = etree.tostring(doc, encoding='unicode')
|
||||
else:
|
||||
if self.env['hide.chatter'].search([('access_management_id.company_ids', 'in', self.env.company.id),
|
||||
if self.env['hide.chatter'].sudo().search([('access_management_id.company_ids', 'in', self.env.company.id),
|
||||
('access_management_id.active', '=', True),
|
||||
('access_management_id.user_ids', 'in', self.env.user.id),
|
||||
('model_id.model', '=', self._name),
|
||||
|
|
@ -78,7 +78,7 @@ class BaseModel(models.AbstractModel):
|
|||
div.getparent().remove(div)
|
||||
res['arch'] = etree.tostring(doc, encoding='unicode')
|
||||
|
||||
restrict_import = access_management_obj.search([('company_ids', 'in', self.env.company.id),
|
||||
restrict_import = access_management_obj.sudo().search([('company_ids', 'in', self.env.company.id),
|
||||
('active', '=', True),
|
||||
('user_ids', 'in', self.env.user.id),
|
||||
('hide_import', '=', True)], limit=1).id
|
||||
|
|
@ -187,7 +187,7 @@ class BaseModel(models.AbstractModel):
|
|||
FROM access_management_users_rel_ah as amusr
|
||||
WHERE amusr.user_id=%s))
|
||||
""",[model_numeric_id, self.env.user.id])
|
||||
records = self.env['access.domain.ah'].browse(row[0] for row in self._cr.fetchall())
|
||||
records = self.env['access.domain.ah'].sudo().browse(row[0] for row in self._cr.fetchall())
|
||||
except:
|
||||
pass
|
||||
return records
|
||||
|
|
@ -214,50 +214,50 @@ class BaseModel(models.AbstractModel):
|
|||
domain_list += partner_domain
|
||||
# eval_context = rec._eval_context()
|
||||
dom = safe_eval(record.domain) if record.domain else []
|
||||
dom = expression.normalize_domain(dom)
|
||||
model_name = self._name
|
||||
if isinstance(dom,list):
|
||||
remove_tuple = False
|
||||
for dom_tuple in dom:
|
||||
if isinstance(dom_tuple, tuple):
|
||||
left_value = dom_tuple[0]
|
||||
operator_value = dom_tuple[1]
|
||||
right_value = dom_tuple[2]
|
||||
left_value_split_list = left_value.split('.')
|
||||
model_string = model_name
|
||||
left_user = False
|
||||
left_company = False
|
||||
for field in left_value_split_list:
|
||||
if dom:
|
||||
dom = expression.normalize_domain(dom)
|
||||
model_name = self._name
|
||||
if isinstance(dom,list):
|
||||
for dom_tuple in dom:
|
||||
if isinstance(dom_tuple, tuple):
|
||||
left_value = dom_tuple[0]
|
||||
operator_value = dom_tuple[1]
|
||||
right_value = dom_tuple[2]
|
||||
left_value_split_list = left_value.split('.')
|
||||
model_string = model_name
|
||||
left_user = False
|
||||
left_company = False
|
||||
model_obj = self.env[model_string]
|
||||
field_type = model_obj.fields_get()[field]['type']
|
||||
if field_type in ['many2one', 'many2many', 'one2many']:
|
||||
field_relation = model_obj.fields_get()[field]['relation']
|
||||
model_string = field_relation
|
||||
if model_string == 'res.users':
|
||||
left_user = True
|
||||
if model_string == 'res.company':
|
||||
left_company = True
|
||||
for field in left_value_split_list:
|
||||
left_user = False
|
||||
left_company = False
|
||||
model_obj = self.env[model_string]
|
||||
field_type = model_obj.fields_get()[field]['type']
|
||||
if field_type in ['many2one', 'many2many', 'one2many']:
|
||||
field_relation = model_obj.fields_get()[field]['relation']
|
||||
model_string = field_relation
|
||||
if model_string == 'res.users':
|
||||
left_user = True
|
||||
if model_string == 'res.company':
|
||||
left_company = True
|
||||
|
||||
if left_user:
|
||||
if operator_value in ['in', 'not in']:
|
||||
if isinstance(right_value, list) and 0 in right_value:
|
||||
zero_index = right_value.index(0)
|
||||
right_value[zero_index] = self.env.user.id
|
||||
if left_user:
|
||||
if operator_value in ['in', 'not in']:
|
||||
if isinstance(right_value, list) and 0 in right_value:
|
||||
zero_index = right_value.index(0)
|
||||
right_value[zero_index] = self.env.user.id
|
||||
|
||||
if left_company:
|
||||
if operator_value in ['in', 'not in']:
|
||||
if isinstance(right_value, list) and 0 in right_value:
|
||||
zero_index = right_value.index(0)
|
||||
right_value[zero_index] = self.env.company.id
|
||||
already_add = False
|
||||
if operator_value == 'date_filter':
|
||||
domain_list += prepare_domain_v2(dom_tuple)
|
||||
if left_company:
|
||||
if operator_value in ['in', 'not in']:
|
||||
if isinstance(right_value, list) and 0 in right_value:
|
||||
zero_index = right_value.index(0)
|
||||
right_value[zero_index] = self.env.company.id
|
||||
already_add = False
|
||||
if operator_value == 'date_filter':
|
||||
domain_list += prepare_domain_v2(dom_tuple)
|
||||
else:
|
||||
domain_list.append(dom_tuple)
|
||||
else:
|
||||
domain_list.append(dom_tuple)
|
||||
else:
|
||||
domain_list.append(dom_tuple)
|
||||
# if length > 1:
|
||||
# domain_list.insert(0, '|')
|
||||
# length -= 1
|
||||
|
|
|
|||
|
|
@ -7,16 +7,23 @@ class remove_action(models.Model):
|
|||
|
||||
access_management_id = fields.Many2one('access.management', 'Access Management')
|
||||
model_id = fields.Many2one('ir.model', 'Model')
|
||||
view_data_ids = fields.Many2many('view.data', 'remove_action_view_data_rel_ah', 'remove_action_id', 'view_data_id', 'Hide Views')
|
||||
server_action_ids = fields.Many2many('action.data' ,'remove_action_server_action_data_rel_ah', 'remove_action_id', 'server_action_id', 'Hide Actions', domain="[('action_id.binding_model_id','=',model_id),('action_id.type','!=','ir.actions.report')]")
|
||||
report_action_ids = fields.Many2many('action.data' ,'remove_action_report_action_data_rel_ah', 'remove_action_id', 'report_action_id', 'Hide Reports', domain="[('action_id.binding_model_id','=',model_id),('action_id.type','=','ir.actions.report')]")
|
||||
restrict_export = fields.Boolean('Hide Export')
|
||||
restrict_import = fields.Boolean('Hide Import')
|
||||
view_data_ids = fields.Many2many('view.data', 'remove_action_view_data_rel_ah', 'remove_action_id', 'view_data_id', 'Hide Views',
|
||||
help="The views are added on list will be hidden in selected model from the defined users.")
|
||||
server_action_ids = fields.Many2many('action.data' ,'remove_action_server_action_data_rel_ah', 'remove_action_id', 'server_action_id', 'Hide Actions', domain="[('action_id.binding_model_id','=',model_id),('action_id.type','!=','ir.actions.report')]",
|
||||
help="The actions are added on list will be hidden in selected model from the defined users.")
|
||||
report_action_ids = fields.Many2many('action.data' ,'remove_action_report_action_data_rel_ah', 'remove_action_id', 'report_action_id', 'Hide Reports', domain="[('action_id.binding_model_id','=',model_id),('action_id.type','=','ir.actions.report')]",
|
||||
help="The Reports are added on list will be hidden in selected model from the defined users.")
|
||||
restrict_export = fields.Boolean('Hide Export',
|
||||
help="Export Button will be hidden in selected model from the defined users.")
|
||||
restrict_import = fields.Boolean('Hide Import',
|
||||
help="Import Button will be hidden in selected model from the defined users.")
|
||||
readonly = fields.Boolean('Read-Only')
|
||||
|
||||
restrict_create = fields.Boolean('Hide Create')
|
||||
restrict_edit = fields.Boolean('Hide Edit')
|
||||
restrict_delete = fields.Boolean('Hide Delete')
|
||||
restrict_archive_unarchive = fields.Boolean('Hide Archive/Unarchive')
|
||||
restrict_duplicate = fields.Boolean('Hide Duplicate')
|
||||
restrict_chatter = fields.Boolean('Hide Chatter')
|
||||
restrict_create = fields.Boolean('Hide Create',help="Create Button will be hidden in selected model from the defined users.")
|
||||
restrict_edit = fields.Boolean('Hide Edit',
|
||||
help="Edit Button will be hidden in selected model from the defined users.")
|
||||
restrict_delete = fields.Boolean('Hide Delete',
|
||||
help="Delete Button will be hidden in selected model from the defined users.")
|
||||
restrict_archive_unarchive = fields.Boolean('Hide Archive/Unarchive',help="Archive and Unarchive action will be hidden in selected model from the defined users.")
|
||||
restrict_duplicate = fields.Boolean('Hide Duplicate',help="Duplicate action will be hidden in selected model from the defined users.")
|
||||
restrict_chatter = fields.Boolean('Hide Chatter',help="The Chatter will be hidden in selected model from the defined users.")
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class res_users(models.Model):
|
|||
self = api.Environment(cr, SUPERUSER_ID, {})[cls._name]
|
||||
access_management_obj = self.env['access.management']
|
||||
|
||||
if access_management_obj.search([('user_ids','in',res),('disable_login','=',True)]).id:
|
||||
if access_management_obj.sudo().search([('user_ids','in',res),('disable_login','=',True)]).id:
|
||||
raise AccessDenied()
|
||||
except AccessDenied:
|
||||
_logger.info("Login failed for db:%s login:%s from ", db, login)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,22 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_access_management,access.access.management,model_access_management,,1,1,1,1
|
||||
access_remove_action,access.remove.action,model_remove_action,,1,1,1,1
|
||||
access_hide_field,access.hide.field,model_hide_field,,1,1,1,1
|
||||
access_access_management_portal_user,access.access.management.portal.user,model_access_management,,1,0,0,0
|
||||
access_remove_action_portal_user,access.remove.action.portal.user,model_remove_action,,1,0,0,0
|
||||
access_hide_field_portal_user,access.hide.field.portal.user,model_hide_field,,1,0,0,0
|
||||
access_access_domain_ah_portal_user,access.access.domain.ah.portal.user,model_access_domain_ah,,1,0,0,0
|
||||
access_hide_view_nodes_portal_user,access.hide.view.nodes.portal.user,model_hide_view_nodes,,1,0,0,0
|
||||
access_hide_filters_groups_portal_user,access_hide_filters_groups_portal_user,model_hide_filters_groups,base.group_user,1,0,0,0
|
||||
access_hide_chatter_portal_user,access.hide.chatter.portal.user,model_hide_chatter,,1,0,0,0
|
||||
|
||||
access_action_data,access.action.data,model_action_data,,1,1,1,1
|
||||
access_view_data,access.view.data,model_view_data,,1,1,1,1
|
||||
access_access_domain_ah,access.access.domain.ah,model_access_domain_ah,,1,1,1,1
|
||||
access_hide_view_nodes,access.hide.view.nodes,model_hide_view_nodes,,1,1,1,1
|
||||
access_store_model_nodes,access.store.model.nodes,model_store_model_nodes,,1,1,1,1
|
||||
access_hide_filters_groups,access_hide_filters_groups,model_hide_filters_groups,base.group_user,1,1,1,1
|
||||
access_store_filters_groups,access_store_filters_groups,model_store_filters_groups,base.group_user,1,1,1,1
|
||||
access_hide_chatter,access.hide.chatter,model_hide_chatter,,1,1,1,1
|
||||
access_menu_item,access.menu.item,model_menu_item,,1,1,1,1
|
||||
|
||||
access_access_management,access.access.management,model_access_management,simplify_access_management.group_access_management_bits,1,1,1,1
|
||||
access_access_domain_ah,access.access.domain.ah,model_access_domain_ah,simplify_access_management.group_access_management_bits,1,1,1,1
|
||||
access_remove_action,access.remove.action,model_remove_action,simplify_access_management.group_access_management_bits,1,1,1,1
|
||||
access_hide_field,access.hide.field,model_hide_field,simplify_access_management.group_access_management_bits,1,1,1,1
|
||||
access_hide_view_nodes,access.hide.view.nodes,model_hide_view_nodes,simplify_access_management.group_access_management_bits,1,1,1,1
|
||||
access_hide_filters_groups,access_hide_filters_groups,model_hide_filters_groups,simplify_access_management.group_access_management_bits,1,1,1,1
|
||||
access_hide_chatter,access.hide.chatter,model_hide_chatter,simplify_access_management.group_access_management_bits,1,1,1,1
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="group_access_management_spt" model="res.groups">
|
||||
<record id="group_access_management_bits" model="res.groups">
|
||||
<field name="name">Access Management</field>
|
||||
</record>
|
||||
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 7.5 MiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
|
@ -0,0 +1,35 @@
|
|||
odoo.define("simpily_access_management.custom_filter_item", function (require) {
|
||||
"use strict";
|
||||
|
||||
const ControlPanel = require("web.ControlPanel");
|
||||
const { patch } = require("web.utils");
|
||||
var rpc = require("web.rpc");
|
||||
|
||||
patch(ControlPanel, "ControlPanelPatchBits", {
|
||||
async mounted() {
|
||||
var self = this;
|
||||
this._super(...arguments);
|
||||
self.removedFields = await rpc.query({
|
||||
model: "access.management",
|
||||
method: "get_hidden_field",
|
||||
args: ["", this?.props?.view?.model],
|
||||
});
|
||||
this.removedFields.forEach((element) => {
|
||||
delete self.fields[element];
|
||||
});
|
||||
},
|
||||
|
||||
async patched() {
|
||||
var self = this;
|
||||
this._super(...arguments);
|
||||
self.removedFields = await rpc.query({
|
||||
model: "access.management",
|
||||
method: "get_hidden_field",
|
||||
args: ["", this?.props?.view?.model],
|
||||
});
|
||||
this.removedFields.forEach((element) => {
|
||||
delete self.fields[element];
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
odoo.define(
|
||||
"simpily_access_management.group_by_menu",
|
||||
function (require) {
|
||||
"use strict";
|
||||
|
||||
const { patch } = require("web.utils");
|
||||
const GroupByMenu = require("web.GroupByMenu");
|
||||
var rpc = require("web.rpc");
|
||||
|
||||
patch(GroupByMenu, "GroupByMenuHideFieldPatch", {
|
||||
async willStart() {
|
||||
await this._super(...arguments);
|
||||
const res = await rpc.query({
|
||||
model: "access.management",
|
||||
method: "get_hidden_field",
|
||||
args: ["", this?.env?.searchModel?.config?.modelName],
|
||||
});
|
||||
debugger
|
||||
this.fields = this.fields.filter((ele) => !res.includes(ele.name));
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -2,55 +2,60 @@ odoo.define('simplify_access_management.hide_chatter', function (require) {
|
|||
"use strict";
|
||||
|
||||
var FormRenderer = require('web.FormRenderer');
|
||||
var Session = require("web.Session");
|
||||
var session = require("web.Session");
|
||||
var rpc = require('web.rpc');
|
||||
|
||||
FormRenderer.include({
|
||||
_render: function () {
|
||||
const res = this._super.apply(this, arguments);
|
||||
_render: async function () {
|
||||
const res = await this._super.apply(this, arguments);
|
||||
const self = this;
|
||||
// this._super.apply(this, arguments);
|
||||
|
||||
var hash = window.location.hash.substring(1);
|
||||
hash = JSON.parse('{"' + hash.replace(/&/g, '","').replace(/=/g,'":"') + '"}', function(key, value) { return key===""?value:decodeURIComponent(value) })
|
||||
if(!hash.cids) {
|
||||
const session = this.getSession();
|
||||
hash.cids = String(session.company_id);
|
||||
var hash = window.location.hash.replace("#", '').split("&");
|
||||
let cids;
|
||||
if(hash.findIndex(ele => ele.includes("cid")) == -1)
|
||||
cids = session.company_id;
|
||||
else {
|
||||
cids = hash.filter(ele => ele.includes("cid"))[0].split("=")[1].split(",");
|
||||
cids = cids.length > 0? parseInt(cids[0]): session.company_id;
|
||||
}
|
||||
rpc.query({
|
||||
model:'access.management',
|
||||
method: 'get_chatter_hide_details',
|
||||
args: [parseInt(hash.cids.charAt(0)), hash.model]
|
||||
}).then(function(result){
|
||||
if(result['hide_send_mail'] == false)
|
||||
{
|
||||
var btn1 = setInterval(function() {
|
||||
if ($('.o_ChatterTopbar_buttonSendMessage').length) {
|
||||
$('.o_ChatterTopbar_buttonSendMessage').remove();
|
||||
clearInterval(btn1);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
if(result['hide_log_notes'] == false)
|
||||
{
|
||||
var btn2 = setInterval(function() {
|
||||
if ($('.o_ChatterTopbar_buttonLogNote').length) {
|
||||
$('.o_ChatterTopbar_buttonLogNote').remove();
|
||||
clearInterval(btn2);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
if(result['hide_schedule_activity'] == false)
|
||||
{
|
||||
var btn3 = setInterval(function() {
|
||||
if ($('.o_ChatterTopbar_buttonScheduleActivity').length) {
|
||||
$('.o_ChatterTopbar_buttonScheduleActivity').remove();
|
||||
clearInterval(btn3);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
let model = hash.filter(ele=>ele.includes("model"))?.[0];
|
||||
model = model? model.split("=")?.[1].split(",")?.[0]: model;
|
||||
if(cids && model) {
|
||||
rpc.query({
|
||||
model:'access.management',
|
||||
method: 'get_chatter_hide_details',
|
||||
args: [cids, model]
|
||||
}).then(function(result){
|
||||
if(result['hide_send_mail'] == false)
|
||||
{
|
||||
var btn1 = setInterval(function() {
|
||||
if ($('.o_ChatterTopbar_buttonSendMessage').length) {
|
||||
$('.o_ChatterTopbar_buttonSendMessage').remove();
|
||||
clearInterval(btn1);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
if(result['hide_log_notes'] == false)
|
||||
{
|
||||
var btn2 = setInterval(function() {
|
||||
if ($('.o_ChatterTopbar_buttonLogNote').length) {
|
||||
$('.o_ChatterTopbar_buttonLogNote').remove();
|
||||
clearInterval(btn2);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
if(result['hide_schedule_activity'] == false)
|
||||
{
|
||||
var btn3 = setInterval(function() {
|
||||
if ($('.o_ChatterTopbar_buttonScheduleActivity').length) {
|
||||
$('.o_ChatterTopbar_buttonScheduleActivity').remove();
|
||||
clearInterval(btn3);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
return res;
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ odoo.define('simplify_access_management.hide_export', function (require) {
|
|||
"use strict";
|
||||
|
||||
var ListRenderer = require('web.ListRenderer');
|
||||
var session
|
||||
var session = require("web.Session");
|
||||
var rpc = require('web.rpc');
|
||||
|
||||
ListRenderer.include({
|
||||
|
|
@ -10,30 +10,34 @@ odoo.define('simplify_access_management.hide_export', function (require) {
|
|||
_render: function () {
|
||||
const res = this._super.apply(this, arguments);
|
||||
const self = this;
|
||||
// this._super.apply(this, arguments);
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
var hash = window.location.hash.substring(1);
|
||||
hash = JSON.parse('{"' + hash.replace(/&/g, '","').replace(/=/g,'":"') + '"}', function(key, value) { return key===""?value:decodeURIComponent(value) })
|
||||
if(!hash.cids) {
|
||||
const session = this.getSession();
|
||||
hash.cids = String(session.company_id);
|
||||
var hash = window.location.hash.replace("#", '').split("&");
|
||||
let cids;
|
||||
if(hash.findIndex(ele => ele.includes("cid")) == -1)
|
||||
cids = session.company_id;
|
||||
else {
|
||||
cids = hash.filter(ele => ele.includes("cid"))[0].split("=")[1].split(",");
|
||||
cids = cids.length > 0? parseInt(cids[0]): session.company_id;
|
||||
}
|
||||
let model = hash.filter(ele=>ele.includes("model"))?.[0];
|
||||
model = model? model.split("=")?.[1].split(",")?.[0]: model;
|
||||
if(cids && model) {
|
||||
rpc.query({
|
||||
model:'access.management',
|
||||
method: 'is_export_hide',
|
||||
args: [cids, model]
|
||||
}).then(function(result){
|
||||
if(result) {
|
||||
var btn1 = setInterval(function() {
|
||||
if ($('.o_list_export_xlsx').length) {
|
||||
$('.o_list_export_xlsx').remove();
|
||||
clearInterval(btn1);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
}
|
||||
rpc.query({
|
||||
model:'access.management',
|
||||
method: 'is_export_hide',
|
||||
args: [parseInt(hash.cids.charAt(0)), hash.model]
|
||||
}).then(function(result){
|
||||
debugger
|
||||
if(result) {
|
||||
debugger
|
||||
var btn1 = setInterval(function() {
|
||||
if ($('.o_list_export_xlsx').length) {
|
||||
$('.o_list_export_xlsx').remove();
|
||||
clearInterval(btn1);
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
return res;
|
||||
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
odoo.define(
|
||||
"simpily_access_management.pivot_renderer_patch",
|
||||
function (require) {
|
||||
"use strict";
|
||||
|
||||
const { patch } = require("web.utils");
|
||||
const PivotRenderer = require("web.PivotRenderer");
|
||||
var rpc = require("web.rpc");
|
||||
|
||||
patch(PivotRenderer, "PivotRendererHideFieldPatch", {
|
||||
async _updateTooltip() {
|
||||
await this._super(...arguments);
|
||||
const res = await rpc.query({
|
||||
model: "access.management",
|
||||
method: "get_hidden_field",
|
||||
args: ["", this?.props?.modelName],
|
||||
});
|
||||
this.props.selectionGroupBys = this.props.selectionGroupBys.filter(
|
||||
(ele) => !res.includes(ele.name)
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
@ -49,7 +49,6 @@ odoo.define("advanced_web_domain_widget.DomainSelector", function (require) {
|
|||
if (!this.readonly) {
|
||||
// Set list of operators according to field type
|
||||
this.displayValue = this.value;
|
||||
debugger
|
||||
this.operators = this._getOperatorsFromType(selectedField.type, selectedField.name);
|
||||
if (_.contains(["child_of", "parent_of", "like", "not like", "=like", "=ilike"], this.operator)) {
|
||||
// In case user entered manually or from demo data
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
<record id="access_management_form_view_ah" model="ir.ui.view">
|
||||
<field name="name">access_management_form_view_ah</field>
|
||||
<field name="groups_id" eval="[(4, ref('group_access_management_spt'))]"/>
|
||||
<field name="groups_id" eval="[(4, ref('group_access_management_bits'))]"/>
|
||||
<field name="model">access.management</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
<group>
|
||||
<field name="name" default_focus="1" required='1'/>
|
||||
<field name="readonly"/>
|
||||
<field name="is_apply_on_without_company"/>
|
||||
<field name="company_ids" options="{'no_create': True}" widget="many2many_tags"
|
||||
groups="base.group_multi_company"/>
|
||||
<field name="self_model_ids" widget="many2many_tags" invisible="1"/>
|
||||
|
|
@ -130,15 +131,17 @@
|
|||
<!-- <field name="model_id" options="{'no_create': True}" domain="[('id','not in',parent.self_model_ids),('abstract','=',False)]" /> -->
|
||||
<field name="model_id" context="{'is_access_rights': True}"
|
||||
options="{'no_open': True, 'no_create': True, 'no_create_edit': True}"
|
||||
required='1' domain="[('id','not in',parent.self_model_ids)]"/>
|
||||
required='1' domain="[('id','not in',parent.self_model_ids)]"
|
||||
width='10'/>
|
||||
<field name="field_id" context="{'is_access_rights': True}"
|
||||
options="{'no_open': True, 'no_create': True, 'no_create_edit': True}"
|
||||
widget='many2many_tags' domain="[('model_id','=',model_id)]"/>
|
||||
<field name="invisible" width='1'/>
|
||||
<field name="readonly" width='1'
|
||||
widget='many2many_tags' domain="[('model_id','=',model_id)]"
|
||||
width='10'/>
|
||||
<field name="invisible" width='10'/>
|
||||
<field name="readonly" width='10'
|
||||
attrs="{'column_invisible' : [('parent.readonly','=',True)]}"/>
|
||||
<field name="required" width='1'/>
|
||||
<field name="external_link" width='1'/>
|
||||
<field name="required" width='10'/>
|
||||
<field name="external_link" width='10'/>
|
||||
</tree>
|
||||
</field>
|
||||
<p role="alert"
|
||||
|
|
@ -189,12 +192,12 @@
|
|||
</sheet>
|
||||
</form>
|
||||
<tree>
|
||||
<field name="model_id"/>
|
||||
<field name="domain"/>
|
||||
<field name="read_right"/>
|
||||
<field name="create_right"/>
|
||||
<field name="write_right"/>
|
||||
<field name="delete_right"/>
|
||||
<field name="model_id" width='10'/>
|
||||
<field name="domain" width='10'/>
|
||||
<field name="read_right" width='10'/>
|
||||
<field name="create_right" width='10'/>
|
||||
<field name="write_right" width='10'/>
|
||||
<field name="delete_right" width='10'/>
|
||||
</tree>
|
||||
</field>
|
||||
<p role="alert"
|
||||
|
|
@ -366,7 +369,7 @@
|
|||
|
||||
<record id="access_management_tree_view_ah" model="ir.ui.view">
|
||||
<field name="name">access_management_tree_view_ah</field>
|
||||
<field name="groups_id" eval="[(4, ref('group_access_management_spt'))]"/>
|
||||
<field name="groups_id" eval="[(4, ref('group_access_management_bits'))]"/>
|
||||
<field name="model">access.management</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-muted="(not active)">
|
||||
|
|
@ -389,8 +392,8 @@
|
|||
</record>
|
||||
|
||||
<menuitem id="main_menu_simplify_access_management" name="Access Studio" action="action_access_management_ah"
|
||||
groups="group_access_management_spt"
|
||||
/>
|
||||
groups="group_access_management_bits"
|
||||
web_icon="simplify_access_management,static/description/icon.png"/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -5,12 +5,15 @@
|
|||
<template id="assets_backend" name="simplify_access_management_view assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/action_items.js"></script>
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/widget/DomainSelector.js"></script>
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/widget/ModelRecordSelector.js"></script>
|
||||
<!-- <script type="text/javascript" src="/simplify_access_management/static/src/js/widget/DomainSelector.js"></script>
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/widget/ModelRecordSelector.js"></script> -->
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/data_manager.js"></script>
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/action_manager.js"></script>
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/hide_chatter.js"></script>
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/hide_export.js"></script>
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/pivot_renderer_patch.js"></script>
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/custom_filter_item.js"></script>
|
||||
<script type="text/javascript" src="/simplify_access_management/static/src/js/groupby_menu.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
<field name="inherit_id" ref="base.view_users_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//notebook" position="inside">
|
||||
<page string='Access Management' groups="simplify_access_management.group_access_management_spt">
|
||||
<page string='Access Management' groups="simplify_access_management.group_access_management_bits">
|
||||
<field name='access_management_ids'>
|
||||
<tree>
|
||||
<field name="name" />
|
||||
|
|
|
|||