update modules

This commit is contained in:
eslamabady 2024-08-12 15:09:29 +03:00
parent fc93591f59
commit 840be35b2f
62 changed files with 54400 additions and 828 deletions

0
odex25_base/advanced_web_domain_widget/__init__.py Normal file → Executable file
View File

6
odex25_base/advanced_web_domain_widget/__manifest__.py Normal file → Executable file
View File

@ -10,14 +10,12 @@
################################################################################# #################################################################################
{ {
'name': 'Advanced Web Domain Widget', '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.', 'summary': 'Set all relational fields domain by selecting its records unsing `in, not in` operator.',
'sequence': 1, 'sequence': 1,
'author': 'Terabits Technolab', 'author': 'Terabits Technolab',
'category': 'Odex25-base',
'license': 'OPL-1', 'license': 'OPL-1',
'website': 'https://www.terabits.xyz', 'website': 'https://www.terabits.xyz/apps/14.0/advanced_web_domain_widget',
'description':""" 'description':"""
""", """,

View File

View File

@ -1 +1,2 @@
from . import domain_prepare from . import domain_prepare
from . import models

View File

12
odex25_base/advanced_web_domain_widget/models/models.py Normal file → Executable file
View File

@ -5,11 +5,9 @@ class BaseModel(models.AbstractModel):
_inherit = 'base' _inherit = 'base'
@api.model @api.model
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, **read_kwargs): def get_widget_name(self, domain=None, fields=None, offset=0, limit=None, order=None, **read_kwargs):
res = super().search_read(domain, fields, offset, limit, order, **read_kwargs) return self.sudo().search_read(domain, ['id', 'display_name'], offset, limit, order)
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
@api.model
def get_widget_count(self, args):
return self.sudo().search_count(args)

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 KiB

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 199 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -26,238 +26,140 @@
<div id="module-description"> <div id="module-description">
<!-- Keep From Here --> <!-- 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="container">
<div class="oe_styling_v8"> <div class="oe_styling_v8">
<!-- Nav START --> <!-- elearning post starts -->
<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>
<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"> <div class="position-relative row justify-content-center align-items-center"
<ul class="nav navbar-nav ml-auto text-right"> style="padding: 20px 10px 40px 10px;">
<div class="col-12 my-3 px-5">
</ul> <div class="header-img">
<img src="img/screens/domain_header_img.png" class="img img-fluid w-100"
style="width: 100% !important;" />
</div> </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;">
<div class="ml-auto text-right" id="navbarNav"> Advanced web domian widget
<ul class="nav navbar-nav ml-auto text-right"> </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."
<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> </h3>
<p
<p class="mb16 text-black-dark px-3" style="font-family: 'Inter', sans-serif; font-size: 18px; font-weight: 500;line-height: 27px; color: #000000; margin-top: 20px;">
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 <br/>
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 <br/>
domain using any relational fields. So, user confused when model has multiple record's and he/she does't remembered. So, we have simplified that by showing models record to <br/>
id and he/she does't remembered. So, we have simplified that by showing models the user. so, he/she can select by finding record and select it. our module will autometic <br/>
record to the user. so, he/she can select by finding record and select it. our module adds ids of selected records in domain. To select related model's record and create <br/>
will autometic adds ids of selected records in domain. To select related model's record domain, we allowed additional two domain operators ('in', 'not in').
and create domain, we allowed additional
two domain operators ('in', 'not in').
</p> </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>
</section> -->
</div>
</div>
</div> </div>
</div>
</div>
</div>
</section>
<!-- elearning post end -->
<!-- features highlight --> <!-- features highlight -->
<section class="oe_container pb-5">
<div class="mt64 mb64"> <section class="domain_features_02">
<h2 style="color:#660066; font-family:'Montserrat'; text-align:center; margin:25px auto; text-transform:uppercase" <div class="position-relative w-100" style="display: inline-grid;">
class="oe_slogan"> <img src="img/screens/domain_bg_img_02.png" class="img-responsive w-100 h-100 img img-fluid position-absolute left_0"/>
<b>Highlights</b>
<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> </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>
<div class="col-md-9" style="padding-left:0; float:left; width:70%">
<h3 class="mt16 mb0" <div class="d-flex justify-content-around align-items-center mt-4">
style="font-family:Roboto; font-weight:500; font-size:20px">Select any <div style="background-color: #F1F7FF; padding: 20px 40px 20px 25px; border-radius: 8px; width: 45% !important; height: 100% !important;" class="shadow-sm">
models records</h3> <h6 style="font-family: 'Inter', sans-serif; font-size: 25px; font-weight: 600;line-height: 36px;color: #151765;">
<p class=" mt8" style="font-family:Roboto"> Select any models records
Easy to create domain of relational fields by selecting any models record in </h6>
domain. We provide additional operators ('in' and 'not in') to create <div class="mt-3">
relational fields domain. <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> </p>
</div> </div>
</div> </div>
</div>
<div class="col-md-6 col-sm-12 mt32"> <div style="background-color: #F1F7FF; padding: 32px 40px 32px 25px; border-radius: 8px; width: 45% !important; height: 100% !important;" class="shadow-sm">
<div class="container shadow" <h6 style="font-family: 'Inter', sans-serif; font-size: 25px; font-weight: 600;line-height: 36px;color: #151765;">
style="border-radius:10px; padding:10px 0px;height: 100%;"> Autometic id add in domain
<div class="col-md-3" style="float:left"> </h6>
<img class="img img-responsive" src="img/feature7.png"> <div class="mt-3">
</div> <p style="font-family: 'Inter', sans-serif; font-size: 17px; font-weight: 500;line-height: 24px;color: #151765;">
<div class="col-md-9" style="padding-left:0; float:left; width:70%"> When user select models records from popup, <br/>
<h3 class="mt16 mb0" there will generate tags of record's names and <br/>
style="font-family:Roboto; font-weight:500; font-size:20px">Autometic id add add records id in domain.
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> </p>
</div> </div>
</div> </div>
</div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- features highlight -->
<!-- tabs --> <!-- tabs -->
<section class="info-tabs"> <section class="info-tabs mt-5">
<div> <div>
<div class="tabs"> <div class="tabs">
<div class="justify-content-center d-flex"> <div class="justify-content-center d-flex">
<!-- Nav pills --> <!-- Nav pills -->
<ul class="nav my-3 o_tab_nav justify-content-center" <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">
style="border-radius:6px 6px; background-color:transparent"> <li class="nav-item">
<li class="nav-item mx-1" style="border-radius:6px 0 0 6px"> <a class="show "
<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" aria-expanded="true" style="padding: 11px 12px 8px 12px !important;">
id="v-guide-tab" data-bs-toggle="pill" aria-controls="v-guide" href="#pills-guide" <span class="m-0" style="font-weight: 600; font-family: 'Inter', sans-serif; color: #1c29da;font-size: 19px; line-height: 23px;">USERGUIDE</span>
style="border-radius:6px; opacity:1; padding:16px">USERGUIDE</a> </a>
</li> </li>
<li class="nav-item mx-1"> <li class="nav-item mx-1">
<a class="nav-link px-md-4 list-group-item-default list-group-item-action active" <a class="show active"
id="v-ss-tab" data-bs-toggle="pill" aria-controls="v-ss" href="#pills-screenshot" 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;">
style="border-radius:6px; opacity:1; padding:16px">SCREENSHOTS</a> <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>
<li class="nav-item mx-1"> <li class="nav-item mx-1">
<a class="nav-link px-md-4 list-group-item-default list-group-item-action" <a class="show"
id="v-faqs-tab" data-bs-toggle="pill" aria-controls="v-faqs" href="#pills-faqs" 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;">
style="border-radius:6px; opacity:1; padding:16px">FAQs</a> <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>
<li class="nav-item mx-1"> <li class="nav-item ">
<a class="nav-link px-md-4 list-group-item-default list-group-item-action" <a class="show"
id="v-release-tab" data-bs-toggle="pill" aria-controls="v-release" href="#pills-release" 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;">
style="border-radius:6px; opacity:1; padding:16px">RELEASES</a> <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> </li>
</ul> </ul>
</div> </div>
<div class="tab-content shadow" style="border-radius: 10px;padding: 10px 0px;" <div class="tab-content" style="border-radius: 10px;"
id="pills-tabContent"> id="pills-tabContent">
<!-- user-guide --> <!-- user-guide -->
<div class="tab-pane fade" id="pills-guide" role="tabpanel" aria-labelledby="v-guide-tab" <div class="tab-pane fade py-3 shadow" id="pills-guide" role="tabpanel"
aria-labelledby="pills-guide-tab"> aria-labelledby="v-guide-tab" aria-labelledby="pills-guide-tab">
<div class="screenshot-description" style="margin: 1% 3%;"> <div class="screenshot-description" style="margin: 1% 3%;">
<div style="border-radius: 10px;background-color: #f9f9f9;text-align:center;"> <div style="border-radius: 10px;background-color: #f9f9f9;text-align:center;">
@ -287,68 +189,127 @@
</div> </div>
<!-- screenshots tab --> <!-- screenshots tab -->
<div class="tab-pane fade text-center active show" id="pills-screenshot" role="tabpanel" aria-labelledby="v-ss-tab" <div class="tab-pane fade text-center active show" id="pills-screenshot" role="tabpanel"
aria-labelledby="pills-screenshot-tab"> 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;"> <!-- 01 -->
<h4 style='font-weight: 600;padding: 20px;'>Here is odoo's 'domain' widget
for domain creation.</h4> <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>
</div> <div class="content"
<div class="screenshot" style="text-align: center;"> style="margin-left: 15px !important;">
<img class="img img-fluid oe_screenshot" style="width: 90%;margin: 2%;" <p
src="img/screens/ss1.png" alt="Odoo domain widget" /> style="font-family: 'Inter', sans-serif; font-size: 20px; font-weight: 500;line-height: 26px;color: #151765;">
</div> Here is odoo's 'domain' widget for domain creation.
<div class="screenshot-description" style="margin: 1% 3%;"> </p>
<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> </div>
</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>
</section>
</div>
<!-- faq tab --> <!-- 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"> aria-labelledby="pills-faqs-tab">
<div class="s_faq mt32 mb32" <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" <div class="panel-group" id="accordion" role="tablist"
aria-multiselectable="true"> aria-multiselectable="true">
@ -360,9 +321,9 @@
style="border:1px solid transparent !important"> style="border:1px solid transparent !important">
<h4 class="panel-title" style="margin: 0;"> <h4 class="panel-title" style="margin: 0;">
<a class="collapsed" <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"
data-bs-toggle="collapse" href="#collapse1" aria-expanded="false"> 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;">
Why should I use this app? Why should I use this app?
</span> </span>
</a> </a>
@ -373,7 +334,8 @@
class="panel-collapse collapse"> class="panel-collapse collapse">
<div> <div>
<p class="mb0" <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 This module provides domains with an additional feature
to select any models record while using any relational to select any models record while using any relational
field and create a domain after selecting it. for that, field and create a domain after selecting it. for that,
@ -395,10 +357,9 @@
style="border:1px solid transparent !important"> style="border:1px solid transparent !important">
<h4 class="panel-title" style="margin: 0;"> <h4 class="panel-title" style="margin: 0;">
<a class="collapsed" <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" data-bs-toggle="collapse" href="#collapse2"
aria-expanded="false"> 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 ? What is user's main benifit ?
</span> </span>
</a> </a>
@ -409,7 +370,8 @@
class="panel-collapse collapse"> class="panel-collapse collapse">
<div> <div>
<p class="mb0" <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 User's main benifit is that, he/she does not have to
remember models record id while he/she have to create remember models record id while he/she have to create
domain based on relational fields, because we direct domain based on relational fields, because we direct
@ -429,10 +391,9 @@
style="border:1px solid transparent !important"> style="border:1px solid transparent !important">
<h4 class="panel-title" style="margin: 0;"> <h4 class="panel-title" style="margin: 0;">
<a class="collapsed" <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" data-bs-toggle="collapse" href="#collapse3"
aria-expanded="false"> 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 Need some customization in this app, whom can I
contact? contact?
</span> </span>
@ -444,7 +405,8 @@
class="panel-collapse collapse"> class="panel-collapse collapse">
<div> <div>
<p class="mb0" <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 Please drop an email at info@terabits.xyz or raise a
ticket through the Odoo store itself. ticket through the Odoo store itself.
@ -461,10 +423,9 @@
style="border:1px solid transparent !important"> style="border:1px solid transparent !important">
<h4 class="panel-title" style="margin: 0;"> <h4 class="panel-title" style="margin: 0;">
<a class="collapsed" <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" data-bs-toggle="collapse" href="#collapse4"
aria-expanded="false"> 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? Do you provide any free support?
</span> </span>
</a> </a>
@ -475,7 +436,8 @@
class="panel-collapse collapse"> class="panel-collapse collapse">
<div> <div>
<p class="mb0" <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 Yes, I do provide free support for 90 days for any
queries or any bug/issue fixing. queries or any bug/issue fixing.
@ -492,10 +454,9 @@
style="border:1px solid transparent !important"> style="border:1px solid transparent !important">
<h4 class="panel-title" style="margin: 0;"> <h4 class="panel-title" style="margin: 0;">
<a class="collapsed" <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" data-bs-toggle="collapse" href="#collapse5"
aria-expanded="false"> 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? What is Support Policy of this Module?
</span> </span>
</a> </a>
@ -506,7 +467,8 @@
class="panel-collapse collapse"> class="panel-collapse collapse">
<div> <div>
<p class="mb0" <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 In case of if any bug raised in the listed features of
this module, I am committed to providing support free of this module, I am committed to providing support free of
cost. You will need to provide me server ssh access or cost. You will need to provide me server ssh access or
@ -522,42 +484,34 @@
</div> </div>
<!-- release tab --> <!-- release tab -->
<div class="tab-pane px-0 px-sm-5 fade" id="pills-release" aria-labelledby="v-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">
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="row my-2 p-4 position-relative">
<div class="col-12 p-4 shadow-sm bg-white"> <div class="col-12 px-0 bg-white">
<h2>Changelog(s)</h2> <h2 style="font-family: 'Inter', sans-serif;font-size: 35px;color: #000;font-weight: 600;">Changelog(s)</h2>
<hr class="mb-4 mt-0"> <hr class="mb-4 mt-0">
<!-- v14.0.1.0.2 --> <!-- v14.0.1.0.2 -->
<h2 class="h4 pb-2"> <h2 class="h4 pb-2">
<span style="color:#00B5DB" class="pr-2">v14.0.1.0.2</span>-<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>
class="pl-2">December <span>-</span>
10, 2022</span> <span class="ps-2" style="font-family: 'Inter', sans-serif;font-size: 23px;font-weight: 500;color: #000;">December 10, 2022</span>
</h2> </h2>
<ul class="list-unstyled"> <p style="font-family: 'Inter', sans-serif;color: #000;font-size: 18px; font-weight: 500; line-height: 28px;">
<li class="d-flex align-items-start mb-3">
Minor bug fix. Minor bug fix.
</li> </p>
</ul>
<!-- v14.0.0.0.0 --> <!-- v14.0.0.0.0 -->
<h2 class="h4 pb-2"> <h2 class="h4 pb-2">
<span style="color:#00B5DB" class="pr-2">v14.0.0.0.0</span>-<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>
class="pl-2">November <span>-</span>
23, 2022</span> <span class="ps-2" style="font-family: 'Inter', sans-serif;font-size: 23px;font-weight: 500;color: #000;">November 23, 2022</span>
</h2> </h2>
<ul class="list-unstyled"> <p style="font-family: 'Inter', sans-serif;color: #000;font-size: 18px; font-weight: 500; line-height: 28px;">
<li class="d-flex align-items-start mb-3">
Initial release for v14 Initial release for v14
</li> </p>
</ul>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -12,7 +12,7 @@ var config = require('web.config');
var core = require('web.core'); var core = require('web.core');
var Domain = require('web.Domain'); var Domain = require('web.Domain');
var DomainSelector = require('advanced_web_domain_widget.TerabitsDomainSelector'); 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'); var view_dialogs = require('web.view_dialogs');
require("web.zoomodoo"); 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 { return {
TerabitsFieldDomain: TerabitsFieldDomain, TerabitsFieldDomain: TerabitsFieldDomain,
TerabitsFieldDomain2: TerabitsFieldDomain2
}; };
}); });

