diff --git a/web_selection_autocomplete/.eslintrc.json b/web_selection_autocomplete/.eslintrc.json new file mode 100644 index 00000000..5c03cc2c --- /dev/null +++ b/web_selection_autocomplete/.eslintrc.json @@ -0,0 +1,291 @@ +{ + "globals": { + "$": false, + "_": false, + "fuzzy": false, + "jQuery": false, + "moment": false, + "odoo": false, + "openerp": false, + "self": false + }, + "env": { + "browser": true + }, + "rules": { + "no-alert": "error", + "no-array-constructor": "error", + "no-bitwise": "off", + "no-caller": "error", + "no-case-declarations": "error", + "no-catch-shadow": "error", + "no-class-assign": "error", + "no-cond-assign": "error", + "no-confusing-arrow": "error", + "no-console": "off", + "no-const-assign": "error", + "no-constant-condition": "error", + "no-continue": "off", + "no-control-regex": "error", + "no-debugger": "error", + "no-delete-var": "error", + "no-div-regex": "error", + "no-dupe-args": "error", + "no-dupe-class-members": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-duplicate-imports": "error", + "no-else-return": "error", + "no-empty": "error", + "no-empty-character-class": "error", + "no-empty-function": "error", + "no-empty-pattern": "error", + "no-eq-null": "error", + "no-eval": "error", + "no-ex-assign": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-extra-boolean-cast": "error", + "no-extra-label": "error", + "no-extra-parens": ["error", "all", { + "nestedBinaryExpressions": false + }], + "no-extra-semi": "error", + "no-fallthrough": "error", + "no-floating-decimal": "error", + "no-func-assign": "error", + "no-implicit-coercion": ["error", { + "allow": ["~"] + }], + "no-implicit-globals": "error", + "no-implied-eval": "error", + "no-inline-comments": "error", + "no-inner-declarations": "error", + "no-invalid-regexp": "error", + "no-invalid-this": "off", + "no-irregular-whitespace": "error", + "no-iterator": "error", + "no-label-var": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-lonely-if": "error", + "no-loop-func": "off", + "no-magic-numbers": "off", + "no-mixed-operators": "error", + "no-mixed-requires": "error", + "no-mixed-spaces-and-tabs": "error", + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-multiple-empty-lines": "error", + "no-native-reassign": "error", + "no-negated-condition": "error", + "no-negated-in-lhs": "error", + "no-nested-ternary": "off", + "no-new": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-new-require": "error", + "no-new-symbol": "error", + "no-new-wrappers": "error", + "no-obj-calls": "error", + "no-octal": "error", + "no-octal-escape": "error", + "no-param-reassign": "error", + "no-path-concat": "error", + "no-plusplus": "off", + "no-process-env": "error", + "no-process-exit": "error", + "no-proto": "error", + "no-prototype-builtins": "error", + "no-redeclare": "error", + "no-regex-spaces": "error", + "no-restricted-globals": "error", + "no-restricted-imports": "error", + "no-restricted-modules": "error", + "no-restricted-syntax": "error", + "no-return-assign": "error", + "no-script-url": "error", + "no-self-assign": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow": "error", + "no-shadow-restricted-names": "error", + "no-whitespace-before-property": "error", + "no-spaced-func": "error", + "no-sparse-arrays": "error", + "no-sync": "error", + "no-tabs": "error", + "no-ternary": "off", + "no-trailing-spaces": "error", + "no-this-before-super": "error", + "no-throw-literal": "error", + "no-undef": "error", + "no-undef-init": "error", + "no-undefined": "off", + "no-unexpected-multiline": "error", + "no-underscore-dangle": "off", + "no-unmodified-loop-condition": "error", + "no-unneeded-ternary": "error", + "no-unreachable": "error", + "no-unsafe-finally": "error", + "no-unused-expressions": "error", + "no-unused-labels": "error", + "no-unused-vars": "error", + "no-use-before-define": "error", + "no-useless-call": "error", + "no-useless-computed-key": "error", + "no-useless-concat": "error", + "no-useless-constructor": "error", + "no-useless-escape": "error", + "no-useless-rename": "error", + "no-void": "error", + "no-var": "off", + "no-warning-comments": "off", + "no-with": "error", + "array-bracket-spacing": "off", + "array-callback-return": "error", + "arrow-body-style": "error", + "arrow-parens": "error", + "arrow-spacing": "off", + "accessor-pairs": "error", + "block-scoped-var": "off", + "block-spacing": ["error", "always"], + "brace-style": "error", + "callback-return": "error", + "camelcase": "off", + "capitalized-comments": ["error", "always", { + "ignoreConsecutiveComments": true, + "ignoreInlineComments": true + }], + "comma-dangle": ["error", "always-multiline"], + "comma-spacing": ["error", { + "before": false, + "after": true + }], + "comma-style": "error", + "complexity": [ + "error", + 15 + ], + "computed-property-spacing": "off", + "consistent-return": "off", + "consistent-this": "off", + "constructor-super": "error", + "curly": "error", + "default-case": "off", + "dot-location": ["error", "property"], + "dot-notation": "error", + "eol-last": "error", + "eqeqeq": "error", + "func-names": "off", + "func-style": "off", + "generator-star-spacing": "off", + "global-require": "error", + "guard-for-in": "off", + "handle-callback-err": "error", + "id-blacklist": "error", + "id-length": "off", + "id-match": "error", + "indent": "error", + "init-declarations": "error", + "jsx-quotes": "error", + "key-spacing": "off", + "keyword-spacing": "error", + "linebreak-style": [ + "error", + "unix" + ], + "lines-around-comment": "error", + "max-depth": "error", + "max-len": ["error", { + "code": 80, + "ignorePattern": "odoo\\.define\\(", + "tabWidth": 4 + }], + "max-lines": "off", + "max-nested-callbacks": "error", + "max-params": "off", + "max-statements": "off", + "max-statements-per-line": "error", + "multiline-ternary": "off", + "new-cap": "off", + "new-parens": "error", + "newline-after-var": "off", + "newline-before-return": "off", + "newline-per-chained-call": "off", + "object-curly-newline": ["error", { "consistent": true }], + "object-curly-spacing": ["error", "never"], + "object-property-newline": ["error", { + "allowAllPropertiesOnSameLine": true + }], + "object-shorthand": "off", + "one-var": "off", + "one-var-declaration-per-line": "off", + "operator-assignment": "error", + "operator-linebreak": "error", + "padded-blocks": "off", + "prefer-arrow-callback": "off", + "prefer-const": "error", + "prefer-reflect": "off", + "prefer-rest-params": "off", + "prefer-spread": "off", + "prefer-template": "off", + "quote-props": "off", + "quotes": "off", + "radix": "error", + "require-yield": "error", + "rest-spread-spacing": "off", + "semi": [ + "error", + "always" + ], + "semi-spacing": "error", + "sort-imports": "error", + "sort-vars": "off", + "space-before-blocks": "error", + "space-before-function-paren": "error", + "space-in-parens": "off", + "space-infix-ops": "off", + "space-unary-ops": "off", + "spaced-comment": ["error", "always"], + "strict": ["error", "function"], + "template-curly-spacing": "off", + "unicode-bom": "error", + "use-isnan": "error", + "valid-jsdoc": ["error", { + "prefer": { + "arg": "param", + "argument": "param", + "augments": "extends", + "constructor": "class", + "exception": "throws", + "func": "function", + "method": "function", + "prop": "property", + "return": "returns", + "virtual": "abstract", + "yield": "yields" + }, + "preferType": { + "array": "Array", + "bool": "Boolean", + "boolean": "Boolean", + "number": "Number", + "object": "Object", + "str": "String", + "string": "String" + }, + "requireParamDescription": false, + "requireReturn": false, + "requireReturnDescription": false, + "requireReturnType": false + }], + "valid-typeof": "error", + "vars-on-top": "off", + "wrap-iife": "error", + "wrap-regex": "error", + "yield-star-spacing": "off", + "yoda": "error" + }, + "parserOptions": {} +} diff --git a/web_selection_autocomplete/README.rst b/web_selection_autocomplete/README.rst new file mode 100644 index 00000000..ba16eab8 --- /dev/null +++ b/web_selection_autocomplete/README.rst @@ -0,0 +1,89 @@ +========================== +Web Selection Autocomplete +========================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :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/12.0/web_selection_autocomplete + :alt: OCA/web +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/web-12-0/web-12-0-web_selection_autocomplete + :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/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Add the widget 'selection_autocomplete' which make selection field ui +more similar to the many2one's, allowing to filter the selection values. + +The most advantageous case is when: + - there are a lot of selection values + - new model not needed but still want the many2one field ui + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +No configuration needed. + +Usage +===== + +The only thing to do is to add the widget 'selection_autocomplete' +to your selection field. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* LevelPrime srl + +Contributors +~~~~~~~~~~~~ + +* Michele Zaccheddu + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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 `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/web_selection_autocomplete/__init__.py b/web_selection_autocomplete/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/web_selection_autocomplete/__manifest__.py b/web_selection_autocomplete/__manifest__.py new file mode 100644 index 00000000..baa17ae6 --- /dev/null +++ b/web_selection_autocomplete/__manifest__.py @@ -0,0 +1,29 @@ +# Copyright 2019 LevelPrime srl +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': "Web Selection Autocomplete", + 'summary': """ + Add the widget 'selection_autocomplete' which make selection field ui + more similar to the many2one's, allowing to filter the selection values. + + The most advantageous case is when: + - there are a lot of selection values + - new model not needed but still want the many2one field ui + """, + 'author': "LevelPrime srl, Odoo Community Association (OCA)", + 'website': "https://github.com/OCA/web", + 'license': 'AGPL-3', + 'development_status': 'Beta', + 'category': 'Web', + 'version': '12.0.1.0.0', + 'depends': ['base', 'web'], + 'data': [ + 'static/src/xml/assets.xml', + ], + 'qweb': [ + 'static/src/xml/template.xml' + ], + 'application': False, + 'installable': True +} diff --git a/web_selection_autocomplete/readme/CONFIGURE.rst b/web_selection_autocomplete/readme/CONFIGURE.rst new file mode 100644 index 00000000..05dcf870 --- /dev/null +++ b/web_selection_autocomplete/readme/CONFIGURE.rst @@ -0,0 +1 @@ +No configuration needed. diff --git a/web_selection_autocomplete/readme/CONTRIBUTORS.rst b/web_selection_autocomplete/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..9f7da1ff --- /dev/null +++ b/web_selection_autocomplete/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Michele Zaccheddu diff --git a/web_selection_autocomplete/readme/DESCRIPTION.rst b/web_selection_autocomplete/readme/DESCRIPTION.rst new file mode 100644 index 00000000..7320dd6f --- /dev/null +++ b/web_selection_autocomplete/readme/DESCRIPTION.rst @@ -0,0 +1,6 @@ +Add the widget 'selection_autocomplete' which make selection field ui +more similar to the many2one's, allowing to filter the selection values. + +The most advantageous case is when: + - there are a lot of selection values + - new model not needed but still want the many2one field ui diff --git a/web_selection_autocomplete/readme/USAGE.rst b/web_selection_autocomplete/readme/USAGE.rst new file mode 100644 index 00000000..4ca1bad2 --- /dev/null +++ b/web_selection_autocomplete/readme/USAGE.rst @@ -0,0 +1,2 @@ +The only thing to do is to add the widget 'selection_autocomplete' +to your selection field. diff --git a/web_selection_autocomplete/static/description/index.html b/web_selection_autocomplete/static/description/index.html new file mode 100644 index 00000000..fc81b109 --- /dev/null +++ b/web_selection_autocomplete/static/description/index.html @@ -0,0 +1,439 @@ + + + + + + +Web Selection Autocomplete + + + +
+

