mirror of https://github.com/OCA/web.git
[16.0][MIG] web_search_with_and.
parent
42cd00faf5
commit
8cc6e17930
|
@ -0,0 +1 @@
|
|||
../../../../web_search_with_and
|
|
@ -0,0 +1,6 @@
|
|||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['setuptools-odoo'],
|
||||
odoo_addon=True,
|
||||
)
|
|
@ -14,14 +14,14 @@ Use AND conditions on omnibar search
|
|||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github
|
||||
:target: https://github.com/OCA/web/tree/15.0/web_search_with_and
|
||||
:target: https://github.com/OCA/web/tree/16.0/web_search_with_and
|
||||
:alt: OCA/web
|
||||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
||||
:target: https://translation.odoo-community.org/projects/web-15-0/web-15-0-web_search_with_and
|
||||
:target: https://translation.odoo-community.org/projects/web-16-0/web-16-0-web_search_with_and
|
||||
:alt: Translate me on Weblate
|
||||
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
|
||||
:target: https://runbot.odoo-community.org/runbot/162/15.0
|
||||
:alt: Try me on Runbot
|
||||
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
|
||||
:target: https://runboat.odoo-community.org/webui/builds.html?repo=OCA/web&target_branch=16.0
|
||||
:alt: Try me on Runboat
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||
|
||||
|
@ -58,7 +58,7 @@ Bug Tracker
|
|||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/OCA/web/issues/new?body=module:%20web_search_with_and%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
`feedback <https://github.com/OCA/web/issues/new?body=module:%20web_search_with_and%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
|
@ -82,6 +82,7 @@ Contributors
|
|||
* Souheil Bejaoui <souheil.bejaoui@acsone.eu>
|
||||
* Pedro Guirao <pedro.guirao@ingenieriacloud.com>
|
||||
* Nedas Žilinskas <nedas.zilinskas@avoin.systems>
|
||||
* Sandip SerpentCS <sandip.v.serpentcs@gmail.com>
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
@ -96,6 +97,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
|
|||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
This module is part of the `OCA/web <https://github.com/OCA/web/tree/15.0/web_search_with_and>`_ project on GitHub.
|
||||
This module is part of the `OCA/web <https://github.com/OCA/web/tree/16.0/web_search_with_and>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
|
|
|
@ -4,16 +4,17 @@
|
|||
|
||||
{
|
||||
"name": "Use AND conditions on omnibar search",
|
||||
"version": "15.0.1.0.0",
|
||||
"author": "Versada UAB, ACSONE SA/NV, Serincloud, Odoo Community Association (OCA)",
|
||||
"version": "16.0.1.0.0",
|
||||
"author": """Sandip SCS, Versada UAB, ACSONE SA/NV, Serincloud,
|
||||
Odoo Community Association (OCA)""",
|
||||
"license": "AGPL-3",
|
||||
"category": "web",
|
||||
"website": "https://github.com/OCA/web",
|
||||
"depends": ["web"],
|
||||
"assets": {
|
||||
"web.assets_backend": [
|
||||
"/web_search_with_and/static/src/js/control_panel_model_extension.js",
|
||||
"/web_search_with_and/static/src/js/search_bar.js",
|
||||
"/web_search_with_and/static/src/js/search_model.esm.js",
|
||||
"/web_search_with_and/static/src/js/search_bar.esm.js",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
* Souheil Bejaoui <souheil.bejaoui@acsone.eu>
|
||||
* Pedro Guirao <pedro.guirao@ingenieriacloud.com>
|
||||
* Nedas Žilinskas <nedas.zilinskas@avoin.systems>
|
||||
* Sandip SerpentCS <sandip.v.serpentcs@gmail.com>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
|
||||
<meta name="generator" content="Docutils: http://docutils.sourceforge.net/" />
|
||||
<title>Use AND conditions on omnibar search</title>
|
||||
<style type="text/css">
|
||||
|
||||
|
@ -367,7 +367,7 @@ ul.auto-toc {
|
|||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/web/tree/15.0/web_search_with_and"><img alt="OCA/web" src="https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/web-15-0/web-15-0-web_search_with_and"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/162/15.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/web/tree/16.0/web_search_with_and"><img alt="OCA/web" src="https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/web-16-0/web-16-0-web_search_with_and"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runboat.odoo-community.org/webui/builds.html?repo=OCA/web&target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
||||
<p>When searching for records on same field Odoo joins multiple queries with OR.
|
||||
For example:</p>
|
||||
<ul class="simple">
|
||||
|
@ -405,7 +405,7 @@ and Odoo finds customers containing “John” AND “Smith”</p>
|
|||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/web/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/OCA/web/issues/new?body=module:%20web_search_with_and%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<a class="reference external" href="https://github.com/OCA/web/issues/new?body=module:%20web_search_with_and%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
|
@ -428,6 +428,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
|
|||
<li>Souheil Bejaoui <<a class="reference external" href="mailto:souheil.bejaoui@acsone.eu">souheil.bejaoui@acsone.eu</a>></li>
|
||||
<li>Pedro Guirao <<a class="reference external" href="mailto:pedro.guirao@ingenieriacloud.com">pedro.guirao@ingenieriacloud.com</a>></li>
|
||||
<li>Nedas Žilinskas <<a class="reference external" href="mailto:nedas.zilinskas@avoin.systems">nedas.zilinskas@avoin.systems</a>></li>
|
||||
<li>Sandip SerpentCS <<a class="reference external" href="mailto:sandip.v.serpentcs@gmail.com">sandip.v.serpentcs@gmail.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
|
@ -437,7 +438,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
|
|||
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.</p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/web/tree/15.0/web_search_with_and">OCA/web</a> project on GitHub.</p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/web/tree/16.0/web_search_with_and">OCA/web</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
odoo.define(
|
||||
"web_search_with_and/static/src/js/control_panel_model_extension.js",
|
||||
function (require) {
|
||||
"use strict";
|
||||
|
||||
const {patch} = require("web.utils");
|
||||
const components = {
|
||||
ControlPanelModelExtension: require("web/static/src/js/control_panel/control_panel_model_extension.js"),
|
||||
};
|
||||
|
||||
const patchObject = components.ControlPanelModelExtension.prototype;
|
||||
patch(
|
||||
patchObject,
|
||||
"web_search_with_and/static/src/js/control_panel_model_extension.js",
|
||||
{
|
||||
addAutoCompletionValues({
|
||||
filterId,
|
||||
label,
|
||||
value,
|
||||
operator,
|
||||
isShiftKey,
|
||||
}) {
|
||||
const queryElem = this.state.query.find(
|
||||
(queryElem) =>
|
||||
queryElem.filterId === filterId &&
|
||||
queryElem.value === value &&
|
||||
queryElem.operator === operator
|
||||
);
|
||||
if (!queryElem) {
|
||||
if (isShiftKey) {
|
||||
const groupId = Math.random();
|
||||
this.state.query.push({
|
||||
filterId,
|
||||
groupId,
|
||||
label,
|
||||
value,
|
||||
operator,
|
||||
});
|
||||
} else {
|
||||
const {groupId} = this.state.filters[filterId];
|
||||
this.state.query.push({
|
||||
filterId,
|
||||
groupId,
|
||||
label,
|
||||
value,
|
||||
operator,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
queryElem.label = label;
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
|
@ -0,0 +1,23 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import {patch} from "@web/core/utils/patch";
|
||||
import {SearchBar} from "@web/search/search_bar/search_bar";
|
||||
|
||||
patch(SearchBar.prototype, "web_search_with_and/static/src/js/search_bar.js", {
|
||||
selectItem(item) {
|
||||
if (!item.unselectable) {
|
||||
const {searchItemId, label, operator, value} = item;
|
||||
this.env.searchModel.addAutoCompletionValues(searchItemId, {
|
||||
label,
|
||||
operator,
|
||||
value,
|
||||
isShiftKey: this.isShiftKey,
|
||||
});
|
||||
}
|
||||
this.resetState();
|
||||
},
|
||||
onSearchKeydown(ev) {
|
||||
this.isShiftKey = ev.shiftKey || false;
|
||||
this._super(ev);
|
||||
},
|
||||
});
|
|
@ -1,140 +0,0 @@
|
|||
odoo.define("web_search_with_and/static/src/js/search_bar.js", function (require) {
|
||||
"use strict";
|
||||
|
||||
const {patch} = require("web.utils");
|
||||
const components = {
|
||||
SearchBar: require("web.SearchBar"),
|
||||
};
|
||||
|
||||
const patchObject = components.SearchBar.prototype;
|
||||
patch(patchObject, "web_search_with_and/static/src/js/search_bar.js", {
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} source
|
||||
*/
|
||||
_selectSource(source) {
|
||||
// Inactive sources are:
|
||||
// - Selection sources
|
||||
// - "no result" items
|
||||
if (source.active) {
|
||||
const labelValue = source.label || this.state.inputValue;
|
||||
console.log(
|
||||
"------------- addAutoCompletionValues11 -------------",
|
||||
source,
|
||||
this.isShiftKey
|
||||
);
|
||||
this.model.dispatch("addAutoCompletionValues", {
|
||||
filterId: source.filterId,
|
||||
value:
|
||||
"value" in source
|
||||
? source.value
|
||||
: this._parseWithSource(labelValue, source),
|
||||
label: labelValue,
|
||||
operator: source.filterOperator || source.operator,
|
||||
isShiftKey: this.isShiftKey,
|
||||
});
|
||||
}
|
||||
this._closeAutoComplete();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {KeyboardEvent} ev
|
||||
*/
|
||||
_onSearchKeydown(ev) {
|
||||
if (ev.isComposing) {
|
||||
// This case happens with an IME for example: we let it handle all key events.
|
||||
return;
|
||||
}
|
||||
if (ev.shiftKey) {
|
||||
this.isShiftKey = true;
|
||||
} else {
|
||||
this.isShiftKey = false;
|
||||
}
|
||||
const currentItem = this.state.sources[this.state.focusedItem] || {};
|
||||
switch (ev.key) {
|
||||
case "ArrowDown":
|
||||
ev.preventDefault();
|
||||
if (Object.keys(this.state.sources).length) {
|
||||
let nextIndex = this.state.focusedItem + 1;
|
||||
if (nextIndex >= this.state.sources.length) {
|
||||
nextIndex = 0;
|
||||
}
|
||||
this.state.focusedItem = nextIndex;
|
||||
} else {
|
||||
this.env.bus.trigger("focus-view");
|
||||
}
|
||||
break;
|
||||
case "ArrowLeft":
|
||||
if (currentItem.expanded) {
|
||||
// Priority 1: fold expanded item.
|
||||
ev.preventDefault();
|
||||
this._expandSource(currentItem, false);
|
||||
} else if (currentItem.parent) {
|
||||
// Priority 2: focus parent item.
|
||||
ev.preventDefault();
|
||||
this.state.focusedItem = this.state.sources.indexOf(
|
||||
currentItem.parent
|
||||
);
|
||||
// Priority 3: Do nothing (navigation inside text).
|
||||
} else if (ev.target.selectionStart === 0) {
|
||||
// Priority 4: navigate to rightmost facet.
|
||||
this._focusFacet(this.model.get("facets").length - 1);
|
||||
}
|
||||
break;
|
||||
case "ArrowRight":
|
||||
if (ev.target.selectionStart === this.state.inputValue.length) {
|
||||
// Priority 1: Do nothing (navigation inside text).
|
||||
if (currentItem.expand) {
|
||||
// Priority 2: go to first child or expand item.
|
||||
ev.preventDefault();
|
||||
if (currentItem.expanded) {
|
||||
this.state.focusedItem++;
|
||||
} else {
|
||||
this._expandSource(currentItem, true);
|
||||
}
|
||||
} else if (
|
||||
ev.target.selectionStart === this.state.inputValue.length
|
||||
) {
|
||||
// Priority 3: navigate to leftmost facet.
|
||||
this._focusFacet(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "ArrowUp":
|
||||
ev.preventDefault();
|
||||
let previousIndex = this.state.focusedItem - 1;
|
||||
if (previousIndex < 0) {
|
||||
previousIndex = this.state.sources.length - 1;
|
||||
}
|
||||
this.state.focusedItem = previousIndex;
|
||||
break;
|
||||
case "Backspace":
|
||||
if (!this.state.inputValue.length) {
|
||||
const facets = this.model.get("facets");
|
||||
if (facets.length) {
|
||||
this._onFacetRemove(facets[facets.length - 1]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "Enter":
|
||||
if (!this.state.inputValue.length) {
|
||||
this.model.dispatch("search");
|
||||
break;
|
||||
}
|
||||
/* Falls through */
|
||||
case "Tab":
|
||||
if (this.state.inputValue.length) {
|
||||
ev.preventDefault(); // Keep the focus inside the search bar
|
||||
this._selectSource(currentItem);
|
||||
}
|
||||
break;
|
||||
case "Escape":
|
||||
if (this.state.sources.length) {
|
||||
this._closeAutoComplete();
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
|
@ -0,0 +1,84 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import {patch} from "@web/core/utils/patch";
|
||||
import {rankInterval} from "@web/search/utils/dates";
|
||||
import {SearchModel} from "@web/search/search_model";
|
||||
|
||||
patch(SearchModel.prototype, "web_search_with_and/static/src/js/search_model.js", {
|
||||
_getGroups() {
|
||||
const preGroups = [];
|
||||
for (const queryElem of this.query) {
|
||||
const {searchItemId} = queryElem;
|
||||
let {groupId} = this.searchItems[searchItemId];
|
||||
if ("autocompleteValue" in queryElem) {
|
||||
if (queryElem.autocompleteValue.isShiftKey) {
|
||||
groupId = Math.random();
|
||||
}
|
||||
}
|
||||
let preGroup = preGroups.find((group) => group.id === groupId);
|
||||
if (!preGroup) {
|
||||
preGroup = {id: groupId, queryElements: []};
|
||||
preGroups.push(preGroup);
|
||||
}
|
||||
queryElem.groupId = groupId;
|
||||
preGroup.queryElements.push(queryElem);
|
||||
}
|
||||
const groups = [];
|
||||
for (const preGroup of preGroups) {
|
||||
const {queryElements, id} = preGroup;
|
||||
const activeItems = [];
|
||||
for (const queryElem of queryElements) {
|
||||
const {searchItemId} = queryElem;
|
||||
let activeItem = activeItems.find(
|
||||
({searchItemId: id}) => id === searchItemId
|
||||
);
|
||||
if ("generatorId" in queryElem) {
|
||||
if (!activeItem) {
|
||||
activeItem = {searchItemId, generatorIds: []};
|
||||
activeItems.push(activeItem);
|
||||
}
|
||||
activeItem.generatorIds.push(queryElem.generatorId);
|
||||
} else if ("intervalId" in queryElem) {
|
||||
if (!activeItem) {
|
||||
activeItem = {searchItemId, intervalIds: []};
|
||||
activeItems.push(activeItem);
|
||||
}
|
||||
activeItem.intervalIds.push(queryElem.intervalId);
|
||||
} else if ("autocompleteValue" in queryElem) {
|
||||
if (!activeItem) {
|
||||
activeItem = {searchItemId, autocompletValues: []};
|
||||
activeItems.push(activeItem);
|
||||
}
|
||||
activeItem.autocompletValues.push(queryElem.autocompleteValue);
|
||||
} else if (!activeItem) {
|
||||
activeItem = {searchItemId};
|
||||
activeItems.push(activeItem);
|
||||
}
|
||||
}
|
||||
for (const activeItem of activeItems) {
|
||||
if ("intervalIds" in activeItem) {
|
||||
activeItem.intervalIds.sort(
|
||||
(g1, g2) => rankInterval(g1) - rankInterval(g2)
|
||||
);
|
||||
}
|
||||
}
|
||||
groups.push({id, activeItems});
|
||||
}
|
||||
|
||||
return groups;
|
||||
},
|
||||
deactivateGroup(groupId) {
|
||||
this.query = this.query.filter((queryElem) => {
|
||||
return queryElem.groupId !== groupId;
|
||||
});
|
||||
|
||||
for (const partName in this.domainParts) {
|
||||
const part = this.domainParts[partName];
|
||||
if (part.groupId === groupId) {
|
||||
this.setDomainParts({[partName]: null});
|
||||
}
|
||||
}
|
||||
this._checkComparisonStatus();
|
||||
this._notify();
|
||||
},
|
||||
});
|
Loading…
Reference in New Issue