View File

@ -239,7 +239,7 @@ BasicModel.include({
}); });
self._rpc({ self._rpc({
model: domainModel, model: domainModel,
method: 'search_count', method: 'get_widget_count',
args: [newDomain], args: [newDomain],
context: context context: context
}) })

View File

@ -6,6 +6,7 @@ odoo.define('advanced_web_domain_widget._terabits_field_registry', function (req
// Basic fields // Basic fields
fieldRegistry.add('terabits_domain', basic_fields.TerabitsFieldDomain); fieldRegistry.add('terabits_domain', basic_fields.TerabitsFieldDomain);
fieldRegistry.add('terabits_field_domain', basic_fields.TerabitsFieldDomain2);
}); });

View File

@ -5,7 +5,7 @@ odoo.define("advanced_web_domain_widget.TerabitsDomainSelector", function (requi
var datepicker = require("web.datepicker"); var datepicker = require("web.datepicker");
var Domain = require("web.Domain"); var Domain = require("web.Domain");
var field_utils = require("web.field_utils"); 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 ModelRecordSelector = require("advanced_web_domain_widget.ModelRecordSelector");
var Widget = require("web.Widget"); var Widget = require("web.Widget");
var _t = core._t; 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 * The TerabitsDomainSelector widget can be used to build prefix char domain. It is the
* TerabitsDomainTree specialization to use to have a fully working widget. * 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 * TerabitsDomainNode which handles a domain which cannot be split in another
* subdomains, i.e. composed of a field chain, an operator and a value. * 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 : []; const ids = (this.value) ? this.value : [];
wDefs.push(this._rpc({ wDefs.push(this._rpc({
model: model_rel, model: model_rel,
method: 'search_read', method: 'get_widget_name',
kwargs: { kwargs: {
domain: [['id', 'in', ids]], domain: [['id', 'in', ids]],
fields: ['id', 'display_name'], fields: ['id', 'display_name'],
}, },
}).then(function (data) { }).then(function (data) {
self.value = []; 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) { _.each(data, function (rec, index) {
self.tagsvalues.push([rec.id, rec.display_name]); self.tagsvalues.push([rec.id, rec.display_name]);
// to remove invalid id which is not in records // 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 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 { return {
TerabitsDomainSelector:TerabitsDomainSelector, TerabitsDomainSelector:TerabitsDomainSelector,
TerabitsDomainLeaf:TerabitsDomainLeaf TerabitsDomainSelector2:TerabitsDomainSelector2,
TerabitsDomainLeaf:TerabitsDomainLeaf,
TerabitsDomainLeaf2:TerabitsDomainLeaf2,
}; };
}); });

View File

@ -10,7 +10,7 @@ odoo.define("advanced_web_domain_widget.DomainSelectorDialog", function (require
/** /**
* @class DomainSelectorDialog * @class DomainSelectorDialog
*/ */
return Dialog.extend({ var DomainSelectorDialog = Dialog.extend({
init: function (parent, model, domain, options) { init: function (parent, model, domain, options) {
this.model = model; this.model = model;
this.options = _.extend({ 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
}
}); });

View 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 * Allows to transform a mapping field name -> field info in an array of the

View File

@ -104,7 +104,7 @@ odoo.define("advanced_web_domain_widget.ModelRecordSelector", function (require)
; ;
var def = this._rpc({ var def = this._rpc({
model: model, model: model,
method: 'search_read', method: 'get_widget_name',
kwargs: { kwargs: {
domain: [], domain: [],
fields: ['id', 'display_name'], fields: ['id', 'display_name'],
@ -113,6 +113,12 @@ odoo.define("advanced_web_domain_widget.ModelRecordSelector", function (require)
if (data) { if (data) {
this.records = 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'){ // if(model == 'res.users'){
// this.records.push({'id':0,'display_name':'Environment User'}) // this.records.push({'id':0,'display_name':'Environment User'})
// } // }

View File

View File

@ -16,6 +16,22 @@
</div> </div>
<div t-else="">Select a model to add a filter.</div> <div t-else="">Select a model to add a filter.</div>
</t> </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"> <t t-name="TerabitsDomainNode.ControlPanel">
<div t-if="!widget.readonly &amp;&amp; !widget.noControlPanel" class="o_domain_node_control_panel" role="toolbar" aria-label="Domain node"> <div t-if="!widget.readonly &amp;&amp; !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> <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> </li>
</t> </t>
</ul> </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) &amp;&amp; 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"> <ul t-name="TerabitsModelRecordSelector.page" class="o_record_selector_page">
<t t-foreach="lines" t-as="line"> <t t-foreach="lines" t-as="line">
<!-- <t t-set="relationToFollow" t-value="followRelations(line) &amp;&amp; line.relation"/> --> <!-- <t t-set="relationToFollow" t-value="followRelations(line) &amp;&amp; line.relation"/> -->

View File

View File

@ -14,5 +14,4 @@ def post_install_action_dup_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {}) env = api.Environment(cr, SUPERUSER_ID, {})
action_data_obj = env['action.data'] action_data_obj = env['action.data']
for action in env['ir.actions.actions'].search([]): for action in env['ir.actions.actions'].search([]):
print(action.name,"===================")
action_data_obj.create({'name':action.name,'action_id':action.id}) action_data_obj.create({'name':action.name,'action_id':action.id})

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################# #################################################################################
# Author : Terabits Technolab (<www.terabits.xyz>) # Author : Terabits Technolab (<www.terabits.xyz>)
# Copyright(c): 2021-23 # Copyright(c): 2023-24
# All Rights Reserved. # All Rights Reserved.
# #
# This module is copyright property of the author mentioned above. # This module is copyright property of the author mentioned above.
@ -11,12 +11,12 @@
{ {
'name': 'Simplify Access Management', 'name': 'Simplify Access Management',
'version': '14.0.11.4.5', 'version': '14.0.12.8.5',
'sequence': 5, 'sequence': 5,
'author': 'Terabits Technolab', 'author': 'Terabits Technolab',
'license': 'OPL-1', 'license': 'OPL-1',
'category': 'Odex25-base', 'category': 'Services',
'website': 'https://www.terabits.xyz/r/SNS', '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. '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, All in one access management App,
Easier then Record rules setup, Easier then Record rules setup,
@ -160,11 +160,11 @@
""", """,
"images": ["static/description/banner.gif"], "images": ["static/description/banner.gif"],
"price": "370.99", "price": "280.99",
"currency": "USD", "currency": "USD",
'data': [ 'data': [
'security/ir.model.access.csv',
'security/res_groups.xml', 'security/res_groups.xml',
'security/ir.model.access.csv',
'data/view_data.xml', 'data/view_data.xml',
'views/access_management_view.xml', 'views/access_management_view.xml',
'views/assets.xml', 'views/assets.xml',

View File

@ -1,3 +1,3 @@
# from . import main # from . import main
from . import action from . import action
from . import export

View File

@ -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

View File

@ -10,14 +10,15 @@ class access_domain_ah(models.Model):
'ir.model', string='Model', index=True, required=True, ondelete='cascade') '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) model_name = fields.Char(string='Model Name', related='model_id.model', readonly=True, store=True)
apply_domain = fields.Boolean('Apply Filter') 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') access_management_id = fields.Many2one('access.management','Access Management')
read_right = fields.Boolean('Read',default=True) 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') create_right = fields.Boolean('Create', help="The set 'Create' access of the selected model for the specified users")
write_right = fields.Boolean('Write') write_right = fields.Boolean('Write', help="The set 'Write' access of the selected model for the specified users")
delete_right = fields.Boolean('Delete') delete_right = fields.Boolean('Delete', help="The set 'Delete' access of the selected model for the specified users")
@api.onchange('apply_domain') @api.onchange('apply_domain')
def _check_domain(self): def _check_domain(self):

View File

@ -14,7 +14,8 @@ class access_management(models.Model):
active = fields.Boolean('Active', default=True) 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_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) 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) remove_action_ids = fields.One2many('remove.action', 'access_management_id', 'Remove Action', copy=True)
@ -32,16 +33,21 @@ class access_management(models.Model):
# Chatter # Chatter
hide_chatter_ids = fields.One2many('hide.chatter', 'access_management_id', 'Hide Chatter', copy=True) hide_chatter_ids = fields.One2many('hide.chatter', 'access_management_id', 'Hide Chatter', copy=True)
hide_chatter = fields.Boolean('Hide Chatter') hide_chatter = fields.Boolean('Hide Chatter',
hide_send_mail = fields.Boolean('Hide Send Message') help="The Chatter will be hidden in all model from the specified users.")
hide_log_notes = fields.Boolean('Hide Log Notes') hide_send_mail = fields.Boolean('Hide Send Message',
hide_schedule_activity = fields.Boolean('Hide Schedule Activity') 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_export = fields.Boolean(help="The Export button will be hidden in all model from the specified users.")
hide_import = fields.Boolean() hide_import = fields.Boolean(help="The Import button will be hidden in all model from the specified users.")
disable_login = fields.Boolean('Disable Login') 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_ids = fields.Many2many('res.company', 'access_management_comapnay_rel', 'access_management_id',
'company_id', 'Companies', required=True, default=lambda self: self.env.company) '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', hide_filters_groups_ids = fields.One2many('hide.filters.groups', 'access_management_id', 'Hide Filters/Group By',
copy=True) copy=True)
is_apply_on_without_company = fields.Boolean()
def _count_total_rules(self): def _count_total_rules(self):
for rec in self: for rec in self:
rule = 0 rule = 0
@ -110,7 +117,7 @@ class access_management(models.Model):
return res return res
def get_remove_options(self, model): 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), ('active', '=', True),
('user_ids', 'in', self.env.user.id), ('user_ids', 'in', self.env.user.id),
('hide_export', '=', True)], limit=1).id ('hide_export', '=', True)], limit=1).id
@ -158,7 +165,7 @@ class access_management(models.Model):
hide_schedule_activity = False hide_schedule_activity = False
if model and hide_send_mail or hide_log_notes or hide_schedule_activity: 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.active', '=', True),
('access_management_id.user_ids', 'in', user_id), ('access_management_id.user_ids', 'in', user_id),
('model_id.model', '=', model)]) ('model_id.model', '=', model)])
@ -192,9 +199,23 @@ class access_management(models.Model):
break break
if not hide_export and model: 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), ('model_id.model', '=', model),
('restrict_export', '=', True)]): ('restrict_export', '=', True)]):
hide_export = True hide_export = True
return hide_export 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 []

View File

@ -9,7 +9,9 @@ class hide_chatter(models.Model):
access_management_id = fields.Many2one('access.management', 'Access Management') access_management_id = fields.Many2one('access.management', 'Access Management')
model_id = fields.Many2one('ir.model', 'Model') model_id = fields.Many2one('ir.model', 'Model')
hide_chatter = fields.Boolean('Chatter') hide_chatter = fields.Boolean('Chatter'
hide_send_mail = fields.Boolean('Send Message') ,help="The Chatter will be hidden in selected model from the specified users.")
hide_log_notes = fields.Boolean('Log Notes') hide_send_mail = fields.Boolean('Send Message'
hide_schedule_activity = fields.Boolean('Schedule Activity') ,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.")

View File

@ -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') field_id = fields.Many2many('ir.model.fields', 'hide_field_ir_model_fields_rel', 'hide_field_id', 'ir_field_id', 'Field')
invisible = fields.Boolean('Invisible') invisible = fields.Boolean('Invisible', help="Selected Field will be hidden in selected model from the defined users.")
readonly = fields.Boolean('Read-Only') readonly = fields.Boolean('Read-Only', help="Selected Field will be Read only in selected model from the defined users.")
required = fields.Boolean('Required') 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') external_link = fields.Boolean('Remove External Link',help="External Link will be hidden for relational fields in selected model from the defined users.")

View File

@ -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) 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', 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', 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') access_management_id = fields.Many2one('access.management', 'Access Management')

View File

@ -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) 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')]") 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')]") help="The Buttons 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')]") 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') access_management_id = fields.Many2one('access.management','Access Management')

