From 8db11abbf66792db49e8a2802bea0370dfc0e297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20D=2E=20D=C3=ADaz?= Date: Sun, 5 Nov 2023 19:47:12 +0100 Subject: [PATCH] imp: dynamic command options --- src/css/terminal.css | 10 ++++ src/js/page/odoo/commands/backoffice/lang.mjs | 49 ++++++++---------- .../odoo/commands/backoffice/settings.mjs | 27 +++++----- src/js/page/odoo/commands/backoffice/view.mjs | 27 +++++----- src/js/page/odoo/commands/common/caf.mjs | 27 +++++----- src/js/page/odoo/commands/common/call.mjs | 27 +++++----- src/js/page/odoo/commands/common/cam.mjs | 27 +++++----- src/js/page/odoo/commands/common/count.mjs | 27 +++++----- src/js/page/odoo/commands/common/create.mjs | 27 +++++----- src/js/page/odoo/commands/common/depends.mjs | 27 +++++----- src/js/page/odoo/commands/common/install.mjs | 27 +++++----- src/js/page/odoo/commands/common/jstest.mjs | 27 +++++----- src/js/page/odoo/commands/common/login.mjs | 39 ++++++--------- src/js/page/odoo/commands/common/metadata.mjs | 27 +++++----- src/js/page/odoo/commands/common/read.mjs | 26 +++++----- src/js/page/odoo/commands/common/search.mjs | 26 +++++----- src/js/page/odoo/commands/common/uhg.mjs | 27 +++++----- .../page/odoo/commands/common/uninstall.mjs | 27 +++++----- src/js/page/odoo/commands/common/unlink.mjs | 27 +++++----- src/js/page/odoo/commands/common/upgrade.mjs | 27 +++++----- src/js/page/odoo/commands/common/write.mjs | 27 +++++----- .../page/odoo/utils/cached_call_service.mjs | 29 +++++++++++ src/js/page/odoo/utils/cached_search_read.mjs | 30 +++++++++++ src/js/page/terminal/commands/help.mjs | 10 ++-- .../page/terminal/core/command_assistant.mjs | 50 ++++++++++++------- src/js/page/terminal/core/screen.mjs | 19 ++++++- .../templates/screen_assistant_panel.mjs | 1 + src/js/page/terminal/terminal.mjs | 7 ++- 28 files changed, 378 insertions(+), 350 deletions(-) create mode 100644 src/js/page/odoo/utils/cached_call_service.mjs create mode 100644 src/js/page/odoo/utils/cached_search_read.mjs diff --git a/src/css/terminal.css b/src/css/terminal.css index ae194f81..20b29cbb 100644 --- a/src/css/terminal.css +++ b/src/css/terminal.css @@ -154,6 +154,14 @@ background-color: var(--terminal-screen-assistant-desc-background-color); } +.o_terminal div#terminal_assistant > span#terminal_assistant_args_info { + position: absolute; + bottom: 0; + right: 10px; + border-radius: 2px 2px 0 0; + background-color: #878787; +} + .o_terminal .terminal-user-input { background-color: var(--terminal-screen-background-color); border: 1px dotted #5a5a5a; @@ -257,6 +265,8 @@ color: var(--terminal-screen-extra-info-color); } +/** COMMAND ASSISTANT **/ + /** HELP COMMAND **/ .o_terminal .terminal-info-section { margin-left: 2em; diff --git a/src/js/page/odoo/commands/backoffice/lang.mjs b/src/js/page/odoo/commands/backoffice/lang.mjs index 63cf6f5d..e89b80f6 100644 --- a/src/js/page/odoo/commands/backoffice/lang.mjs +++ b/src/js/page/odoo/commands/backoffice/lang.mjs @@ -7,6 +7,7 @@ import searchRead from '@odoo/orm/search_read'; import callModelMulti from '@odoo/osv/call_model_multi'; import callModel from '@odoo/osv/call_model'; import getContent from '@odoo/utils/get_content'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import file2base64 from '@terminal/utils/file2base64'; import isEmpty from '@terminal/utils/is_empty'; import {ARG} from '@trash/constants'; @@ -146,37 +147,29 @@ async function cmdLang(kwargs, screen) { throw new Error('Invalid operation!'); } -const cache = { - modules: [], - langs: [], -}; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'module') { - if (!arg_value) { - const records = await searchRead( - 'ir.module.module', - [], - ['name'], - this.getContext(), - ); - cache.modules = records.map(item => item.name); - return cache.modules; - } - return cache.modules.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.module.module_active', + 'ir.module.module', + [], + ['name'], + this.getContext({active_test: true}), + null, + item => item.name, + ); } else if (arg_name === 'lang') { - if (!arg_value) { - const records = await searchRead( - 'res.lang', - [['active', '=', true]], - ['code'], - this.getContext(), - ); - cache.langs = records.map(item => item.code); - return cache.langs; - } - return cache.langs.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_res.lang_active', + 'res.lang', + [], + ['code'], + this.getContext({active_test: true}), + null, + item => item.code, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/backoffice/settings.mjs b/src/js/page/odoo/commands/backoffice/settings.mjs index 108a07fb..4de3e3fd 100644 --- a/src/js/page/odoo/commands/backoffice/settings.mjs +++ b/src/js/page/odoo/commands/backoffice/settings.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import doAction from '@odoo/base/do_action'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; async function cmdOpenSettings(kwargs) { @@ -18,22 +18,19 @@ async function cmdOpenSettings(kwargs) { this.doHide(); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'module') { - if (!arg_value) { - const records = await searchRead( - 'ir.module.module', - [], - ['name'], - this.getContext(), - ); - cache = records.map(item => item.name); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.module.module_active', + 'ir.module.module', + [], + ['name'], + this.getContext({active_test: true}), + null, + item => item.name, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/backoffice/view.mjs b/src/js/page/odoo/commands/backoffice/view.mjs index 2fb6f539..57fa0387 100644 --- a/src/js/page/odoo/commands/backoffice/view.mjs +++ b/src/js/page/odoo/commands/backoffice/view.mjs @@ -5,7 +5,7 @@ import doAction from '@odoo/base/do_action'; import getParentAdapter from '@odoo/utils/get_parent_adapter'; import getOdooService from '@odoo/utils/get_odoo_service'; import getOdooVersionMajor from '@odoo/utils/get_odoo_version_major'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; function openSelectCreateDialog(model, title, domain, on_selected) { @@ -71,22 +71,19 @@ async function cmdViewModelRecord(kwargs) { ); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/caf.mjs b/src/js/page/odoo/commands/common/caf.mjs index a1d7452f..7b7df3be 100644 --- a/src/js/page/odoo/commands/common/caf.mjs +++ b/src/js/page/odoo/commands/common/caf.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import callModel from '@odoo/osv/call_model'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import isEmpty from '@terminal/utils/is_empty'; import {ARG} from '@trash/constants'; @@ -70,22 +70,19 @@ async function cmdCheckFieldAccess(kwargs, screen) { return s_result; } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/call.mjs b/src/js/page/odoo/commands/common/call.mjs index 753c5936..2cfb3990 100644 --- a/src/js/page/odoo/commands/common/call.mjs +++ b/src/js/page/odoo/commands/common/call.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import rpcQuery from '@odoo/rpc'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; async function cmdCallModelMethod(kwargs, screen) { @@ -21,22 +21,19 @@ async function cmdCallModelMethod(kwargs, screen) { }); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/cam.mjs b/src/js/page/odoo/commands/common/cam.mjs index 2de7be24..16e7b810 100644 --- a/src/js/page/odoo/commands/common/cam.mjs +++ b/src/js/page/odoo/commands/common/cam.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import callModel from '@odoo/osv/call_model'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; async function cmdCheckModelAccess(kwargs, screen) { @@ -24,22 +24,19 @@ async function cmdCheckModelAccess(kwargs, screen) { }); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/count.mjs b/src/js/page/odoo/commands/common/count.mjs index da836efd..c33e02e4 100644 --- a/src/js/page/odoo/commands/common/count.mjs +++ b/src/js/page/odoo/commands/common/count.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import searchCount from '@odoo/orm/search_count'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; async function cmdCount(kwargs, screen) { @@ -14,22 +14,19 @@ async function cmdCount(kwargs, screen) { ); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/create.mjs b/src/js/page/odoo/commands/common/create.mjs index 4858f52b..fb2e95c4 100644 --- a/src/js/page/odoo/commands/common/create.mjs +++ b/src/js/page/odoo/commands/common/create.mjs @@ -3,7 +3,7 @@ import doAction from '@odoo/base/do_action'; import createRecord from '@odoo/orm/create_record'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import Recordset from '@terminal/core/recordset'; import renderRecordCreated from '@odoo/templates/record_created'; import {ARG} from '@trash/constants'; @@ -39,22 +39,19 @@ async function cmdCreateModelRecord(kwargs, screen) { return Recordset.make(kwargs.model, records); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/depends.mjs b/src/js/page/odoo/commands/common/depends.mjs index 8201c7ba..be82dfa3 100644 --- a/src/js/page/odoo/commands/common/depends.mjs +++ b/src/js/page/odoo/commands/common/depends.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import callModel from '@odoo/osv/call_model'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import getOdooVersionMajor from '@odoo/utils/get_odoo_version_major'; import isEmpty from '@terminal/utils/is_empty'; import {ARG} from '@trash/constants'; @@ -37,22 +37,19 @@ async function cmdModuleDepends(kwargs, screen) { }); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'module') { - if (!arg_value) { - const records = await searchRead( - 'ir.module.module', - [], - ['name'], - this.getContext(), - ); - cache = records.map(item => item.name); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.module.module_active', + 'ir.module.module', + [], + ['name'], + this.getContext({active_test: true}), + null, + item => item.name, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/install.mjs b/src/js/page/odoo/commands/common/install.mjs index 935ce927..c06d9072 100644 --- a/src/js/page/odoo/commands/common/install.mjs +++ b/src/js/page/odoo/commands/common/install.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import callModelMulti from '@odoo/osv/call_model_multi'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; import {searchModules} from './__utils__'; @@ -39,22 +39,19 @@ async function cmdInstallModule(kwargs, screen) { }); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'module') { - if (!arg_value) { - const records = await searchRead( - 'ir.module.module', - [], - ['name'], - this.getContext(), - ); - cache = records.map(item => item.name); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.module.module', + 'ir.module.module', + [], + ['name'], + this.getContext(), + null, + item => item.name, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/jstest.mjs b/src/js/page/odoo/commands/common/jstest.mjs index 3a59a641..1ff85ea8 100644 --- a/src/js/page/odoo/commands/common/jstest.mjs +++ b/src/js/page/odoo/commands/common/jstest.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import {ARG} from '@trash/constants'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; async function cmdJSTest(kwargs) { let mod = kwargs.module || ''; @@ -17,22 +17,19 @@ async function cmdJSTest(kwargs) { window.location = url; } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'module') { - if (!arg_value) { - const records = await searchRead( - 'ir.module.module', - [], - ['name'], - this.getContext(), - ); - cache = records.map(item => item.name); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.module.module_active', + 'ir.module.module', + [], + ['name'], + this.getContext({active_test: true}), + null, + item => item.name, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/login.mjs b/src/js/page/odoo/commands/common/login.mjs index e9610fbc..89a4bd23 100644 --- a/src/js/page/odoo/commands/common/login.mjs +++ b/src/js/page/odoo/commands/common/login.mjs @@ -2,8 +2,8 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import getOdooSession from '@odoo/utils/get_odoo_session'; -import callService from '@odoo/osv/call_service'; -import searchRead from '@odoo/orm/search_read'; +import cachedCallService from '@odoo/utils/cached_call_service'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; async function cmdLoginAs(kwargs, screen) { @@ -35,32 +35,21 @@ async function cmdLoginAs(kwargs, screen) { return res; } -const cache = { - databases: [], - users: [], -}; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'database') { - if (!arg_value) { - const records = await callService('db', 'list', {}); - cache.databases = records; - return cache.databases; - } - return cache.databases.filter(item => item.startsWith(arg_value)); + return cachedCallService('options_db_list', 'db', 'list', {}); } else if (arg_name === 'user') { - if (!arg_value) { - const records = await searchRead( - 'res.users', - [['active', '=', true]], - ['login'], - this.getContext(), - ); - cache.users = records.map(item => item.login); - return cache.users; - } - return cache.users.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_res.users_active', + 'res.users', + [], + ['login'], + this.getContext({active_test: true}), + null, + item => item.name, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/metadata.mjs b/src/js/page/odoo/commands/common/metadata.mjs index dd47693c..4af39e13 100644 --- a/src/js/page/odoo/commands/common/metadata.mjs +++ b/src/js/page/odoo/commands/common/metadata.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import callModelMulti from '@odoo/osv/call_model_multi'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import renderMetadata from '@odoo/templates/metadata'; import {ARG} from '@trash/constants'; @@ -26,22 +26,19 @@ async function cmdMetadata(kwargs, screen) { return metadata; } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/read.mjs b/src/js/page/odoo/commands/common/read.mjs index da2731a1..f6767937 100644 --- a/src/js/page/odoo/commands/common/read.mjs +++ b/src/js/page/odoo/commands/common/read.mjs @@ -3,6 +3,7 @@ import callModel from '@odoo/osv/call_model'; import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import Recordset from '@terminal/core/recordset'; import {ARG} from '@trash/constants'; @@ -50,22 +51,19 @@ async function cmdSearchModelRecordId(kwargs, screen) { return recordset; } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/search.mjs b/src/js/page/odoo/commands/common/search.mjs index 64241b76..7ab0cf5b 100644 --- a/src/js/page/odoo/commands/common/search.mjs +++ b/src/js/page/odoo/commands/common/search.mjs @@ -3,6 +3,7 @@ import searchRead from '@odoo/orm/search_read'; import getFieldsInfo from '@odoo/orm/get_fields_info'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {default as Recordset} from '@terminal/core/recordset'; import {ARG} from '@trash/constants'; @@ -110,22 +111,19 @@ async function cmdSearchModelRecord(kwargs, screen, meta) { return recordset; } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/uhg.mjs b/src/js/page/odoo/commands/common/uhg.mjs index 5dcd24ac..7f37aaa5 100644 --- a/src/js/page/odoo/commands/common/uhg.mjs +++ b/src/js/page/odoo/commands/common/uhg.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import callModel from '@odoo/osv/call_model'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; async function cmdUserHasGroups(kwargs, screen) { @@ -18,22 +18,19 @@ async function cmdUserHasGroups(kwargs, screen) { }); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'group') { - if (!arg_value) { - const records = await searchRead( - 'ir.model.data', - [['model', '=', 'res.groups']], - ['name', 'module'], - this.getContext(), - ); - cache = records.map(item => `${item.module}.${item.name}`); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model.data_res.groups_active', + 'ir.model.data', + [['model', '=', 'res.groups']], + ['name', 'module'], + this.getContext({active_test: true}), + null, + item => `${item.module}.${item.name}`, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/uninstall.mjs b/src/js/page/odoo/commands/common/uninstall.mjs index 117c7ec9..786e8f14 100644 --- a/src/js/page/odoo/commands/common/uninstall.mjs +++ b/src/js/page/odoo/commands/common/uninstall.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import callModelMulti from '@odoo/osv/call_model_multi'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import isEmpty from '@terminal/utils/is_empty'; import {ARG} from '@trash/constants'; import {searchModules} from './__utils__'; @@ -52,22 +52,19 @@ async function cmdUninstallModule(kwargs, screen) { throw new Error(`'${kwargs.module}' module doesn't exists`); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'module') { - if (!arg_value) { - const records = await searchRead( - 'ir.module.module', - [], - ['name'], - this.getContext(), - ); - cache = records.map(item => item.name); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.module.module_active', + 'ir.module.module', + [], + ['name'], + this.getContext({active_test: true}), + null, + item => item.name, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/unlink.mjs b/src/js/page/odoo/commands/common/unlink.mjs index 3ba5f5bb..a03b9511 100644 --- a/src/js/page/odoo/commands/common/unlink.mjs +++ b/src/js/page/odoo/commands/common/unlink.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import unlinkRecord from '@odoo/orm/unlink_record'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; async function cmdUnlinkModelRecord(kwargs, screen) { @@ -14,22 +14,19 @@ async function cmdUnlinkModelRecord(kwargs, screen) { ); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/upgrade.mjs b/src/js/page/odoo/commands/common/upgrade.mjs index 8913e69e..ee0c9915 100644 --- a/src/js/page/odoo/commands/common/upgrade.mjs +++ b/src/js/page/odoo/commands/common/upgrade.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import callModelMulti from '@odoo/osv/call_model_multi'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; import {searchModules} from './__utils__'; @@ -39,22 +39,19 @@ async function cmdUpgradeModule(kwargs, screen) { }); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'module') { - if (!arg_value) { - const records = await searchRead( - 'ir.module.module', - [], - ['name'], - this.getContext(), - ); - cache = records.map(item => item.name); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.module.module_active', + 'ir.module.module', + [], + ['name'], + this.getContext({active_test: true}), + null, + item => item.name, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/commands/common/write.mjs b/src/js/page/odoo/commands/common/write.mjs index 74c3631b..6366306f 100644 --- a/src/js/page/odoo/commands/common/write.mjs +++ b/src/js/page/odoo/commands/common/write.mjs @@ -2,7 +2,7 @@ // License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import writeRecord from '@odoo/orm/write_record'; -import searchRead from '@odoo/orm/search_read'; +import cachedSearchRead from '@odoo/utils/cached_search_read'; import {ARG} from '@trash/constants'; async function cmdWriteModelRecord(kwargs, screen) { @@ -17,22 +17,19 @@ async function cmdWriteModelRecord(kwargs, screen) { }); } -let cache = []; -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'model') { - if (!arg_value) { - const records = await searchRead( - 'ir.model', - [], - ['model'], - this.getContext(), - ); - cache = records.map(item => item.model); - return cache; - } - return cache.filter(item => item.startsWith(arg_value)); + return cachedSearchRead( + 'options_ir.model_active', + 'ir.model', + [], + ['model'], + this.getContext({active_test: true}), + null, + item => item.model, + ); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/odoo/utils/cached_call_service.mjs b/src/js/page/odoo/utils/cached_call_service.mjs new file mode 100644 index 00000000..9ffb5840 --- /dev/null +++ b/src/js/page/odoo/utils/cached_call_service.mjs @@ -0,0 +1,29 @@ +// Copyright Alexandre Díaz +// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import callService from '@odoo/osv/call_service'; + +const cache = {}; +export default async function ( + cache_name, + service, + method, + args, + options, + map_func, +) { + if (options?.force || typeof cache[cache_name] === 'undefined') { + let values = []; + try { + values = await callService(service, method, args); + } catch (e) { + // Do nothing + } + if (map_func) { + cache[cache_name] = values.map(map_func); + } else { + cache[cache_name] = values; + } + } + return cache[cache_name]; +} diff --git a/src/js/page/odoo/utils/cached_search_read.mjs b/src/js/page/odoo/utils/cached_search_read.mjs new file mode 100644 index 00000000..3b2e3b4e --- /dev/null +++ b/src/js/page/odoo/utils/cached_search_read.mjs @@ -0,0 +1,30 @@ +// Copyright Alexandre Díaz +// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import searchRead from '@odoo/orm/search_read'; + +const cache = {}; +export default async function ( + cache_name, + model, + domain, + fields, + context, + options, + map_func, +) { + if (options?.force || typeof cache[cache_name] === 'undefined') { + let records = []; + try { + records = await searchRead(model, domain, fields, context, options); + } catch (e) { + // Do nothing + } + if (map_func) { + cache[cache_name] = records.map(map_func); + } else { + cache[cache_name] = records; + } + } + return cache[cache_name]; +} diff --git a/src/js/page/terminal/commands/help.mjs b/src/js/page/terminal/commands/help.mjs index 599585f2..58b1b367 100644 --- a/src/js/page/terminal/commands/help.mjs +++ b/src/js/page/terminal/commands/help.mjs @@ -73,15 +73,11 @@ function cmdPrintHelp(kwargs, screen) { } } -async function getOptions(arg_name, arg_info, arg_value) { +function getOptions(arg_name) { if (arg_name === 'cmd') { - const command_names = Object.keys(this.virtMachine.commands); - if (arg_value) { - return command_names.filter(item => item.startsWith(arg_value)); - } - return command_names; + return Promise.resolve(Object.keys(this.virtMachine.commands)); } - return []; + return Promise.resolve([]); } export default { diff --git a/src/js/page/terminal/core/command_assistant.mjs b/src/js/page/terminal/core/command_assistant.mjs index 1a5ff691..45ec3e27 100644 --- a/src/js/page/terminal/core/command_assistant.mjs +++ b/src/js/page/terminal/core/command_assistant.mjs @@ -29,14 +29,16 @@ export default class CommandAssistant { arg_infos.push(arg_info); } } - return arg_infos; + return [arg_infos, command_info.args.length]; } #getAvailableParameters(command_info, arg_name, arg_value) { const arg_info = getArgumentInfoByName(command_info.args, arg_name); const res_param_infos = []; + let total_count = 0; if (arg_info) { if (arg_info.strict_values) { + total_count = arg_info.strict_values.length; const def_value = arg_info.default_value; for (const strict_value of arg_info.strict_values) { if (!arg_value || String(strict_value).startsWith(arg_value)) { @@ -54,6 +56,7 @@ export default class CommandAssistant { arg_info.default_value && String(arg_info.default_value).startsWith(arg_value) ) { + total_count = 1; res_param_infos.push({ value: arg_info.default_value, is_default: true, @@ -65,7 +68,15 @@ export default class CommandAssistant { } } - return res_param_infos; + return [res_param_infos, total_count]; + } + + #filterParameterOptions(values, filter_by) { + let res = values || []; + if (filter_by) { + res = values.filter(item => item.startsWith(filter_by)); + } + return res.slice(0, MAX_OPTIONS); } async #getAvailableDynamicParameters(command_info, arg_name, arg_value) { @@ -73,15 +84,12 @@ export default class CommandAssistant { if (!arg_info) { return []; } - let options = - (await command_info.options.bind(this.#parent)( - arg_info.names.long, - arg_info, - arg_value, - )) || []; - options = options.slice(0, MAX_OPTIONS); + const options = + (await command_info.options.bind(this.#parent)(arg_info.names.long)) || + []; + const options_filtered = this.#filterParameterOptions(options, arg_value); const ret = []; - for (const option of options) { + for (const option of options_filtered) { ret.push({ value: option, is_default: false, @@ -91,7 +99,7 @@ export default class CommandAssistant { values: options, }); } - return ret; + return [ret, options.length]; } getSelectedParameterIndex(parse_info, caret_pos) { @@ -186,12 +194,12 @@ export default class CommandAssistant { } async getAvailableOptions(data, caret_pos) { - const ret = []; const input_info = this.getInputInfo(data, caret_pos); if (isEmpty(input_info)) { - return []; + return [[], 0]; } if (input_info.index.cmd === input_info.index.current) { + const ret = []; // Command name const cmd_names = this.#getAvailableCommandNames( input_info.token.cmd || data, @@ -204,19 +212,20 @@ export default class CommandAssistant { description: this.#virtMachine.commands[cmd_name].definition, }); } - return ret; + return [ret, Object.keys(this.#virtMachine.commands).length]; } const command_info = input_info.token.cmd ? this.#virtMachine.commands[input_info.token.cmd] : undefined; if (!command_info) { - return []; + return [[], 0]; } if (input_info.index.current === input_info.index.arg) { + const ret = []; // Argument - const arg_infos = this.#getAvailableArguments( + const [arg_infos, total_count] = this.#getAvailableArguments( command_info, input_info.token.arg, ); @@ -231,19 +240,21 @@ export default class CommandAssistant { values: arg_info.strict_values, }); } + return [ret, total_count]; } else if ( input_info.index.current !== input_info.index.cmd && input_info.index.current - 1 === input_info.index.arg && input_info.token.arg ) { + const ret = []; // Parameter - let param_infos = this.#getAvailableParameters( + let [param_infos, total_count] = this.#getAvailableParameters( command_info, input_info.token.arg, input_info.token.current, ); if (isEmpty(param_infos)) { - param_infos = await this.#getAvailableDynamicParameters( + [param_infos, total_count] = await this.#getAvailableDynamicParameters( command_info, input_info.token.arg, input_info.token.current, @@ -261,8 +272,9 @@ export default class CommandAssistant { values: param_info.strict_values, }); } + return [ret, total_count]; } - return ret; + return [[], 0]; } } diff --git a/src/js/page/terminal/core/screen.mjs b/src/js/page/terminal/core/screen.mjs index e48f94b1..e87cd3fd 100644 --- a/src/js/page/terminal/core/screen.mjs +++ b/src/js/page/terminal/core/screen.mjs @@ -137,7 +137,7 @@ export default class Screen { } this.#$input.val(''); this.cleanShadowInput(); - this.updateAssistantPanelOptions([], -1); + this.updateAssistantPanelOptions([], -1, 0); } cleanShadowInput() { @@ -182,13 +182,18 @@ export default class Screen { }, 1); } - updateAssistantPanelOptions(options, selected_option_index) { + updateAssistantPanelOptions( + options, + selected_option_index, + total_options_count, + ) { if (!this.#wasStart) { return; } if (typeof this.#question_active !== 'undefined') { this.$assistant_args.html(''); + this.$assistant_args_info.html(''); this.$assistant_desc.html(''); return; } @@ -202,6 +207,13 @@ export default class Screen { ); } this.$assistant_args.html(renderAssistantArgOptionList(html_options)); + if (total_options_count === 0) { + this.$assistant_args_info.html(''); + } else { + this.$assistant_args_info.text( + `${options.length} of ${total_options_count}`, + ); + } if (selected_option_index !== -1 || options.length === 1) { const opt = @@ -548,6 +560,9 @@ export default class Screen { #createAssistantPanel() { this.$assistant = $(renderAssistantPanel()); this.$assistant_args = this.$assistant.find('#terminal_assistant_args'); + this.$assistant_args_info = this.$assistant.find( + '#terminal_assistant_args_info', + ); this.$assistant_desc = this.$assistant.find('#terminal_assistant_desc'); this.$assistant.appendTo(this.#$container); } diff --git a/src/js/page/terminal/templates/screen_assistant_panel.mjs b/src/js/page/terminal/templates/screen_assistant_panel.mjs index ca32f72a..36ef2152 100644 --- a/src/js/page/terminal/templates/screen_assistant_panel.mjs +++ b/src/js/page/terminal/templates/screen_assistant_panel.mjs @@ -9,5 +9,6 @@ export default function () {
+ `; } diff --git a/src/js/page/terminal/terminal.mjs b/src/js/page/terminal/terminal.mjs index 4b9a62ce..ddf846f4 100644 --- a/src/js/page/terminal/terminal.mjs +++ b/src/js/page/terminal/terminal.mjs @@ -45,6 +45,7 @@ export default class Terminal { #commandAssistant = null; #assistantOptions = {}; + #assistantOptionsTotalCount = 0; #selAssistanOption = -1; #messageListeners = {}; @@ -609,12 +610,15 @@ export default class Terminal { this.screen.getInputCaretStartPos(), ); }) - .then(options => { + .then(result => { + const [options, total_count] = result; this.#selAssistanOption = -1; this.#assistantOptions = options; + this.#assistantOptionsTotalCount = total_count; this.screen.updateAssistantPanelOptions( this.#assistantOptions, this.#selAssistanOption, + this.#assistantOptionsTotalCount, ); }); } @@ -800,6 +804,7 @@ export default class Terminal { this.screen.updateAssistantPanelOptions( this.#assistantOptions, this.#selAssistanOption, + this.#assistantOptionsTotalCount, ); }