Web Selection Autocomplete

+ + +

Beta License: AGPL-3 OCA/web Translate me on Weblate Try me on Runbot

+

Add the widget ‘selection_autocomplete’ which make selection field ui +more similar to the many2one’s, allowing to filter the selection values.

+
+
The most advantageous case is when:
+
    +
  • there are a lot of selection values
  • +
  • new model not needed but still want the many2one field ui
  • +
+
+
+

Table of contents

+ +
+

Configuration

+

No configuration needed.

+
+
+

Usage

+

The only thing to do is to add the widget ‘selection_autocomplete’ +to your selection field.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub 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.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • LevelPrime srl
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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 project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/web_selection_autocomplete/static/src/js/web_selection_autocomplete.js b/web_selection_autocomplete/static/src/js/web_selection_autocomplete.js new file mode 100644 index 00000000..14e1d0d8 --- /dev/null +++ b/web_selection_autocomplete/static/src/js/web_selection_autocomplete.js @@ -0,0 +1,105 @@ +odoo.define('web_selection_autocomplete.autocomplete', function (require) { + 'use strict'; + + var registry = require('web.field_registry'); + var SelectionField = require('web.relational_fields').FieldSelection; + + registry.add( + 'selection_autocomplete', + SelectionField.extend({ + template: 'SelectionAutocomplete', + specialData: null, + supportedFieldTypes: ['selection'], + _renderEdit: function () { + // Set value on internal property and on dom element + if (this.value) { + var value = this.get_sel_string(this.value) || this.value; + this.$el.val(value); + this.value = value; + } + + var self = this; + if (!this.is_initialized()) { + this.$el.autocomplete({ + source: _.flatten( + _.map(this.values, _.last)), + minLength: 0, + close: function (e) { + // Needed in some cases, + // eg. blur event with tab key click + // while focus on autocomplete values + // which set the focused value on the input element + // but does not trigger the 'change' event. + if (e.target.value) { + self._onChange(e); + } + }, + }); + } + + }, + _renderReadonly: function () { + this.$el.text(this.get_sel_string(this.value)); + }, + _onChange: function () { + this._setValue(arguments[0].target.value); + }, + getFocusableElement: function () { + return this.$el.is('input') ? this.$el : $(); + }, + _setValue: function (value, options) { + this._isValid = this.check_validity(value); + + if (value) { + this.value = this.get_sel_value(value); + + + var def = $.Deferred(); + var changes = {}; + changes[this.name] = this.value; + + this.trigger_up('field_changed', { + dataPointID: this.dataPointID, + changes: changes, + viewType: this.viewType, + doNotSetDirty: options && options.doNotSetDirty, + notifyChange: !options || + options.notifyChange !== false, + allowWarning: options && options.allowWarning, + onSuccess: def.resolve.bind(def), + onFailure: def.reject.bind(def), + }); + return def; + } + return $.when(); + }, + is_initialized: function () { + return this.$el.hasClass('ui-autocomplete-input'); + }, + check_validity: function (val) { + var isValid = this.is_selection_valid(val); + this.$el.parent().toggleClass( + 'o_selection_autocomplete_invalid', + !isValid); + + return isValid; + }, + is_selection_valid: function (val) { + return !_.isEmpty(_.find(this.values, function (v) { + return v[1] === val; + })); + }, + get_sel_string: function (value) { + return this._get_value(0, 1, value); + }, + get_sel_value: function (value) { + return this._get_value(1, 0, value); + }, + _get_value: function (i, j, value) { + var match = _.find(this.values, function (v) { + return v[i] === value; + }); + return match ? match[j] : null; + }, + })); +}); diff --git a/web_selection_autocomplete/static/src/scss/web_selection_autocomplete.scss b/web_selection_autocomplete/static/src/scss/web_selection_autocomplete.scss new file mode 100644 index 00000000..15b64bc8 --- /dev/null +++ b/web_selection_autocomplete/static/src/scss/web_selection_autocomplete.scss @@ -0,0 +1,9 @@ +.o_selection_autocomplete_invalid { + &::before { + color: #DF382C !important; + content: 'Wrong value. Insert one of the available options.' !important; + } + input { + border-color: #DF382C !important; + } +} diff --git a/web_selection_autocomplete/static/src/xml/assets.xml b/web_selection_autocomplete/static/src/xml/assets.xml new file mode 100644 index 00000000..c383ab8f --- /dev/null +++ b/web_selection_autocomplete/static/src/xml/assets.xml @@ -0,0 +1,9 @@ + + +