View File

@ -1,14 +1,15 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging import logging
from odoo.http import request from odoo.http import request
from odoo import api, fields, models, tools, _ from odoo import api, fields, models, tools,_
from odoo.exceptions import Warning, ValidationError, AccessError from odoo.exceptions import Warning, ValidationError,AccessError
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class ir_model_access(models.Model): class ir_model_access(models.Model):
_inherit = 'ir.model.access' _inherit = 'ir.model.access'
# The context parameter is useful when the method translates error messages. # 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 # 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` # 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) self.flush(self._fields)
""" """
This part is writen to by pass base access rule and apply dynamic rule of access management rule, 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. In case of any record found in access management.
@ -41,7 +43,7 @@ class ir_model_access(models.Model):
if model: if model:
self._cr.execute("SELECT id FROM ir_model WHERE model='" + model + "'") self._cr.execute("SELECT id FROM ir_model WHERE model='" + model + "'")
model_numeric_id = self._cr.fetchone()[0] 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: try:
self._cr.execute(""" self._cr.execute("""
SELECT dm.id SELECT dm.id
@ -53,13 +55,14 @@ class ir_model_access(models.Model):
IN (SELECT amusr.access_management_id IN (SELECT amusr.access_management_id
FROM access_management_users_rel_ah as amusr FROM access_management_users_rel_ah as amusr
WHERE amusr.user_id=%s)) WHERE amusr.user_id=%s))
""", [model_numeric_id, self.env.user.id]) """,[model_numeric_id, self.env.user.id])
except: except:
pass 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: if access_domain_ah_ids:
return True return True
# We check if a specific rule exists # We check if a specific rule exists
self._cr.execute("""SELECT MAX(CASE WHEN perm_{mode} THEN 1 ELSE 0 END) self._cr.execute("""SELECT MAX(CASE WHEN perm_{mode} THEN 1 ELSE 0 END)
FROM ir_model_access a FROM ir_model_access a
@ -102,7 +105,11 @@ class ir_model_access(models.Model):
resolution_info = _("Contact your administrator to request access if necessary.") 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) _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, operation_error=operation_error,
group_info=group_info, group_info=group_info,
resolution_info=resolution_info) resolution_info=resolution_info)
@ -116,18 +123,15 @@ class ir_model_access(models.Model):
if data and data[0] != 'installed': if data and data[0] != 'installed':
read_value = False read_value = False
if self.env.user.id and read_value: 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 = " + str(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"
self._cr.execute(a) self._cr.execute(a)
a = self._cr.fetchall() a = self._cr.fetchall()
if a: 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) self._cr.execute(a)
a = self._cr.fetchall() a = self._cr.fetchall()
if a: 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) self._cr.execute(a)
a = self._cr.fetchall() a = self._cr.fetchall()
if bool(a): if bool(a):
@ -136,4 +140,5 @@ class ir_model_access(models.Model):
except: except:
pass pass
return bool(r) return bool(r)

