1
@@ -13,8 +13,8 @@
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
'cr_m2o_faster/static/src/views/fields/many2one/*',
|
||||
# 'cr_m2o_faster/static/src/views/fields/many2many/*',
|
||||
# 'cr_m2o_faster/static/src/views/fields/many2one/*',
|
||||
'cr_m2o_faster/static/src/views/fields/many2many/*',
|
||||
],
|
||||
},
|
||||
'installable': True,
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
import {patch} from "@web/core/utils/patch";
|
||||
import {Many2manyField} from "@web/views/fields/many2one/many2one_field";
|
||||
import {useSelectCreate} from "@web/views/fields/relational_utils";
|
||||
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
|
||||
patch(Many2manyField.prototype, {
|
||||
setup(...args) {
|
||||
super.setup(...args)
|
||||
let self = this;
|
||||
this.selectCreate = useSelectCreate({
|
||||
resModel:this.relation,
|
||||
activeActions: this.state.activeActions,
|
||||
onSelected: (resId) => {
|
||||
const resIds = Array.isArray(resId) ? resId : [resId];
|
||||
const values = resIds.map((id) => ({id}));
|
||||
return self.update(values);
|
||||
},
|
||||
onCreateEdit: ({context}) => this.openMany2X({context}),
|
||||
onUnselect: this.update,
|
||||
});
|
||||
},
|
||||
onMoreBtnClick() {
|
||||
const domain = this.getDomain();
|
||||
let dynamicFilters = [];
|
||||
const title = sprintf(_t("Search: %s"), this.props.string);
|
||||
this.selectCreate({
|
||||
domain,
|
||||
context: this.context,
|
||||
filters: dynamicFilters,
|
||||
title,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-inherit="web.Many2ManyField" t-inherit-mode="extension">
|
||||
<xpath expr="//Many2XAutocomplete" position="after">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary fa fa-list-alt o_external_button"
|
||||
tabindex="-1"
|
||||
draggable="false"
|
||||
aria-label="更多"
|
||||
data-tooltip="更多"
|
||||
t-on-click="onMoreBtnClick"
|
||||
/>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -8,8 +8,8 @@
|
||||
class="btn btn-secondary fa fa-list-alt o_external_button"
|
||||
tabindex="-1"
|
||||
draggable="false"
|
||||
aria-label="更多"
|
||||
data-tooltip="更多"
|
||||
aria-label="Show More"
|
||||
data-tooltip="Show More"
|
||||
t-on-click="onMoreBtnClick"
|
||||
/>
|
||||
</xpath>
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
class="btn btn-secondary fa fa-list-alt o_external_button"
|
||||
tabindex="-1"
|
||||
draggable="false"
|
||||
aria-label="更多"
|
||||
data-tooltip="更多"
|
||||
aria-label="Show More"
|
||||
data-tooltip="Show More"
|
||||
t-on-click="onMoreBtnClick"
|
||||
/>
|
||||
</xpath>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
Odoo Proprietary License v1.0
|
||||
|
||||
This software and associated files (the "Software") may only be used (executed,
|
||||
modified, executed after modifications) if you have purchased a valid license
|
||||
from the authors, typically via Odoo Apps, or if you have received a written
|
||||
agreement from the authors of the Software (see the COPYRIGHT file).
|
||||
|
||||
You may develop Odoo modules that use the Software as a library (typically
|
||||
by depending on it, importing it and using its resources), but without copying
|
||||
any source code or material from the Software. You may distribute those
|
||||
modules under the license of your choice, provided that this license is
|
||||
compatible with the terms of the Odoo Proprietary License (For example:
|
||||
LGPL, MIT, or proprietary licenses similar to this one).
|
||||
|
||||
It is forbidden to publish, distribute, sublicense, or sell copies of the Software
|
||||
or modified copies of the Software.
|
||||
|
||||
The above copyright notice and this permission notice must be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
@@ -0,0 +1,73 @@
|
||||
# Part of Odoo, Aktiv Software.
|
||||
# See LICENSE file for full copyright & licensing details.
|
||||
|
||||
# Author: Aktiv Software.
|
||||
# mail: odoo@aktivsoftware.com
|
||||
# Copyright (C) 2015-Present Aktiv Software PVT. LTD.
|
||||
# Contributions:
|
||||
# Aktiv Software:
|
||||
# - Kuldip Trapasiya
|
||||
# - Tanvi Gajera
|
||||
|
||||
{
|
||||
"name": "Tree View Advanced Search / Direct Filter in List",
|
||||
"version": "17.0.1.0.0",
|
||||
"category": "Advanced search on Tree view",
|
||||
"summary": """This module allows a user to directly filter on the Tree / List View.
|
||||
The data will be filtered Runtime.
|
||||
List Filter ,
|
||||
Filter List,
|
||||
Column Filter,
|
||||
Tree Filter,
|
||||
Filter Tree,
|
||||
Advance Search,
|
||||
Search Advance,
|
||||
Tree Search,
|
||||
Direct Search,
|
||||
Fast Search,
|
||||
Quick Search,
|
||||
Dynamic Search,
|
||||
Dynamic Tree,
|
||||
Data Search,
|
||||
Search Data,
|
||||
Data search in Tree,
|
||||
X2many search,
|
||||
X2many search in Tree
|
||||
""",
|
||||
"description": """
|
||||
This module allows a user to directly single/multiple filter on the Tree / List View.
|
||||
The data will be filtered Runtime. Columns can be directly searched on the Tree View.
|
||||
List Filter
|
||||
Column Filter
|
||||
Tree Filter
|
||||
Advance Search
|
||||
Tree Search
|
||||
Direct Search
|
||||
Fast Search
|
||||
Quick Search
|
||||
Dynamic Search
|
||||
Dynamic Tree
|
||||
Data Search
|
||||
Data search in Tree
|
||||
X2many search
|
||||
X2many search in Tree
|
||||
""",
|
||||
"author": "Aktiv Software",
|
||||
"website": "http://www.aktivsoftware.com",
|
||||
"license": "OPL-1",
|
||||
"price": 95.00,
|
||||
"currency": "USD",
|
||||
"depends": ["web", "sale_management"],
|
||||
"data": [],
|
||||
"assets": {
|
||||
"web.assets_backend": [
|
||||
# Custum Library
|
||||
"tree_view_advanced_filter/static/src/js/*.js",
|
||||
"tree_view_advanced_filter/static/src/css/main.scss",
|
||||
]
|
||||
},
|
||||
"images": ["static/description/banner.jpg"],
|
||||
"installable": True,
|
||||
"auto_install": False,
|
||||
"application": False,
|
||||
}
|
||||
|
After Width: | Height: | Size: 655 KiB |
|
After Width: | Height: | Size: 379 KiB |
|
After Width: | Height: | Size: 477 KiB |
|
After Width: | Height: | Size: 472 KiB |
|
After Width: | Height: | Size: 458 KiB |
|
After Width: | Height: | Size: 381 KiB |
|
After Width: | Height: | Size: 739 KiB |
|
After Width: | Height: | Size: 427 KiB |
|
After Width: | Height: | Size: 300 KiB |
|
After Width: | Height: | Size: 162 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
@@ -0,0 +1,542 @@
|
||||
<div class="container">
|
||||
<div class="oe_styling_v8">
|
||||
<div class="container p-3 mb-3">
|
||||
<div class="row">
|
||||
<div class="col-12 d-lg-flex justify-content-between" style="border-bottom:1px solid #d5d5d5">
|
||||
<div class="my-2 d-flex justify-content-center">
|
||||
<img src="/default_icons/aktiv-logo.png" class="w-auto" style="height:50px !important">
|
||||
</div>
|
||||
<div
|
||||
class="my-2 w-100 w-lg-auto d-md-flex align-items-center justify-content-around justify-content-lg-start">
|
||||
<div class="text-white font-weight-bold text-center"
|
||||
style="background-color:#875A7B !important; padding:5px 15px 8px !important; margin:0 5px 5px 5px !important; border-radius: 15px;">
|
||||
<i class="fa fa-check mr-1"></i>Enterprise
|
||||
</div>
|
||||
<div class="text-white font-weight-bold text-center"
|
||||
style="background-color:#7C7BAD !important; padding:5px 15px 8px !important; margin:0 5px 5px 5px !important; border-radius: 15px;">
|
||||
<i class="fa fa-check mr-1"></i>Community
|
||||
</div>
|
||||
<div class="text-white font-weight-bold text-center"
|
||||
style="background-color:#875A7B !important; padding:5px 15px 8px !important; margin:0 5px 5px 5px !important; border-radius: 15px;">
|
||||
<i class="fa fa-check mr-1"></i>Odoo.Sh
|
||||
</div>
|
||||
<div class="text-white font-weight-bold text-center"
|
||||
style="background-color:#7C7BAD !important; padding:5px 15px 8px !important; margin:0 5px 5px 5px !important; border-radius: 15px;">
|
||||
<i class="fa fa-check mr-1"></i>Self Hosted
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container pt-0 px-4 pb-5">
|
||||
<div class="row">
|
||||
<div class="col-12 bg-white" style="padding:4rem 1rem !important;">
|
||||
<div class="d-md-flex justify-content-center mb-2">
|
||||
<img src="icon.png" class="mx-auto mr-md-2 ml-md-0 mb-2 mb-md-0" height="80px" width="80px">
|
||||
<div>
|
||||
<h1 class="text-center font-weight-bold display-3"
|
||||
style="font-family:'Montserrat', sans-serif !important; color: #b01e2f !important">
|
||||
Tree View Advanced Search / Direct Filter in List
|
||||
</h1>
|
||||
<p class="text-center pb-3"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-weight:300 !important; color:#040f3a !important; font-size:1.4rem !important;">
|
||||
The module allows you to quickly search records from the list view.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<img src="GIF.gif" class="img-responsive w-100 h-auto" height="auto">
|
||||
</div>
|
||||
</div>
|
||||
<!-- Demo video link -->
|
||||
<div class="row mb-4 justify-content-center">
|
||||
<a target="_blank" href="https://youtu.be/kvZ0dC6Cnnw"
|
||||
style="background-color: #b01e2f !important; color: #fff !important; font-family:'Montserrat', sans-serif !important; font-size:1.4rem; border-radius: 5px; padding: 5px 15px;"
|
||||
class="fw-bolder w-auto">
|
||||
Video Tutorial
|
||||
</a>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 px-3 text-center">
|
||||
<h2 class="font-weight-bold"
|
||||
style="color: #b01e2f !important; font-family:'Montserrat', sans-serif !important; font-size:2rem;">
|
||||
Explore this module
|
||||
</h2>
|
||||
<div class="mt-3">
|
||||
<a class="font-weight-bold" href="#overview" class="mr-5"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:1.3rem; color:#040f3a !important">Overview
|
||||
<i class="fa fa-chevron-right ml-1" style="color:#282F33 !important"></i></a>
|
||||
<a class="font-weight-bold" href="#features" class="mr-5"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:1.3rem; color:#040f3a !important">Key
|
||||
Features <i class="fa fa-chevron-right ml-1" style="color:#282F33 !important"></i></a>
|
||||
<a class="font-weight-bold" href="#setup" class="mr-5"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:1.3rem; color:#040f3a !important">Setup
|
||||
& Configuration
|
||||
<i class="fa fa-chevron-right ml-1" style="color:#282F33 !important"></i></a>
|
||||
<a class="font-weight-bold" href="#screenshots" class="mr-5"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:1.3rem; color:#040f3a !important">Screenshots
|
||||
<i class="fa fa-chevron-right ml-1" style="color:#282F33 !important"></i></a>
|
||||
</div>
|
||||
<hr class="my-5" style="border-color:d5d5d5 !important">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- OVERVIEW -->
|
||||
<div class="row " id="overview">
|
||||
<div class="col-12 px-4">
|
||||
<h2 class="font-weight-bold"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:2rem; color:#b01e2f !important">
|
||||
Overview
|
||||
</h2>
|
||||
<hr
|
||||
style="border: 2px solid #040f3a !important; background-color: #040f3a !important; width: 50px !important; margin-left: 0 !important; margin-bottom: 2rem !important; margin-top: 8px;">
|
||||
<p class="mt-4"
|
||||
style="font-size:1.1rem !important; color:#282F33 !important; font-weight:400 !important; line-height:1.85 !important">
|
||||
Unlike the default search functionality of Odoo, this custom app allows user to use dynamic single/multiple
|
||||
search filter on the Tree / List View in all the base and custom Odoo modules. The data will be
|
||||
filtered Runtime.
|
||||
For e.g., if user wants to search single/multiple quotation for customers in the invoice module, he/she can
|
||||
search the single as well as multi customers by their invoice number, invoice creation date, delivery date, customer
|
||||
name, invoice date, source document, sales person, company, due date, tax, total amount, amount
|
||||
due, status, etc.
|
||||
In short, each field/column in the list/tree view will contain an advanced single/multiple filter option to
|
||||
easily access the data anywhere.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- FEATURES -->
|
||||
<div class="row my-5" id="features">
|
||||
<div class="col-sm-12 col-md-12 col-lg-12 px-4">
|
||||
<h2 class="font-weight-bold"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:2rem; color:#b01e2f !important">
|
||||
Features
|
||||
</h2>
|
||||
<hr
|
||||
style="border: 2px solid #040f3a !important; background-color: #040f3a !important; width: 50px !important; margin-left: 0 !important; margin-bottom: 2rem !important; margin-top: 8px;">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-6 my-3" style="border-bottom:2px solid #f0f0f0;">
|
||||
<div class="d-flex" style="padding:1rem 0px !important;">
|
||||
<img src="/default_icons/check.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<h3 style="font-size:1.2rem !important">Single/multiple search runtime on every tree views with
|
||||
advanced filter option</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 my-3" style="border-bottom:2px solid #f0f0f0;">
|
||||
<div class="d-flex" style="padding:1rem 0px !important;">
|
||||
<img src="/default_icons/check.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<h3 style="font-size:1.2rem !important">In Date or Datetime fields, a range
|
||||
selection will be visible</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-6 my-3" style="border-bottom:2px solid #f0f0f0;">
|
||||
<div class="d-flex" style="padding:1rem 0px !important;">
|
||||
<img src="/default_icons/check.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<h3 style="font-size:1.2rem !important">User can easily search on text,
|
||||
date/datetime, many2one, integer/float columns</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 my-3" style="border-bottom:2px solid #f0f0f0;">
|
||||
<div class="d-flex" style="padding:1rem 0px !important;">
|
||||
<img src="/default_icons/check.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<h3 style="font-size:1.2rem !important">Integer and Float columns will search
|
||||
for the exact value</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-6 my-3" style="border-bottom:2px solid #f0f0f0;">
|
||||
<div class="d-flex" style="padding:1rem 0px !important;">
|
||||
<img src="/default_icons/check.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<h3 style="font-size:1.2rem !important">Single/multi Search runtime on every tree views of
|
||||
the relational fields(X2many) with advanced filter option</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 my-3" style="border-bottom:2px solid #f0f0f0;">
|
||||
<div class="d-flex" style="padding:1rem 0px !important;">
|
||||
<img src="/default_icons/check.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<h3 style="font-size:1.2rem !important">Apply multiple search filters on single column.
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SETUP & CONFIGURATION -->
|
||||
<div class="row mb-5" id="setup">
|
||||
<div class="col-12 px-4">
|
||||
<h2 class="font-weight-bold"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:2rem; color:#b01e2f !important">
|
||||
Setup & Configuration
|
||||
</h2>
|
||||
<hr
|
||||
style="border: 2px solid #040f3a !important; background-color: #040f3a !important; width: 50px !important; margin-left: 0 !important; margin-bottom: 2rem !important; margin-top: 8px;">
|
||||
|
||||
<div class="mt-5">
|
||||
<h2 class="font-weight-bold"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:1.2rem; color:#b01e2f !important">
|
||||
No prerequisites required before installation.
|
||||
</h2>
|
||||
<ul class="mb-2 pb-2">
|
||||
<li class="p-1" style="border-bottom: 2px solid #f0f0f0;">
|
||||
<h3 style="font-size:1.2rem !important">Required Apps
|
||||
</h3>
|
||||
<p>
|
||||
Web
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<h2 class="font-weight-bold"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:1.2rem; color:#b01e2f !important">
|
||||
Configuration.
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="d-flex mb-2 pb-2">
|
||||
<img src="/default_icons/arrow.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<div>
|
||||
<h3 style="font-size:1.2rem !important">No configurations.
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SCREENSHOTS -->
|
||||
<div class="row mb-5" id="screenshots">
|
||||
<div class="col-12 px-4">
|
||||
<h2 class="font-weight-bold"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:2rem; color:#b01e2f !important">
|
||||
Screenshots
|
||||
</h2>
|
||||
<hr
|
||||
style="border: 2px solid #040f3a !important; background-color: #040f3a !important; width: 50px !important; margin-left: 0 !important; margin-bottom: 2rem !important; margin-top: 8px;">
|
||||
<div class="mt-5">
|
||||
<div class="d-flex mb-2 pb-2">
|
||||
<img src="/default_icons/arrow.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<div>
|
||||
<h3 style="font-size:1.2rem !important">Single/multi search Runtime on Tree Views
|
||||
</h3>
|
||||
<p>
|
||||
After Installing this module, User will see an extra row in every tree view which
|
||||
includes the column filter.
|
||||
User can easily search on text, date/datetime, many2one, integer/float columns.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<img src="Browser_Screen_Mockup_1.jpg" class="img-responsive img-thumbnail border">
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="d-flex mb-2 pb-2">
|
||||
<img src="/default_icons/arrow.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<div>
|
||||
<h3 style="font-size:1.2rem !important">Apply multiple search filters on text, many2one, integer/float columns.
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<img src="Browser_Screen_Mockup_2.jpg" class="img-responsive img-thumbnail border">
|
||||
</div>
|
||||
|
||||
<!-- <div class="mt-5">
|
||||
<img src="Browser_Screen_Mockup_2.jpg" class="img-responsive img-thumbnail border">
|
||||
</div> -->
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="d-flex mb-2 pb-2">
|
||||
<img src="/default_icons/arrow.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<div>
|
||||
<h3 style="font-size:1.2rem !important">Filter will not be visible on widgets and
|
||||
non-stored compute columns.
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<img src="Browser_Screen_Mockup_3.jpg" class="img-responsive img-thumbnail border">
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="d-flex mb-2 pb-2">
|
||||
<img src="/default_icons/arrow.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<div>
|
||||
<h3 style="font-size:1.2rem !important">Single/multi search Runtime on Tree View of relational fields
|
||||
(X2many)</h3>
|
||||
</div>
|
||||
</div>
|
||||
<img src="Browser_Screen_Mockup_4.jpg" class="img-responsive img-thumbnail border">
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="d-flex mb-2 pb-2">
|
||||
<img src="/default_icons/arrow.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<div class="">
|
||||
<h3 style="font-size:1.2rem !important">Apply multiple search filters on single columns</h3>
|
||||
</div>
|
||||
</div>
|
||||
<img src="Browser_Screen_Mockup_5.jpg" class="img-responsive img-thumbnail border">
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<div class="d-flex mb-2 pb-2">
|
||||
<img src="/default_icons/arrow.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<div>
|
||||
<h3 style="font-size:1.2rem !important">Single/ multi filter can be apply on the
|
||||
folded list view i.e in group by mode.
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<img src="Browser_Screen_Mockup_6.jpg" class="img-responsive img-thumbnail border">
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<div class="d-flex mb-2 pb-2">
|
||||
<img src="/default_icons/arrow.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<div>
|
||||
<h3 style="font-size:1.2rem !important">Text and M2O Columns.
|
||||
</h3>
|
||||
<p>
|
||||
It is very easy to search the data in Many2one and Selection fields.
|
||||
The record count and the summation of the column value will also be adjusted based
|
||||
on the data.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<img src="Browser_Screen_Mockup_7.jpg" class="img-responsive img-thumbnail border">
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<div class="d-flex mb-2 pb-2">
|
||||
<img src="/default_icons/arrow.png" width="20px" height="20px" class="mr-2 me-2">
|
||||
<div>
|
||||
<h3 style="font-size:1.2rem !important">Integer and Float Columns.
|
||||
</h3>
|
||||
<p>
|
||||
Integer and Float columns will single/multi search for the exact value inputted by the user.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<img src="Browser_Screen_Mockup_8.jpg" class="img-responsive img-thumbnail border">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- SUGGESTED APPS -->
|
||||
<div class="row mt-3">
|
||||
<div class="col-lg-12 d-flex flex-column justify-content-center" style="padding:2.5rem 15px !important">
|
||||
<h2 class="font-weight-bold"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:2rem; color:#b01e2f !important">
|
||||
Suggested Apps
|
||||
</h2>
|
||||
<hr
|
||||
style="border: 2px solid #040f3a !important; background-color: #040f3a !important; width: 50px !important; margin-left: 0 !important; margin-bottom: 2rem !important; margin-top: 8px;">
|
||||
<div id="product_slider" class="row carousel slide mt-4 data-ride=" carousel="">
|
||||
<!-- The slideshow -->
|
||||
<div class="carousel-inner">
|
||||
<div class="carousel-item active" style="min-height: 193.656px;">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/13.0/garage_management/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block w-100 h-auto"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./suggested_apps/garbage_management.jpg">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/product_social_share_aktiv/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block w-100 h-auto"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./suggested_apps/product_social_media.jpg">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/15.0/ecommerce_country_product_restriction/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block w-100 h-auto"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./suggested_apps/ecommerce_contry_restriction.jpg">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item" style="min-height: 193.656px;">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/15.0/user_recent_log/" target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block w-100 h-auto"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./suggested_apps/user_activity_log.jpg">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/web_odoo_dynamic_dashboard/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block w-100 h-auto"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./suggested_apps/web_dynamic_dashboard.jpg">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/website_product_stock_aktiv/"
|
||||
target="_blank">
|
||||
<div style="border-radius:10px">
|
||||
<img class="img img-responsive center-block w-100 h-auto"
|
||||
style="border-top-left-radius:10px; border-top-right-radius:10px"
|
||||
src="./suggested_apps/website_product_stock.jpg">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Left and right controls -->
|
||||
<a class="carousel-control-prev" href="#product_slider" data-slide="prev"
|
||||
style="width:35px; color:#000"> <span class="carousel-control-prev-icon"><i
|
||||
class="fa fa-chevron-left" style="font-size:24px"></i></span> </a> <a
|
||||
class="carousel-control-next" href="#product_slider" data-slide="next"
|
||||
style="width:35px; color:#000">
|
||||
<span class="carousel-control-next-icon"><i class="fa fa-chevron-right"
|
||||
style="font-size:24px"></i></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SUGGESTED PRODUCTS -->
|
||||
<!-- OUR SERVICES -->
|
||||
<section style="margin-top:2rem !important">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h2 class="font-weight-bold"
|
||||
style="font-family:'Montserrat', sans-serif !important; font-size:2rem; color:#b01e2f !important">
|
||||
Our Services
|
||||
</h2>
|
||||
<hr
|
||||
style="border: 2px solid #040f3a !important; background-color: #040f3a !important; width: 50px !important; margin-left: 0 !important; margin-bottom: 2rem !important; margin-top: 8px;">
|
||||
</div>
|
||||
<div
|
||||
class="col-md-4 col-sm-6 col-12 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
<img src="/default_icons/Odoo_Consulting.png" class="img-responsive"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
</div>
|
||||
<h6 class="text-center"
|
||||
style="font-family:Montserrat, 'sans-serif' !important; font-weight:bold">
|
||||
Odoo
|
||||
Consulting
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="col-md-4 col-sm-6 col-12 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
<img src="/default_icons/Odoo_Customization.png" class="img-responsive"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
</div>
|
||||
<h6 class="text-center"
|
||||
style="font-family:Montserrat, 'sans-serif' !important; font-weight:bold">
|
||||
Odoo
|
||||
Customization
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="col-md-4 col-sm-6 col-12 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
<img src="/default_icons/Odoo_Implementation.png" class="img-responsive"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
</div>
|
||||
<h6 class="text-center"
|
||||
style="font-family:Montserrat, 'sans-serif' !important; font-weight:bold">
|
||||
Odoo
|
||||
Implementation
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="col-md-4 col-sm-6 col-12 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
<img src="/default_icons/Odoo_Integration.png" class="img-responsive"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
</div>
|
||||
<h6 class="text-center"
|
||||
style="font-family:Montserrat, 'sans-serif' !important; font-weight:bold">
|
||||
Odoo
|
||||
Integration
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="col-md-4 col-sm-6 col-12 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
<img src="/default_icons/Odoo_Migration.png" class="img-responsive"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
</div>
|
||||
<h6 class="text-center"
|
||||
style="font-family:Montserrat, 'sans-serif' !important; font-weight:bold">
|
||||
Odoo
|
||||
Migration
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="col-md-4 col-sm-6 col-12 d-flex flex-column justify-content-center align-items-center my-4">
|
||||
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
<img src="/default_icons/Odoo_Support.png" class="img-responsive"
|
||||
style="border-radius:15px !important; height:80px; width:80px">
|
||||
</div>
|
||||
<h6 class="text-center"
|
||||
style="font-family:Montserrat, 'sans-serif' !important; font-weight:bold">
|
||||
Odoo
|
||||
Support
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END OF END OF OUR SERVICES -->
|
||||
<!-- FOOTER -->
|
||||
<!-- Don't Remove Below Part -->
|
||||
<div>
|
||||
<h2 class="oe_slogan">
|
||||
<a href="http://aktivsoftware.com/" target="new">
|
||||
<img src="/default_icons/aktiv-logo.png" class="img img-responsive" />
|
||||
</a>
|
||||
<br />
|
||||
<a href="mailto:sales@aktivsoftware.com" style="color: #000000 !important;">
|
||||
Get Help & Support
|
||||
</a>
|
||||
</h2>
|
||||
<div class="oe_slogan oe_spaced text-center">
|
||||
<a class="btn btn success mt8" title="website" target="new"
|
||||
style="background-color: #b01e2f !important; border-radius: 5px !important; color: #ffffff !important; position:relative; overflow: hidden;"
|
||||
href="http://aktivsoftware.com/"><b>Website</b></a>
|
||||
<a class="btn btn success mt8" title="Contact Us"
|
||||
style="background-color: #b01e2f !important; border-radius: 5px !important; color: #ffffff !important; position:relative; overflow: hidden;"
|
||||
href="mailto:sales@aktivsoftware.com"><b>Contact Us</b></a>
|
||||
<a class="btn btn success mt8" title="Request New Features Now!"
|
||||
style="background-color: #b01e2f !important; border-radius: 5px !important; color: #ffffff !important; position:relative; overflow: hidden;"
|
||||
href="mailto:sales@aktivsoftware.com"><b>Request For New Features</b></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF FOOTER -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 108 KiB |
@@ -0,0 +1,71 @@
|
||||
.tree_search_item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.tree_search_item .selected a:before {
|
||||
font-family: FontAwesome;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
input.input_text{
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.search_div{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #1a4040;
|
||||
font-size: 15px !important;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
padding: 2px;
|
||||
}
|
||||
.input_text{
|
||||
flex: 2;
|
||||
border: none!important;
|
||||
}
|
||||
.search_button{
|
||||
margin: 0px 0px;
|
||||
border:none
|
||||
}
|
||||
.search_button:hover{
|
||||
color: blueviolet;
|
||||
}
|
||||
.remove_button{
|
||||
border:none
|
||||
}
|
||||
.remove_button:hover{
|
||||
color: indianred;
|
||||
}
|
||||
.hidden_button{
|
||||
display:none
|
||||
}
|
||||
.table_layout
|
||||
{
|
||||
table-layout:auto
|
||||
}
|
||||
|
||||
.auto-overflow {
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
/* Hide scrollbar for Chrome, Safari and Opera */
|
||||
.auto-overflow::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hide scrollbar for IE, Edge and Firefox */
|
||||
.auto-overflow {
|
||||
-ms-overflow-style: none;
|
||||
/* IE and Edge */
|
||||
scrollbar-width: none;
|
||||
/* Firefox */
|
||||
}
|
||||
|
||||
.min-wp-50 {
|
||||
min-width: 50px !important;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// /** @odoo-module */
|
||||
|
||||
import { SearchModel } from "@web/search/search_model";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(SearchModel.prototype, {
|
||||
async _reloadSections() {
|
||||
super._reloadSections(...arguments);
|
||||
if (this.ak_domains) {
|
||||
this._domain = this.domain.concat(this.ak_domains);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,594 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { ListRenderer } from "@web/views/list/list_renderer";
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { session } from "@web/session";
|
||||
import { serialize } from "@web/core/l10n/dates";
|
||||
import { serializeDateTime } from "@web/core/l10n/dates";
|
||||
import { loadJS, loadCSS } from "@web/core/assets";
|
||||
const { onMounted, onPatched } = owl;
|
||||
const { DateTime } = luxon;
|
||||
|
||||
export const ListRendererCust = {
|
||||
setup() {
|
||||
|
||||
super.setup();
|
||||
browser.sessionStorage.setItem('domainlist', JSON.stringify([])); // Replaced localStorage with sessionStorage
|
||||
|
||||
onMounted(() => {
|
||||
this._renderSearchPanel()
|
||||
});
|
||||
|
||||
onPatched(() => {
|
||||
this._renderSearchPanel()
|
||||
});
|
||||
},
|
||||
|
||||
_renderSearchPanel: async function () {
|
||||
await loadJS("https://cdn.jsdelivr.net/jquery/latest/jquery.min.js")
|
||||
await loadJS("https://cdn.jsdelivr.net/momentjs/latest/moment.min.js")
|
||||
await loadJS("https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js")
|
||||
await loadCSS("https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css")
|
||||
var List = this.props.list;
|
||||
const bm_params = List.model.__bm_load_params__;
|
||||
const rootRef = this.rootRef.el
|
||||
const tableRef = this.tableRef.el;
|
||||
tableRef.removeAttribute('style')
|
||||
var columns = this.allColumns.filter((col) => {
|
||||
if (col.optional && this.optionalActiveFields[col.name] == false) {
|
||||
return false;
|
||||
}
|
||||
if (col.column_invisible == true || col.column_invisible && col.invisible) {
|
||||
return false;
|
||||
}
|
||||
// if (col.optional == 'hide'){
|
||||
// return false;
|
||||
// }
|
||||
if (['in_invoice', 'in_refund', 'in_receipt'].includes(this.props.list.evalContext.default_move_type)){
|
||||
if (['Vendor', 'Invoice Date'].includes(col.string)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (['out_invoice', 'out_refund', 'out_receipt'].includes(this.props.list.evalContext.default_move_type)){
|
||||
if (['Customer', 'Bill Date'].includes(col.string)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (col.name == 'move_type'){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
var $tr1 = $('<tr>').append(columns.map(columns => this._renderHeaderCellSearch(columns)));
|
||||
if (this.hasSelectors) {
|
||||
$tr1.prepend($('<td>').addClass('o_list_record_selector'));
|
||||
}
|
||||
|
||||
if (this.isStudioEditable || this.displayOptionalFields) {
|
||||
$tr1.append($('<td>').addClass('o_list_record_selector'));
|
||||
}
|
||||
|
||||
if ($(tableRef).find('.search_td').length) {
|
||||
$(tableRef).find('.search_td').parent().replaceWith($tr1)
|
||||
}
|
||||
else {
|
||||
$tr1.insertAfter($(tableRef).find('tr')[0]);
|
||||
}
|
||||
|
||||
rootRef.querySelectorAll('thead tr td.search_td input').forEach((a) => a.addEventListener('keyup', this._onfilter.bind(this)));
|
||||
rootRef.querySelectorAll('.search_button').forEach((a) => a.addEventListener('click', this._onSearch.bind(this)));
|
||||
rootRef.querySelectorAll('.remove_button').forEach((a) => a.addEventListener('click', this._onRemove.bind(this)));
|
||||
rootRef.querySelectorAll('thead tr td').forEach((a) => a.addEventListener('keypress', this._onKeyPress.bind(this)));
|
||||
},
|
||||
|
||||
_renderHeaderCellSearch: function (node) {
|
||||
var List = this.props.list
|
||||
var search_tr = $($('tr')[1]).find('input.input_text')
|
||||
var old_domain = JSON.parse(browser.sessionStorage.getItem('domainlist'))
|
||||
var input_dict = {}
|
||||
var self = this;
|
||||
var $td = $('<td>', {
|
||||
class: 'search_td'
|
||||
});
|
||||
|
||||
for (var i = 0; i < search_tr.length; i++) {
|
||||
var field = $(search_tr[i]).attr('name')
|
||||
var value = $(search_tr[i]).val()
|
||||
input_dict[String(field)] = value
|
||||
}
|
||||
if (node.type != 'field') {
|
||||
return $td
|
||||
}
|
||||
const {
|
||||
name,
|
||||
string,
|
||||
widget,
|
||||
} = node;
|
||||
var searched_value = old_domain.filter(function (domain) {
|
||||
return domain[0] == name;
|
||||
});
|
||||
var widget_list = ["monetary", "date", "many2one_avatar_user", "badge", "task_with_hours", "timesheet_uom", "sol_product_many2one"];
|
||||
var value_of_tr = searched_value.length > 0 ? searched_value[0][2] : ""
|
||||
var field = List.fields[name];
|
||||
|
||||
if (name) {
|
||||
$td.attr('data-name', name);
|
||||
} else if (string) {
|
||||
$td.attr('data-string', string);
|
||||
}
|
||||
if (!field) {
|
||||
return $td;
|
||||
}
|
||||
var description = string || field.string;
|
||||
|
||||
// search elements
|
||||
var search_div = $('<div>').attr({
|
||||
'class': 'search_div d-inline-flex auto-overflow'
|
||||
});
|
||||
var $input = $('<input>').attr({
|
||||
name: name,
|
||||
data_name: name,
|
||||
data_text: string,
|
||||
placeholder: description,
|
||||
autocomplete: "autocomplete",
|
||||
'class': 'input_text min-wp-50'
|
||||
});
|
||||
var search_button = $('<button>').attr({
|
||||
type: 'button',
|
||||
name: name,
|
||||
'class': 'search_button fa fa-search'
|
||||
});
|
||||
var remove_button = $('<button>').attr({
|
||||
type: 'button',
|
||||
name: name,
|
||||
'class': 'remove_button fa fa-remove',
|
||||
});
|
||||
|
||||
// Prepare search bars
|
||||
if (!widget || widget_list.includes(widget)) {
|
||||
if (string !== " " && field.store) {
|
||||
if (field.type == 'selection') {
|
||||
var selection_options = []
|
||||
for (let option = -1; option < field.selection.length - 1; option += 1) {
|
||||
selection_options.push((field.selection[option], field.selection[option + 1]))
|
||||
}
|
||||
|
||||
const selection_input = '<select class="input_text input_select" type="select" name=' + name + ' data_name=' + name + ' data_text=' + string + ' placeholder=' + description + ' style="height:25px;">'
|
||||
var option = '<option selected="selected" class="text-muted" value> -- Select -- </option>';
|
||||
$.each(field.selection, function (index, value) {
|
||||
option += '<option value="' + value[0] + '">' + value[1] + '</option>'
|
||||
$(selection_input).add('<option value="' + value[0] + '">' + value[1] + '</option>')
|
||||
});
|
||||
if (value_of_tr) {
|
||||
if (typeof value_of_tr == 'string') {
|
||||
value_of_tr = [value_of_tr];
|
||||
}
|
||||
value_of_tr.forEach((val) => {
|
||||
var $value_tag = $('<span>').attr({
|
||||
title: val,
|
||||
name: val,
|
||||
value: val,
|
||||
class: 'd-inline-flex badge',
|
||||
})
|
||||
var tag_val = "";
|
||||
field.selection.forEach((value) => {
|
||||
if (val == value[0]) {
|
||||
tag_val = value[1];
|
||||
}
|
||||
});
|
||||
$value_tag.append($(
|
||||
`<div class="o_tag_badge_text">${tag_val}</div>`
|
||||
))
|
||||
$value_tag.val(val);
|
||||
$value_tag.css('background-color', '#dfdfdf');
|
||||
$value_tag.css('border-radius', '20px');
|
||||
$value_tag.css('font-size', '15px');
|
||||
search_div.append($value_tag)
|
||||
})
|
||||
}
|
||||
|
||||
var sel_in = selection_input + option + '</select>'
|
||||
search_div.find('span').append(remove_button);
|
||||
search_div.append(sel_in)
|
||||
search_div.append(search_button)
|
||||
$td.append(search_div)
|
||||
}
|
||||
if (['integer', 'float', 'monetary'].includes(field.type)) {
|
||||
$input.attr({ type: 'number' });
|
||||
|
||||
$input.text(description)
|
||||
if (value_of_tr) {
|
||||
if (typeof value_of_tr == 'number') {
|
||||
value_of_tr = [value_of_tr];
|
||||
}
|
||||
value_of_tr.forEach((val) => {
|
||||
var $value_tag = $('<span>').attr({
|
||||
title: val,
|
||||
name: val,
|
||||
value: val,
|
||||
class: 'd-inline-flex badge',
|
||||
})
|
||||
$value_tag.append($(
|
||||
`<div class="o_tag_badge_text">${val}</div>`
|
||||
))
|
||||
$value_tag.val(val);
|
||||
$value_tag.css('background-color', '#dfdfdf');
|
||||
$value_tag.css('border-radius', '20px');
|
||||
$value_tag.css('font-size', '15px');
|
||||
search_div.append($value_tag)
|
||||
})
|
||||
}
|
||||
search_div.find('span').append(remove_button);
|
||||
search_div.append($input);
|
||||
search_div.append(search_button);
|
||||
$td.append(search_div);
|
||||
}
|
||||
if (['many2one', 'char'].includes(field.type)) {
|
||||
$input.attr({ type: 'text' });
|
||||
|
||||
$input.text(description)
|
||||
const values_of_tr = searched_value.map((val) => {
|
||||
return val[2];
|
||||
})
|
||||
if (values_of_tr.length) {
|
||||
values_of_tr.forEach((val) => {
|
||||
var $value_tag = $('<span>').attr({
|
||||
title: val,
|
||||
name: val,
|
||||
value: val,
|
||||
class: 'd-inline-flex badge',
|
||||
})
|
||||
$value_tag.append($(
|
||||
`<div class="o_tag_badge_text">${val}</div>`
|
||||
))
|
||||
$value_tag.val(val);
|
||||
$value_tag.append(remove_button);
|
||||
$value_tag.css('background-color', '#dfdfdf');
|
||||
$value_tag.css('border-radius', '20px');
|
||||
$value_tag.css('font-size', '15px');
|
||||
search_div.append($value_tag)
|
||||
})
|
||||
}
|
||||
search_div.find('span').append(remove_button);
|
||||
search_div.append($input);
|
||||
search_div.append(search_button);
|
||||
$td.append(search_div);
|
||||
}
|
||||
if (field.type == 'datetime' || field.type == 'date') {
|
||||
var value_of_tr1 = searched_value.length > 1 ? (searched_value[0][2]).split(' ')[0] + '/' + (searched_value[1][2]).split(' ')[0] : ""
|
||||
var search_div = $('<div>').attr({
|
||||
'class': 'search_div'
|
||||
});
|
||||
var $input_date1 = $('<input>').attr({
|
||||
type: 'text',
|
||||
name: name,
|
||||
placeholder: 'Date Range',
|
||||
autocomplete: "autocomplete",
|
||||
width: '150px',
|
||||
'class': 'input_text',
|
||||
'style': 'min-width:200px !important'
|
||||
});
|
||||
var search_button = $('<button>').attr({
|
||||
type: 'button',
|
||||
name: name,
|
||||
'class': 'search_button fa fa-search'
|
||||
});
|
||||
var remove_button = $('<button>').attr({
|
||||
type: 'button',
|
||||
name: name,
|
||||
'class': 'remove_button fa fa-remove hidden_button',
|
||||
});
|
||||
$input_date1.daterangepicker();
|
||||
$input_date1.on('apply.daterangepicker', function (ev, picker) {
|
||||
$input_date1.val(picker.startDate.format('YYYY-MM-DD') + '/' + picker.endDate.format('YYYY-MM-DD'));
|
||||
var e = $.Event("keypress", {
|
||||
which: 13
|
||||
});
|
||||
$input_date1.trigger(e);
|
||||
e.keyCode = 13
|
||||
self._onfilter(e)
|
||||
$input_date1.change()
|
||||
});
|
||||
|
||||
$input_date1.on('cancel.daterangepicker', function (ev, picker) {
|
||||
$input_date1.val('');
|
||||
var e = $.Event("keypress", {
|
||||
which: 13
|
||||
});
|
||||
$input_date1.trigger(e);
|
||||
e.keyCode = 13
|
||||
self._onfilter(e)
|
||||
$input_date1.change()
|
||||
});
|
||||
$input_date1.text(description)
|
||||
$input_date1.val(value_of_tr1)
|
||||
|
||||
if (value_of_tr1) {
|
||||
$(search_button).addClass('hidden_button');
|
||||
$(remove_button).removeClass('hidden_button');
|
||||
}
|
||||
if ($(search_button).hasClass('hidden_button')) {
|
||||
$input_date1.attr('readonly', 'readonly');
|
||||
$input_date1.css('background-color', '#dfdfdf');
|
||||
$input_date1.css('border-radius', '20px');
|
||||
}
|
||||
search_div.append($input_date1)
|
||||
search_div.append(remove_button)
|
||||
search_div.append(search_button)
|
||||
$td.append(search_div)
|
||||
}
|
||||
}
|
||||
}
|
||||
return $td;
|
||||
},
|
||||
|
||||
_onKeyPress: function (ev) {
|
||||
ev.stopPropagation(); // to prevent jquery's blockUI to cancel event
|
||||
},
|
||||
|
||||
_onSearch: function (event) {
|
||||
var self = this
|
||||
var $target = $(event.currentTarget);
|
||||
var field_name = $target.attr('name')
|
||||
let all_input_tags = $target.parents('tr').find('input.input_text,select.input_text')
|
||||
if (!all_input_tags.length) {
|
||||
all_input_tags = $($('tr')[5]).find('input.input_text,select.input_text')
|
||||
}
|
||||
all_input_tags.each(function (el) {
|
||||
if (all_input_tags[el].name == field_name) {
|
||||
var e = $.Event("keypress", {
|
||||
which: 13
|
||||
});
|
||||
$(all_input_tags[el]).trigger(e);
|
||||
e.keyCode = 13
|
||||
self._onfilter(e)
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_onRemove: function (event) {
|
||||
const List = this.props.list;
|
||||
var self = this;
|
||||
var updated_domain = [];
|
||||
var old_domain = JSON.parse(browser.sessionStorage.getItem('domainlist'));
|
||||
var field_name = $(event.currentTarget).attr('name');
|
||||
var tag_value = $(event.currentTarget.parentElement).attr('value');
|
||||
let all_input_tags = $($('tr')[1]).find('input.input_text');
|
||||
|
||||
if (!all_input_tags.length) {
|
||||
all_input_tags = $($('tr')[5]).find('input.input_text')
|
||||
}
|
||||
const ListDomain = old_domain;
|
||||
if (["monetary", "float", "integer", "selection"].includes(List.fields[field_name].type)) {
|
||||
ListDomain.map(function (el) {
|
||||
tag_value = !isNaN(tag_value) ? parseFloat(tag_value) : tag_value;
|
||||
if (field_name == el[0] && el[2].includes(tag_value)) {
|
||||
const index = el[2].indexOf(tag_value);
|
||||
index > -1 ? el[2].splice(index, 1) : false;
|
||||
el[2].length ? updated_domain.push(el) : false;
|
||||
}
|
||||
else {
|
||||
updated_domain.push(el)
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (["date", "datetime"].includes(List.fields[field_name].type)) {
|
||||
ListDomain.map(function (el) {
|
||||
if (field_name != el[0]) {
|
||||
updated_domain.push(el)
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
ListDomain.map(function (el) {
|
||||
if (field_name != el[0] || tag_value != el[2]) {
|
||||
updated_domain.push(el)
|
||||
}
|
||||
if (el == '|') {
|
||||
let index = updated_domain.indexOf('|');
|
||||
updated_domain.splice(index, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
browser.sessionStorage.setItem('domainlist', JSON.stringify(updated_domain));
|
||||
var indexes = []
|
||||
var to_update = []
|
||||
var count = 0
|
||||
updated_domain.forEach(el => {
|
||||
if (indexes.length && el[1] == 'ilike' && updated_domain[indexes[indexes.length - 1]][0] == el[0]) {
|
||||
to_update.push(indexes[indexes.length - 1])
|
||||
} else if (el[1] == 'ilike') {
|
||||
indexes.push(count)
|
||||
}
|
||||
count += 1;
|
||||
})
|
||||
to_update.reverse()
|
||||
to_update.forEach(A => {
|
||||
updated_domain.splice(A, 0, '|');
|
||||
})
|
||||
self.perform_search(self, updated_domain);
|
||||
self._renderSearchPanel();
|
||||
},
|
||||
|
||||
_onfilter: function (e) {
|
||||
const List = this.props.list;
|
||||
const old_domain = JSON.parse(browser.sessionStorage.getItem('domainlist'));
|
||||
|
||||
if (e.key === 'Enter' || e.keyCode === 13) {
|
||||
var domain_list = [];
|
||||
var self = this
|
||||
var $target = $(e.target);
|
||||
let all_input_tags = $target.parents('tr').find('input.input_text')
|
||||
if (!all_input_tags.length) {
|
||||
all_input_tags = $($('tr')[5]).find('input.input_text')
|
||||
}
|
||||
|
||||
let all_select_tags = $target.parents('tr').find('select.input_text')
|
||||
if (!all_select_tags.length) {
|
||||
all_select_tags = $($('tr')[5]).find('select.input_text')
|
||||
}
|
||||
|
||||
var search_tr = all_input_tags.filter(function (el) {
|
||||
return all_input_tags[el].value
|
||||
});
|
||||
var search_select = all_select_tags.filter(function (el) {
|
||||
return all_select_tags[el].value
|
||||
});
|
||||
|
||||
/* Checking if both the variables `search_tr` and `search_select` are
|
||||
empty. If both variables are empty, it will return without executing the further code. */
|
||||
if (!search_tr.length && !search_select.length) {
|
||||
// self.perform_search(self, domain_list);
|
||||
return
|
||||
}
|
||||
|
||||
for (var i = 0; i < search_tr.length; i++) {
|
||||
var field = $(search_tr[i]).attr('name')
|
||||
var string = search_tr[i].textContent
|
||||
var value = $(search_tr[i]).val()
|
||||
if (value) {
|
||||
if (List.fields[field].type == "date") {
|
||||
var startDate = moment(value.split('/')[0]).format('YYYY-MM-DD');
|
||||
var endDate = moment(value.split('/')[1]).format('YYYY-MM-DD');
|
||||
if (startDate == 'Invalid date' || endDate == 'Invalid date') {
|
||||
window.alert("Please enter valid input for " + string);
|
||||
} else {
|
||||
domain_list.push([field, '>=', startDate])
|
||||
domain_list.push([field, '<=', endDate])
|
||||
}
|
||||
} else if (List.fields[field].type == "datetime") {
|
||||
var startDate = moment(value.split('/')[0]).format('YYYY-MM-DD 00:00:00');
|
||||
var endDate = moment(value.split('/')[1]).format('YYYY-MM-DD 23:59:59');
|
||||
if (startDate == 'Invalid date' || endDate == 'Invalid date') {
|
||||
window.alert("Please enter valid input for " + string);
|
||||
} else {
|
||||
domain_list.push([field, '>=', startDate])
|
||||
domain_list.push([field, '<=', endDate])
|
||||
}
|
||||
|
||||
} else if (["monetary", "float", "integer"].includes(List.fields[field].type)) {
|
||||
var domain = old_domain.filter((domain) => {
|
||||
return domain[0] == field;
|
||||
})
|
||||
if (domain.length) {
|
||||
if (!domain[0][2].includes(parseFloat(value))) {
|
||||
domain[0][2].push(parseFloat(value));
|
||||
}
|
||||
domain_list.push(domain[0])
|
||||
}
|
||||
else {
|
||||
domain_list.push([field, 'in', [parseFloat(value)]]);
|
||||
}
|
||||
} else {
|
||||
if (old_domain.length) {
|
||||
old_domain.forEach((domain) => {
|
||||
if (domain[0] == field) {
|
||||
domain_list.push(domain);
|
||||
}
|
||||
})
|
||||
if (!(old_domain.map((d) => { return d[2] }).includes(value) &&
|
||||
old_domain.map((d) => { return d[0] }).includes(field))) {
|
||||
domain_list.push([field, 'ilike', value]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
domain_list.push([field, 'ilike', value]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$(all_select_tags).each(function (index, elem) {
|
||||
var elem_value = $(elem).val();
|
||||
var elem_field = $(elem).attr('data_name');
|
||||
if (elem_value.length > 0) {
|
||||
if (List.fields[elem_field].type == 'selection') {
|
||||
var domain = old_domain.filter((domain) => {
|
||||
return domain[0] == elem_field
|
||||
})
|
||||
if (domain.length) {
|
||||
if (!domain[0][2].includes(elem_value)) {
|
||||
domain[0][2].push(elem_value);
|
||||
}
|
||||
domain_list.push(domain[0])
|
||||
}
|
||||
else {
|
||||
domain_list.push([elem_field, 'in', [elem_value]])
|
||||
}
|
||||
}
|
||||
else {
|
||||
domain_list.push([elem_field, '=', elem_value])
|
||||
}
|
||||
}
|
||||
});
|
||||
old_domain.forEach((domain) => {
|
||||
var avail = domain_list.filter(a => {
|
||||
if (domain[1] == 'in') {
|
||||
return domain[2].every(f => a[2].includes(f)) && a[0] == domain[0]
|
||||
}
|
||||
else {
|
||||
return a[2].toString() == domain[2].toString() && a[0] == domain[0]
|
||||
}
|
||||
|
||||
}).length
|
||||
if (!(avail)) {
|
||||
domain_list.push(domain)
|
||||
}
|
||||
})
|
||||
browser.sessionStorage.setItem('domainlist', JSON.stringify(domain_list));
|
||||
var indexes = []
|
||||
var to_update = []
|
||||
var count = 0
|
||||
domain_list.forEach(el => {
|
||||
if (indexes.length && el[1] == 'ilike' && domain_list[indexes[indexes.length - 1]][0] == el[0]) {
|
||||
to_update.push(indexes[indexes.length - 1])
|
||||
} else if (el[1] == 'ilike') {
|
||||
indexes.push(count)
|
||||
}
|
||||
count += 1;
|
||||
})
|
||||
to_update.reverse()
|
||||
to_update.forEach(A => {
|
||||
domain_list.splice(A, 0, '|');
|
||||
})
|
||||
self.perform_search(self, domain_list);
|
||||
}
|
||||
},
|
||||
|
||||
perform_search: async function (self, domain_list) {
|
||||
const searchModel = self.env.searchModel;
|
||||
const list = self.props.list;
|
||||
|
||||
|
||||
if (self.isX2Many) {
|
||||
const bm_params = list.model.config;
|
||||
/**
|
||||
* Function will not apply to new records.
|
||||
*/
|
||||
if (!(bm_params.resId || bm_params.resIds.length)) {
|
||||
browser.sessionStorage.setItem('domainlist', JSON.stringify([]));
|
||||
return;
|
||||
}
|
||||
var res_id = bm_params.resId ? bm_params.resId : bm_params.resIds[0]
|
||||
const readIds = await self.env.model.orm.read(
|
||||
self.props.nestedKeyOptionalFieldsData.model,
|
||||
[res_id],
|
||||
[self.props.nestedKeyOptionalFieldsData.field])
|
||||
|
||||
domain_list.push(['id', 'in', readIds[0][self.props.nestedKeyOptionalFieldsData.field]])
|
||||
|
||||
var resIds = await self.env.model.orm.search(list.resModel, domain_list, {
|
||||
limit: session.active_ids_limit,
|
||||
context: list.context,
|
||||
});
|
||||
await list._load({'nextCurrentIds': resIds})
|
||||
}
|
||||
else {
|
||||
searchModel.ak_domains = domain_list;
|
||||
searchModel._notify();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
patch(ListRenderer.prototype, ListRendererCust);
|
||||
@@ -9,6 +9,7 @@ from odoo.exceptions import UserError, ValidationError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HrAttendance(models.Model):
|
||||
_inherit = "hr.attendance"
|
||||
_description = "Attendance"
|
||||
|
||||