View File

@ -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'] 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 self.env.user.id and read_value and not all_data:
if model_name not in model_list: if model_name not in model_list:
# self._cr.execute("""SELECT am.id FROM access_management as am self._cr.execute("""SELECT am.id FROM access_management as am
# WHERE active='t' AND readonly = True AND am.id WHERE active='t' AND readonly = True AND am.id
# IN (SELECT au.access_management_id IN (SELECT au.access_management_id
# FROM access_management_users_rel_ah as au FROM access_management_users_rel_ah as au
# WHERE user_id = %s AND am.id WHERE user_id = %s AND am.id
# IN (SELECT ac.access_management_id IN (SELECT ac.access_management_id
# FROM access_management_comapnay_rel as ac FROM access_management_comapnay_rel as ac
# WHERE ac.company_id=%s))"""%(self.env.user.id, self.env.company.id)) 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) # a = "select access_management_id from access_management_comapnay_rel where company_id = " + str(self.env.company.id)
# self._cr.execute(a) # self._cr.execute(a)
# a = self._cr.fetchall() # a = self._cr.fetchall()
@ -85,11 +85,13 @@ class ir_rule(models.Model):
""", [model_numeric_id, self.env.user.id]) """, [model_numeric_id, self.env.user.id])
except: except:
pass 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( row[0] for row in self._cr.fetchall()).filtered(
lambda line: self.env.company in line.access_management_id.company_ids) 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) # 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: if access_domain_ah_ids:
all_company = self.env['res.company'].sudo().search([]).ids
company_domain = []
domain_list = [] domain_list = []
if model_name == 'res.partner': if model_name == 'res.partner':
# jo aya user related jetala partner 6 ana access alag thi apididha 6 error no ave atle # 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() eval_context = self._eval_context()
# only domain records # only domain records
length = len(access_domain_ah_ids.sudo()) if access_domain_ah_ids.sudo() else 0 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(): for access in access_domain_ah_ids.sudo():
dom = safe_eval(access.domain, eval_context) if access.domain else [] 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: if dom:
dom = expression.normalize_domain(dom) dom = expression.normalize_domain(dom)
for dom_tuple in dom: for dom_tuple in dom:
@ -138,6 +155,14 @@ class ir_rule(models.Model):
right_value[zero_index] = self.env.company.id right_value[zero_index] = self.env.company.id
if operator_value == 'date_filter': if operator_value == 'date_filter':
domain_list += prepare_domain_v2(dom_tuple) domain_list += prepare_domain_v2(dom_tuple)
domain_list.insert(0,'&')
domain_list+= company_domain
else:
if company_domain:
company_domain.append(dom_tuple)
domain_list.insert(0,'&')
domain_list+= company_domain
else: else:
domain_list.append(dom_tuple) domain_list.append(dom_tuple)
else: else:
@ -145,7 +170,34 @@ class ir_rule(models.Model):
if length > 1: if length > 1:
domain_list.insert(0, '|') domain_list.insert(0, '|')
length -= 1 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 domain_list:
if com_domain:
domain_list.insert(0, '|')
domain_list+=com_domain
return domain_list return domain_list
return res return res

View File

@ -13,12 +13,12 @@ class ir_ui_view(models.Model):
hide_button_obj = self.env['hide.view.nodes'] hide_button_obj = self.env['hide.view.nodes']
if name_manager.Model._name == 'res.config.settings' and node.tag == 'div' and node.get('string'): 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'): 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_info['modifiers']['invisible'] = True
node.set('invisible', '1') node.set('invisible', '1')
if node.tag == 'a': 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 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), ('model_id.model','=',name_manager.Model._name),
('access_management_id.active','=',True), ('access_management_id.active','=',True),
('access_management_id.company_ids','in',self.env.company.id), ('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: if hide_field.external_link:
options_dict = {} options_dict = {}
if 'widget' in node.attrib.keys(): 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'] del node.attrib['widget']
if 'options' in node.attrib.keys(): if 'options' in node.attrib.keys():
options_dict = ast.literal_eval(node.attrib['options']) options_dict = ast.literal_eval(node.attrib['options'])

View File

@ -15,7 +15,7 @@ class BaseModel(models.AbstractModel):
@api.model @api.model
def load_views(self, views, options=None): def load_views(self, views, options=None):
actions_and_prints = [] 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', ('access_management_id', 'in',
self.env.user.access_management_ids.ids), self.env.user.access_management_ids.ids),
('model_id.model', '=', self._name)]): ('model_id.model', '=', self._name)]):
@ -49,13 +49,13 @@ class BaseModel(models.AbstractModel):
res = super().fields_view_get(view_id, view_type, toolbar, submenu) res = super().fields_view_get(view_id, view_type, toolbar, submenu)
access_management_obj = self.env['access.management'] 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 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_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'].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': 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), ('active', '=', True),
('user_ids', 'in', self.env.user.id), ('user_ids', 'in', self.env.user.id),
('hide_chatter', '=', True)], ('hide_chatter', '=', True)],
@ -66,7 +66,7 @@ class BaseModel(models.AbstractModel):
div.getparent().remove(div) div.getparent().remove(div)
res['arch'] = etree.tostring(doc, encoding='unicode') res['arch'] = etree.tostring(doc, encoding='unicode')
else: 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.active', '=', True),
('access_management_id.user_ids', 'in', self.env.user.id), ('access_management_id.user_ids', 'in', self.env.user.id),
('model_id.model', '=', self._name), ('model_id.model', '=', self._name),
@ -78,7 +78,7 @@ class BaseModel(models.AbstractModel):
div.getparent().remove(div) div.getparent().remove(div)
res['arch'] = etree.tostring(doc, encoding='unicode') 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), ('active', '=', True),
('user_ids', 'in', self.env.user.id), ('user_ids', 'in', self.env.user.id),
('hide_import', '=', True)], limit=1).id ('hide_import', '=', True)], limit=1).id
@ -187,7 +187,7 @@ class BaseModel(models.AbstractModel):
FROM access_management_users_rel_ah as amusr FROM access_management_users_rel_ah as amusr
WHERE amusr.user_id=%s)) WHERE amusr.user_id=%s))
""",[model_numeric_id, self.env.user.id]) """,[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: except:
pass pass
return records return records
@ -214,10 +214,10 @@ class BaseModel(models.AbstractModel):
domain_list += partner_domain domain_list += partner_domain
# eval_context = rec._eval_context() # eval_context = rec._eval_context()
dom = safe_eval(record.domain) if record.domain else [] dom = safe_eval(record.domain) if record.domain else []
if dom:
dom = expression.normalize_domain(dom) dom = expression.normalize_domain(dom)
model_name = self._name model_name = self._name
if isinstance(dom,list): if isinstance(dom,list):
remove_tuple = False
for dom_tuple in dom: for dom_tuple in dom:
if isinstance(dom_tuple, tuple): if isinstance(dom_tuple, tuple):
left_value = dom_tuple[0] left_value = dom_tuple[0]

View File

@ -7,16 +7,23 @@ class remove_action(models.Model):
access_management_id = fields.Many2one('access.management', 'Access Management') access_management_id = fields.Many2one('access.management', 'Access Management')
model_id = fields.Many2one('ir.model', 'Model') 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') 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')]") help="The views 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')]") 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')]",
restrict_export = fields.Boolean('Hide Export') help="The actions are added on list will be hidden in selected model from the defined users.")
restrict_import = fields.Boolean('Hide Import') 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') readonly = fields.Boolean('Read-Only')
restrict_create = fields.Boolean('Hide Create') 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') restrict_edit = fields.Boolean('Hide Edit',
restrict_delete = fields.Boolean('Hide Delete') help="Edit Button will be hidden in selected model from the defined users.")
restrict_archive_unarchive = fields.Boolean('Hide Archive/Unarchive') restrict_delete = fields.Boolean('Hide Delete',
restrict_duplicate = fields.Boolean('Hide Duplicate') help="Delete Button will be hidden in selected model from the defined users.")
restrict_chatter = fields.Boolean('Hide Chatter') 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.")

View File

@ -37,7 +37,7 @@ class res_users(models.Model):
self = api.Environment(cr, SUPERUSER_ID, {})[cls._name] self = api.Environment(cr, SUPERUSER_ID, {})[cls._name]
access_management_obj = self.env['access.management'] 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() raise AccessDenied()
except AccessDenied: except AccessDenied:
_logger.info("Login failed for db:%s login:%s from ", db, login) _logger.info("Login failed for db:%s login:%s from ", db, login)

View File

@ -1,12 +1,22 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 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_access_management_portal_user,access.access.management.portal.user,model_access_management,,1,0,0,0
access_remove_action,access.remove.action,model_remove_action,,1,1,1,1 access_remove_action_portal_user,access.remove.action.portal.user,model_remove_action,,1,0,0,0
access_hide_field,access.hide.field,model_hide_field,,1,1,1,1 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_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_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_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_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 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_access_management access_access_management_portal_user access.access.management access.access.management.portal.user model_access_management 1 1 0 1 0 1 0
3 access_remove_action access_remove_action_portal_user access.remove.action access.remove.action.portal.user model_remove_action 1 1 0 1 0 1 0
4 access_hide_field access_hide_field_portal_user access.hide.field access.hide.field.portal.user model_hide_field 1 1 0 1 0 1 0
5 access_access_domain_ah_portal_user access.access.domain.ah.portal.user model_access_domain_ah 1 0 0 0
6 access_hide_view_nodes_portal_user access.hide.view.nodes.portal.user model_hide_view_nodes 1 0 0 0
7 access_hide_filters_groups_portal_user access_hide_filters_groups_portal_user model_hide_filters_groups base.group_user 1 0 0 0
8 access_hide_chatter_portal_user access.hide.chatter.portal.user model_hide_chatter 1 0 0 0
9 access_action_data access.action.data model_action_data 1 1 1 1
10 access_action_data access_view_data access.action.data access.view.data model_action_data model_view_data 1 1 1 1
11 access_view_data access_store_model_nodes access.view.data access.store.model.nodes model_view_data model_store_model_nodes 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
12 access_store_model_nodes access_store_filters_groups access.store.model.nodes access_store_filters_groups model_store_model_nodes model_store_filters_groups base.group_user 1 1 1 1
access_hide_filters_groups access_hide_filters_groups model_hide_filters_groups base.group_user 1 1 1 1
13 access_store_filters_groups access_menu_item access_store_filters_groups access.menu.item model_store_filters_groups model_menu_item base.group_user 1 1 1 1
14 access_hide_chatter access_access_management access.hide.chatter access.access.management model_hide_chatter model_access_management simplify_access_management.group_access_management_bits 1 1 1 1
15 access_access_domain_ah access.access.domain.ah model_access_domain_ah simplify_access_management.group_access_management_bits 1 1 1 1
16 access_remove_action access.remove.action model_remove_action simplify_access_management.group_access_management_bits 1 1 1 1
17 access_hide_field access.hide.field model_hide_field simplify_access_management.group_access_management_bits 1 1 1 1
18 access_hide_view_nodes access.hide.view.nodes model_hide_view_nodes simplify_access_management.group_access_management_bits 1 1 1 1
19 access_hide_filters_groups access_hide_filters_groups model_hide_filters_groups simplify_access_management.group_access_management_bits 1 1 1 1
20 access_hide_chatter access.hide.chatter model_hide_chatter simplify_access_management.group_access_management_bits 1 1 1 1
21
22

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<data> <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> <field name="name">Access Management</field>
</record> </record>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -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];
});
},
});
});

View File

@ -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));
},
});
}
);

View File

@ -2,25 +2,29 @@ odoo.define('simplify_access_management.hide_chatter', function (require) {
"use strict"; "use strict";
var FormRenderer = require('web.FormRenderer'); var FormRenderer = require('web.FormRenderer');
var Session = require("web.Session"); var session = require("web.Session");
var rpc = require('web.rpc'); var rpc = require('web.rpc');
FormRenderer.include({ FormRenderer.include({
_render: function () { _render: async function () {
const res = this._super.apply(this, arguments); const res = await this._super.apply(this, arguments);
const self = this; const self = this;
// this._super.apply(this, arguments); // this._super.apply(this, arguments);
var hash = window.location.hash.replace("#", '').split("&");
var hash = window.location.hash.substring(1); let cids;
hash = JSON.parse('{"' + hash.replace(/&/g, '","').replace(/=/g,'":"') + '"}', function(key, value) { return key===""?value:decodeURIComponent(value) }) if(hash.findIndex(ele => ele.includes("cid")) == -1)
if(!hash.cids) { cids = session.company_id;
const session = this.getSession(); else {
hash.cids = String(session.company_id); 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({ rpc.query({
model:'access.management', model:'access.management',
method: 'get_chatter_hide_details', method: 'get_chatter_hide_details',
args: [parseInt(hash.cids.charAt(0)), hash.model] args: [cids, model]
}).then(function(result){ }).then(function(result){
if(result['hide_send_mail'] == false) if(result['hide_send_mail'] == false)
{ {
@ -51,6 +55,7 @@ odoo.define('simplify_access_management.hide_chatter', function (require) {
} }
}); });
}
return res; return res;
}, },
}); });

View File

@ -2,7 +2,7 @@ odoo.define('simplify_access_management.hide_export', function (require) {
"use strict"; "use strict";
var ListRenderer = require('web.ListRenderer'); var ListRenderer = require('web.ListRenderer');
var session var session = require("web.Session");
var rpc = require('web.rpc'); var rpc = require('web.rpc');
ListRenderer.include({ ListRenderer.include({
@ -10,22 +10,25 @@ odoo.define('simplify_access_management.hide_export', function (require) {
_render: function () { _render: function () {
const res = this._super.apply(this, arguments); const res = this._super.apply(this, arguments);
const self = this; const self = this;
// this._super.apply(this, arguments); this._super.apply(this, arguments);
var hash = window.location.hash.substring(1); var hash = window.location.hash.replace("#", '').split("&");
hash = JSON.parse('{"' + hash.replace(/&/g, '","').replace(/=/g,'":"') + '"}', function(key, value) { return key===""?value:decodeURIComponent(value) }) let cids;
if(!hash.cids) { if(hash.findIndex(ele => ele.includes("cid")) == -1)
const session = this.getSession(); cids = session.company_id;
hash.cids = String(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({ rpc.query({
model:'access.management', model:'access.management',
method: 'is_export_hide', method: 'is_export_hide',
args: [parseInt(hash.cids.charAt(0)), hash.model] args: [cids, model]
}).then(function(result){ }).then(function(result){
debugger
if(result) { if(result) {
debugger
var btn1 = setInterval(function() { var btn1 = setInterval(function() {
if ($('.o_list_export_xlsx').length) { if ($('.o_list_export_xlsx').length) {
$('.o_list_export_xlsx').remove(); $('.o_list_export_xlsx').remove();
@ -34,6 +37,7 @@ odoo.define('simplify_access_management.hide_export', function (require) {
}, 50); }, 50);
} }
}); });
}
return res; return res;
}, },

View File

@ -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)
);
},
});
}
);

View File

@ -49,7 +49,6 @@ odoo.define("advanced_web_domain_widget.DomainSelector", function (require) {
if (!this.readonly) { if (!this.readonly) {
// Set list of operators according to field type // Set list of operators according to field type
this.displayValue = this.value; this.displayValue = this.value;
debugger
this.operators = this._getOperatorsFromType(selectedField.type, selectedField.name); this.operators = this._getOperatorsFromType(selectedField.type, selectedField.name);
if (_.contains(["child_of", "parent_of", "like", "not like", "=like", "=ilike"], this.operator)) { if (_.contains(["child_of", "parent_of", "like", "not like", "=like", "=ilike"], this.operator)) {
// In case user entered manually or from demo data // In case user entered manually or from demo data

View File

@ -4,7 +4,7 @@
<record id="access_management_form_view_ah" model="ir.ui.view"> <record id="access_management_form_view_ah" model="ir.ui.view">
<field name="name">access_management_form_view_ah</field> <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="model">access.management</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
@ -40,6 +40,7 @@
<group> <group>
<field name="name" default_focus="1" required='1'/> <field name="name" default_focus="1" required='1'/>
<field name="readonly"/> <field name="readonly"/>
<field name="is_apply_on_without_company"/>
<field name="company_ids" options="{'no_create': True}" widget="many2many_tags" <field name="company_ids" options="{'no_create': True}" widget="many2many_tags"
groups="base.group_multi_company"/> groups="base.group_multi_company"/>
<field name="self_model_ids" widget="many2many_tags" invisible="1"/> <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" options="{'no_create': True}" domain="[('id','not in',parent.self_model_ids),('abstract','=',False)]" /> -->
<field name="model_id" context="{'is_access_rights': True}" <field name="model_id" context="{'is_access_rights': True}"
options="{'no_open': True, 'no_create': True, 'no_create_edit': 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}" <field name="field_id" context="{'is_access_rights': True}"
options="{'no_open': True, 'no_create': True, 'no_create_edit': True}" options="{'no_open': True, 'no_create': True, 'no_create_edit': True}"
widget='many2many_tags' domain="[('model_id','=',model_id)]"/> widget='many2many_tags' domain="[('model_id','=',model_id)]"
<field name="invisible" width='1'/> width='10'/>
<field name="readonly" width='1' <field name="invisible" width='10'/>
<field name="readonly" width='10'
attrs="{'column_invisible' : [('parent.readonly','=',True)]}"/> attrs="{'column_invisible' : [('parent.readonly','=',True)]}"/>
<field name="required" width='1'/> <field name="required" width='10'/>
<field name="external_link" width='1'/> <field name="external_link" width='10'/>
</tree> </tree>
</field> </field>
<p role="alert" <p role="alert"
@ -189,12 +192,12 @@
</sheet> </sheet>
</form> </form>
<tree> <tree>
<field name="model_id"/> <field name="model_id" width='10'/>
<field name="domain"/> <field name="domain" width='10'/>
<field name="read_right"/> <field name="read_right" width='10'/>
<field name="create_right"/> <field name="create_right" width='10'/>
<field name="write_right"/> <field name="write_right" width='10'/>
<field name="delete_right"/> <field name="delete_right" width='10'/>
</tree> </tree>
</field> </field>
<p role="alert" <p role="alert"
@ -366,7 +369,7 @@
<record id="access_management_tree_view_ah" model="ir.ui.view"> <record id="access_management_tree_view_ah" model="ir.ui.view">
<field name="name">access_management_tree_view_ah</field> <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="model">access.management</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree decoration-muted="(not active)"> <tree decoration-muted="(not active)">
@ -389,8 +392,8 @@
</record> </record>
<menuitem id="main_menu_simplify_access_management" name="Access Studio" action="action_access_management_ah" <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> </data>
</odoo> </odoo>

View File

@ -5,12 +5,15 @@
<template id="assets_backend" name="simplify_access_management_view assets" inherit_id="web.assets_backend"> <template id="assets_backend" name="simplify_access_management_view assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside"> <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/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/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/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/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/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_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/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> </xpath>
</template> </template>
</data> </data>

View File

@ -8,7 +8,7 @@
<field name="inherit_id" ref="base.view_users_form"/> <field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//notebook" position="inside"> <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'> <field name='access_management_ids'>
<tree> <tree>
<field name="name" /> <field name="name" />