diff --git a/dms_field/README.rst b/dms_field/README.rst
index f3ca007ae..8ade0e6de 100644
--- a/dms_field/README.rst
+++ b/dms_field/README.rst
@@ -7,7 +7,7 @@ DMS Field
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- !! source digest: sha256:923426d186000e2da1d7e32f4ba6b770234a94e4f930f56fdbece369f3729153
+ !! source digest: sha256:ed7854681f73bbc617938529c1da77fcf81cba2bf46a8ae9387d8f20b360a53b
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
@@ -17,13 +17,13 @@ DMS Field
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fdms-lightgray.png?logo=github
- :target: https://github.com/OCA/dms/tree/15.0/dms_field
+ :target: https://github.com/OCA/dms/tree/16.0/dms_field
:alt: OCA/dms
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/dms-15-0/dms-15-0-dms_field
+ :target: https://translation.odoo-community.org/projects/dms-16-0/dms-16-0-dms_field
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
- :target: https://runboat.odoo-community.org/builds?repo=OCA/dms&target_branch=15.0
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/dms&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -65,7 +65,7 @@ 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 to smash it by providing a detailed and welcomed
-`feedback `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -101,6 +101,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/dms `_ project on GitHub.
+This module is part of the `OCA/dms `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/dms_field/__manifest__.py b/dms_field/__manifest__.py
index 6dc6d6d9b..75947d518 100644
--- a/dms_field/__manifest__.py
+++ b/dms_field/__manifest__.py
@@ -5,7 +5,7 @@
"name": "DMS Field",
"summary": """
Create DMS View and allow to use them inside a record""",
- "version": "15.0.1.2.1",
+ "version": "16.0.1.0.0",
"license": "LGPL-3",
"author": "Creu Blanca,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/dms",
@@ -19,11 +19,14 @@
],
"assets": {
"web.assets_backend": [
- "dms_field/static/src/js/**/*",
- "dms_field/static/src/scss/**/*",
+ "dms_field/static/src/**/*",
+ ("remove", "dms_field/static/src/views/fields/x2many/x2many_field.xml"),
+ (
+ "after",
+ "/web/static/src/views/fields/x2many/x2many_field.xml",
+ "dms_field/static/src/views/fields/x2many/x2many_field.xml",
+ ),
],
- "web.assets_qweb": ["dms_field/static/src/xml/**/*"],
},
- "qweb": ["static/src/xml/*.xml"],
"demo": ["demo/partner_dms.xml"],
}
diff --git a/dms_field/demo/partner_dms.xml b/dms_field/demo/partner_dms.xml
index 6114a6605..2faa85980 100644
--- a/dms_field/demo/partner_dms.xml
+++ b/dms_field/demo/partner_dms.xml
@@ -11,7 +11,7 @@
string="DMS"
attrs="{'invisible': [('id', '=', False)]}"
>
-
+
diff --git a/dms_field/i18n/dms_field.pot b/dms_field/i18n/dms_field.pot
index e2147d89d..2e1cb5526 100644
--- a/dms_field/i18n/dms_field.pot
+++ b/dms_field/i18n/dms_field.pot
@@ -4,8 +4,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 15.0\n"
+"Project-Id-Version: Odoo Server 16.0+e\n"
"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2024-06-04 08:09+0000\n"
+"PO-Revision-Date: 2024-06-04 08:09+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -14,10 +16,10 @@ msgstr ""
"Plural-Forms: \n"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
-msgid "Action Buttons"
+msgid "A file with the same name already exists"
msgstr ""
#. module: dms_field
@@ -26,42 +28,43 @@ msgid "Action Window View"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Actions"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Add Directory: "
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Add File: "
msgstr ""
#. module: dms_field
-#: code:addons/dms_field/models/dms_field_template.py:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
-msgid "Autogenerate group from %(model)s (%(name)s)"
+msgid "An error occurred during the upload"
msgstr ""
#. module: dms_field
-#: model:ir.model,name:dms_field.model_base
-msgid "Base"
+#. odoo-python
+#: code:addons/dms_field/models/dms_field_template.py:0
+#, python-format
+msgid "Autogenerate group from %(model)s (%(name)s) #%(id)s"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Close the selected node"
+#: model:ir.model,name:dms_field.model_base
+msgid "Base"
msgstr ""
#. module: dms_field
@@ -70,29 +73,15 @@ msgid "Company"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Context Menu"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/controls.xml:0
-#, python-format
-msgid "Create"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Create File"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Create directory"
msgstr ""
@@ -108,17 +97,14 @@ msgid "Created on"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Cut"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_view.js:0
#: model_terms:ir.ui.view,arch_db:dms_field.view_partner_form
-#, python-format
msgid "DMS"
msgstr ""
@@ -151,20 +137,21 @@ msgstr ""
#: model:ir.model.fields,field_description:dms_field.field_base_language_export__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_language_import__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_language_install__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_base_module_install_request__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_base_module_install_review__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_module_uninstall__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_module_update__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_module_upgrade__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_partner_merge_automatic_wizard__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_partner_merge_line__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_base_update_translations__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_bus_bus__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_bus_presence__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_change_password_own__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_change_password_user__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_change_password_wizard__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_decimal_precision__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_dms_category__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_dms_classification_template__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_dms_directory__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_dms_file__dms_directory_ids
@@ -174,18 +161,10 @@ msgstr ""
#: model:ir.model.fields,field_description:dms_field.field_dms_tag__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_fetchmail_server__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_format_address_mixin__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_department__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_departure_reason__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_departure_wizard__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_employee__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_employee_base__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_employee_category__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_employee_public__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_job__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_plan__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_plan_activity_type__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_plan_wizard__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_work_location__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_google_gmail_mixin__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_iap_account__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_iap_autocomplete_api__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_iap_enrich_api__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_image_mixin__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_url__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_window__dms_directory_ids
@@ -199,6 +178,7 @@ msgstr ""
#: model:ir.model.fields,field_description:dms_field.field_ir_asset__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_attachment__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_autovacuum__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_ir_binary__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_config_parameter__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_cron__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_cron_trigger__dms_directory_ids
@@ -246,14 +226,15 @@ msgstr ""
#: model:ir.model.fields,field_description:dms_field.field_ir_qweb_field_relative__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_qweb_field_selection__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_qweb_field_text__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_ir_qweb_field_time__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_rule__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_sequence__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_sequence_date_range__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_server_object_lines__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_ir_translation__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_menu__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_view__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_view_custom__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_ir_websocket__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_activity__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_activity_mixin__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_activity_type__dms_directory_ids
@@ -263,25 +244,28 @@ msgstr ""
#: model:ir.model.fields,field_description:dms_field.field_mail_blacklist_remove__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_bot__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_channel__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_mail_channel_partner__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_mail_channel_member__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_channel_rtc_session__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_compose_message__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_composer_mixin__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_followers__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_mail_gateway_allowed__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_guest__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_ice_server__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_mail_link_preview__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_mail__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_message__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_message_reaction__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_mail_message_schedule__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_message_subtype__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_notification__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_render_mixin__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_mail_resend_cancel__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_resend_message__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_resend_partner__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_shortcode__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_template__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_template_preview__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_mail_template_reset__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_thread__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_thread_blacklist__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_thread_cc__dms_directory_ids
@@ -294,6 +278,9 @@ msgstr ""
#: model:ir.model.fields,field_description:dms_field.field_portal_share__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_portal_wizard__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_portal_wizard_user__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_privacy_log__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_privacy_lookup_wizard__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_privacy_lookup_wizard_line__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_publisher_warranty_contract__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_report_base_report_irmodulereference__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_report_layout__dms_directory_ids
@@ -311,6 +298,7 @@ msgstr ""
#: model:ir.model.fields,field_description:dms_field.field_res_groups__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_lang__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_partner__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_res_partner_autocomplete_sync__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_partner_bank__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_partner_category__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_partner_industry__dms_directory_ids
@@ -319,42 +307,47 @@ msgstr ""
#: model:ir.model.fields,field_description:dms_field.field_res_users_apikeys__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_apikeys_description__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_apikeys_show__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_res_users_deletion__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_identitycheck__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_log__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_settings__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_settings_volumes__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_reset_view_arch_wizard__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_calendar__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_calendar_attendance__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_calendar_leaves__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_mixin__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_resource__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_test__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_api__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_composer__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_resend__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_resend_recipient__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_sms__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_template__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_template_preview__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_template_reset__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_snailmail_confirm__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_snailmail_letter__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_snailmail_letter_format_error__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_snailmail_letter_missing_required_fields__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_template_reset_mixin__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_web_editor_assets__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_web_editor_converter_test_sub__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_web_tour_tour__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_wizard_dms_classification__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_wizard_dms_classification_detail__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_wizard_dms_file_move__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_wizard_ir_model_menu_create__dms_directory_ids
msgid "DMS Directories"
msgstr ""
#. module: dms_field
-#: model:ir.model.fields.selection,name:dms_field.selection__ir_actions_act_window_view__view_mode__dms_tree
-#: model:ir.model.fields.selection,name:dms_field.selection__ir_ui_view__type__dms_tree
+#: model:ir.model.fields.selection,name:dms_field.selection__ir_actions_act_window_view__view_mode__dms_list
+#: model:ir.model.fields.selection,name:dms_field.selection__ir_ui_view__type__dms_list
msgid "DMS Tree"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
-#: code:addons/dms_field/static/src/xml/controls.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Delete"
msgstr ""
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_directory.py:0
#, python-format
msgid "Directories of this storage must be related to a record"
@@ -366,6 +359,7 @@ msgid "Directory"
msgstr ""
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_directory.py:0
#, python-format
msgid "Directory %s must be root in order to be related to a record"
@@ -394,45 +388,16 @@ msgid "Documents"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Download"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Drag and Drop"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "END"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/controls.xml:0
-#, python-format
-msgid "Edit"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Edit the selected node"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Elements:"
msgstr ""
@@ -443,21 +408,14 @@ msgstr ""
msgid "Embedded DMS templates"
msgstr ""
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "F2"
-msgstr ""
-
#. module: dms_field
#: model:ir.model.fields,field_description:dms_field.field_dms_storage__field_template_ids
msgid "File templated ids"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Files:"
msgstr ""
@@ -467,39 +425,11 @@ msgstr ""
msgid "Groups"
msgstr ""
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "HOME"
-msgstr ""
-
#. module: dms_field
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__id
msgid "ID"
msgstr ""
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Jump to the bottom"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Jump to the top"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Keyboard Shortcuts"
-msgstr ""
-
#. module: dms_field
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template____last_update
msgid "Last Modified on"
@@ -526,17 +456,10 @@ msgid "Model name"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Move down one node"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
+#. odoo-python
+#: code:addons/dms_field/models/ir_ui_view.py:0
#, python-format
-msgid "Move up one node"
+msgid "Model not found: %(model)s"
msgstr ""
#. module: dms_field
@@ -545,31 +468,16 @@ msgid "Name"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
-#: code:addons/dms_field/static/src/xml/controls.xml:0
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Open"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Open all nodes"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Open the selected node"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_controller.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Open: "
msgstr ""
@@ -580,42 +488,36 @@ msgid "Parent Directory"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Paste"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/controls.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
-msgid "Refresh"
+msgid "Preview"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Rename"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/controls.xml:0
-#, python-format
-msgid "Show Help"
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/preview.xml:0
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Size:"
msgstr ""
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_storage.py:0
#, python-format
msgid "Some directories are inconsistent with the storage models"
@@ -628,40 +530,42 @@ msgid "Storage"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Subdirectories:"
msgstr ""
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
+#. odoo-python
+#: code:addons/dms_field/models/dms_storage.py:0
#, python-format
-msgid ""
-"The action button at the top of the view can be used to open,\n"
-" create, edit or delete a node."
+msgid "There are directories not associated to a record"
msgstr ""
#. module: dms_field
-#: code:addons/dms_field/models/dms_storage.py:0
+#. odoo-python
+#: code:addons/dms_field/models/dms_field_template.py:0
#, python-format
-msgid "There are directories not associated to a record"
+msgid "There is already a linked directory created."
msgstr ""
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_field_template.py:0
#, python-format
-msgid "There is already a linked directory created."
+msgid "There is already a template created for this model."
msgstr ""
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_field_template.py:0
#, python-format
msgid "There is no template linked to this model"
msgstr ""
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_directory.py:0
#, python-format
msgid "This record is already related in this storage"
@@ -683,25 +587,6 @@ msgstr ""
msgid "View Type"
msgstr ""
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid ""
-"You can change the structure by moving nodes. It is also possible\n"
-" to create new nodes by dragging files and even entire folder\n"
-" structures on the view."
-msgstr ""
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid ""
-"You can open a context menu by right-clicking on any node. This\n"
-" contains further options for interacting with the node."
-msgstr ""
-
#. module: dms_field
#: model:ir.model.fields,help:dms_field.field_dms_field_template__directory_format_name
msgid ""
diff --git a/dms_field/i18n/es.po b/dms_field/i18n/es.po
index 19f85c747..b46a89ac2 100644
--- a/dms_field/i18n/es.po
+++ b/dms_field/i18n/es.po
@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-02-07 15:56+0000\n"
-"PO-Revision-Date: 2024-03-23 09:34+0000\n"
+"POT-Creation-Date: 2024-06-04 08:09+0000\n"
+"PO-Revision-Date: 2024-06-04 10:11+0200\n"
"Last-Translator: Ivorra78 \n"
"Language-Team: none\n"
"Language: es\n"
@@ -15,14 +15,14 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.17\n"
+"X-Generator: Poedit 3.0.1\n"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
-msgid "Action Buttons"
-msgstr "Botones de acción"
+msgid "A file with the same name already exists"
+msgstr "Ya existe un archivo con el mismo nombre"
#. module: dms_field
#: model:ir.model,name:dms_field.model_ir_actions_act_window_view
@@ -30,73 +30,60 @@ msgid "Action Window View"
msgstr "Vista de la ventana de acción"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Actions"
msgstr "Acciones"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Add Directory: "
msgstr "Añadir directorio: "
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Add File: "
msgstr "Agregar archivo: "
#. module: dms_field
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
+#, python-format
+msgid "An error occurred during the upload"
+msgstr "Se ha producido un error durante la carga"
+
+#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_field_template.py:0
#, python-format
-msgid "Autogenerate group from %(model)s (%(name)s)"
-msgstr "Grupo autogenerado desde %(model)s (%(name)s)"
+msgid "Autogenerate group from %(model)s (%(name)s) #%(id)s"
+msgstr "Grupo autogenerado desde %(model)s (%(name)s) #%(id)s"
#. module: dms_field
#: model:ir.model,name:dms_field.model_base
msgid "Base"
msgstr "Base/Fuente"
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Close the selected node"
-msgstr "Cerrar el nodo seleccionado"
-
#. module: dms_field
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__company_id
msgid "Company"
msgstr "Compañía"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Context Menu"
-msgstr "Menú contextual"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/controls.xml:0
-#, python-format
-msgid "Create"
-msgstr "Crear"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Create File"
msgstr "Crear archivo"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Create directory"
msgstr "Crear directorio"
@@ -112,17 +99,14 @@ msgid "Created on"
msgstr "Creado el"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Cut"
msgstr "Cortar"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_view.js:0
#: model_terms:ir.ui.view,arch_db:dms_field.view_partner_form
-#, python-format
msgid "DMS"
msgstr "DMS"
@@ -155,20 +139,21 @@ msgstr "DMS"
#: model:ir.model.fields,field_description:dms_field.field_base_language_export__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_language_import__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_language_install__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_base_module_install_request__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_base_module_install_review__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_module_uninstall__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_module_update__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_module_upgrade__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_partner_merge_automatic_wizard__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_base_partner_merge_line__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_base_update_translations__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_bus_bus__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_bus_presence__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_change_password_own__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_change_password_user__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_change_password_wizard__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_decimal_precision__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_dms_category__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_dms_classification_template__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_dms_directory__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_dms_file__dms_directory_ids
@@ -178,18 +163,10 @@ msgstr "DMS"
#: model:ir.model.fields,field_description:dms_field.field_dms_tag__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_fetchmail_server__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_format_address_mixin__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_department__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_departure_reason__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_departure_wizard__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_employee__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_employee_base__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_employee_category__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_employee_public__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_job__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_plan__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_plan_activity_type__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_plan_wizard__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_hr_work_location__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_google_gmail_mixin__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_iap_account__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_iap_autocomplete_api__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_iap_enrich_api__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_image_mixin__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_url__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_window__dms_directory_ids
@@ -203,6 +180,7 @@ msgstr "DMS"
#: model:ir.model.fields,field_description:dms_field.field_ir_asset__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_attachment__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_autovacuum__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_ir_binary__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_config_parameter__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_cron__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_cron_trigger__dms_directory_ids
@@ -250,14 +228,15 @@ msgstr "DMS"
#: model:ir.model.fields,field_description:dms_field.field_ir_qweb_field_relative__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_qweb_field_selection__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_qweb_field_text__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_ir_qweb_field_time__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_rule__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_sequence__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_sequence_date_range__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_server_object_lines__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_ir_translation__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_menu__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_view__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_view_custom__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_ir_websocket__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_activity__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_activity_mixin__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_activity_type__dms_directory_ids
@@ -267,25 +246,28 @@ msgstr "DMS"
#: model:ir.model.fields,field_description:dms_field.field_mail_blacklist_remove__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_bot__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_channel__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_mail_channel_partner__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_mail_channel_member__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_channel_rtc_session__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_compose_message__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_composer_mixin__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_followers__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_mail_gateway_allowed__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_guest__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_ice_server__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_mail_link_preview__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_mail__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_message__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_message_reaction__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_mail_message_schedule__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_message_subtype__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_notification__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_render_mixin__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_mail_resend_cancel__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_resend_message__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_resend_partner__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_shortcode__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_template__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_template_preview__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_mail_template_reset__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_thread__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_thread_blacklist__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_mail_thread_cc__dms_directory_ids
@@ -298,6 +280,9 @@ msgstr "DMS"
#: model:ir.model.fields,field_description:dms_field.field_portal_share__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_portal_wizard__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_portal_wizard_user__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_privacy_log__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_privacy_lookup_wizard__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_privacy_lookup_wizard_line__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_publisher_warranty_contract__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_report_base_report_irmodulereference__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_report_layout__dms_directory_ids
@@ -315,6 +300,7 @@ msgstr "DMS"
#: model:ir.model.fields,field_description:dms_field.field_res_groups__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_lang__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_partner__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_res_partner_autocomplete_sync__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_partner_bank__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_partner_category__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_partner_industry__dms_directory_ids
@@ -323,42 +309,47 @@ msgstr "DMS"
#: model:ir.model.fields,field_description:dms_field.field_res_users_apikeys__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_apikeys_description__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_apikeys_show__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_res_users_deletion__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_identitycheck__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_log__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_settings__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_res_users_settings_volumes__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_reset_view_arch_wizard__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_calendar__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_calendar_attendance__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_calendar_leaves__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_mixin__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_resource__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_resource_test__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_api__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_composer__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_resend__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_resend_recipient__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_sms__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_template__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_template_preview__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_sms_template_reset__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_snailmail_confirm__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_snailmail_letter__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_snailmail_letter_format_error__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_snailmail_letter_missing_required_fields__dms_directory_ids
+#: model:ir.model.fields,field_description:dms_field.field_template_reset_mixin__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_web_editor_assets__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_web_editor_converter_test_sub__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_web_tour_tour__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_wizard_dms_classification__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_wizard_dms_classification_detail__dms_directory_ids
-#: model:ir.model.fields,field_description:dms_field.field_wizard_dms_file_move__dms_directory_ids
#: model:ir.model.fields,field_description:dms_field.field_wizard_ir_model_menu_create__dms_directory_ids
msgid "DMS Directories"
msgstr "Directorios DMS"
#. module: dms_field
-#: model:ir.model.fields.selection,name:dms_field.selection__ir_actions_act_window_view__view_mode__dms_tree
-#: model:ir.model.fields.selection,name:dms_field.selection__ir_ui_view__type__dms_tree
+#: model:ir.model.fields.selection,name:dms_field.selection__ir_actions_act_window_view__view_mode__dms_list
+#: model:ir.model.fields.selection,name:dms_field.selection__ir_ui_view__type__dms_list
msgid "DMS Tree"
msgstr "Árbol DMS"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
-#: code:addons/dms_field/static/src/xml/controls.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Delete"
msgstr "Borrar"
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_directory.py:0
#, python-format
msgid "Directories of this storage must be related to a record"
@@ -372,6 +363,7 @@ msgid "Directory"
msgstr "Directorio"
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_directory.py:0
#, python-format
msgid "Directory %s must be root in order to be related to a record"
@@ -402,44 +394,16 @@ msgid "Documents"
msgstr "Documentos"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Download"
msgstr "Descargar"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Drag and Drop"
-msgstr "Arrastrar y soltar"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "END"
-msgstr "FIN"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/controls.xml:0
-#, python-format
-msgid "Edit"
-msgstr "Editar"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Edit the selected node"
-msgstr "Editar el nodo seleccionado"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Elements:"
msgstr "Elementos:"
@@ -450,21 +414,14 @@ msgstr "Elementos:"
msgid "Embedded DMS templates"
msgstr "Plantillas DMS embebidas"
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "F2"
-msgstr "F2"
-
#. module: dms_field
#: model:ir.model.fields,field_description:dms_field.field_dms_storage__field_template_ids
msgid "File templated ids"
msgstr "Fichero de identificadores plantillas"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Files:"
msgstr "Archivos:"
@@ -474,39 +431,11 @@ msgstr "Archivos:"
msgid "Groups"
msgstr "Grupos"
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "HOME"
-msgstr "CASA"
-
#. module: dms_field
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__id
msgid "ID"
msgstr "ID (identificación)"
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Jump to the bottom"
-msgstr "Saltar a la parte inferior"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Jump to the top"
-msgstr "Saltar a la parte superior"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Keyboard Shortcuts"
-msgstr "Métodos abreviados de teclado"
-
#. module: dms_field
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template____last_update
msgid "Last Modified on"
@@ -533,18 +462,11 @@ msgid "Model name"
msgstr "Nombre de modelo"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
+#. odoo-python
+#: code:addons/dms_field/models/ir_ui_view.py:0
#, python-format
-msgid "Move down one node"
-msgstr "Desplazarse un nodo hacia abajo"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Move up one node"
-msgstr "Desplazarse un nodo hacia arriba"
+msgid "Model not found: %(model)s"
+msgstr "Modelo no encontrado: %(model)s"
#. module: dms_field
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__name
@@ -552,31 +474,16 @@ msgid "Name"
msgstr "Nombre"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
-#: code:addons/dms_field/static/src/xml/controls.xml:0
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Open"
msgstr "Abrir"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Open all nodes"
-msgstr "Abrir todos los nodos"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid "Open the selected node"
-msgstr "Abrir el nodo seleccionado"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_controller.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Open: "
msgstr "Abrir "
@@ -587,41 +494,35 @@ msgid "Parent Directory"
msgstr "Directorio parental"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Paste"
msgstr "Pegar"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/controls.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
-msgid "Refresh"
-msgstr "Actualizar"
+msgid "Preview"
+msgstr "Previsualizar"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
#, python-format
msgid "Rename"
msgstr "Renombrar"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/controls.xml:0
-#, python-format
-msgid "Show Help"
-msgstr "Mostrar ayuda"
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Size:"
msgstr "Tamaño:"
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_storage.py:0
#, python-format
msgid "Some directories are inconsistent with the storage models"
@@ -636,43 +537,42 @@ msgid "Storage"
msgstr "Almacenamiento"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/preview.xml:0
+#. odoo-javascript
+#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
#, python-format
msgid "Subdirectories:"
msgstr "Subdirectorios:"
#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid ""
-"The action button at the top of the view can be used to open,\n"
-" create, edit or delete a node."
-msgstr ""
-"El botón de acción en la parte superior de la vista se puede utilizar para "
-"abrir,\n"
-" crear, editar o eliminar un nodo."
-
-#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_storage.py:0
#, python-format
msgid "There are directories not associated to a record"
msgstr "Hay directorios no asociados a un registro"
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_field_template.py:0
#, python-format
msgid "There is already a linked directory created."
msgstr "Ya hay un directorio creado relacionado."
#. module: dms_field
+#. odoo-python
+#: code:addons/dms_field/models/dms_field_template.py:0
+#, python-format
+msgid "There is already a template created for this model."
+msgstr "Ya hay una plantilla creada para este modelo."
+
+#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_field_template.py:0
#, python-format
msgid "There is no template linked to this model"
msgstr "No hay plantilla vinculada a este modelo"
#. module: dms_field
+#. odoo-python
#: code:addons/dms_field/models/dms_directory.py:0
#, python-format
msgid "This record is already related in this storage"
@@ -694,34 +594,6 @@ msgstr "Vista"
msgid "View Type"
msgstr "Tipo de vista"
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid ""
-"You can change the structure by moving nodes. It is also possible\n"
-" to create new nodes by dragging files and even "
-"entire folder\n"
-" structures on the view."
-msgstr ""
-"Puede cambiar la estructura moviendo nodos. También es posible\n"
-" crear nuevos nodos arrastrando archivos e incluso "
-"estructuras de carpetas\n"
-" completas en la vista."
-
-#. module: dms_field
-#. openerp-web
-#: code:addons/dms_field/static/src/xml/dialogs.xml:0
-#, python-format
-msgid ""
-"You can open a context menu by right-clicking on any node. This\n"
-" contains further options for interacting with the "
-"node."
-msgstr ""
-"Puede abrir un menú contextual haciendo clic con el botón derecho en "
-"cualquier nodo. Este\n"
-" contiene más opciones para interactuar con el nodo."
-
#. module: dms_field
#: model:ir.model.fields,help:dms_field.field_dms_field_template__directory_format_name
msgid ""
@@ -730,3 +602,111 @@ msgid ""
msgstr ""
"Puede utilizar expresiones para definir el nombre del directorio,\n"
"\tejemplo: {{object.name}}"
+
+#, python-format
+#~ msgid "Action Buttons"
+#~ msgstr "Botones de acción"
+
+#, python-format
+#~ msgid "Close the selected node"
+#~ msgstr "Cerrar el nodo seleccionado"
+
+#, python-format
+#~ msgid "Context Menu"
+#~ msgstr "Menú contextual"
+
+#, python-format
+#~ msgid "Create"
+#~ msgstr "Crear"
+
+#, python-format
+#~ msgid "Drag and Drop"
+#~ msgstr "Arrastrar y soltar"
+
+#, python-format
+#~ msgid "END"
+#~ msgstr "FIN"
+
+#, python-format
+#~ msgid "Edit"
+#~ msgstr "Editar"
+
+#, python-format
+#~ msgid "Edit the selected node"
+#~ msgstr "Editar el nodo seleccionado"
+
+#, python-format
+#~ msgid "F2"
+#~ msgstr "F2"
+
+#, python-format
+#~ msgid "HOME"
+#~ msgstr "CASA"
+
+#, python-format
+#~ msgid "Jump to the bottom"
+#~ msgstr "Saltar a la parte inferior"
+
+#, python-format
+#~ msgid "Jump to the top"
+#~ msgstr "Saltar a la parte superior"
+
+#, python-format
+#~ msgid "Keyboard Shortcuts"
+#~ msgstr "Métodos abreviados de teclado"
+
+#, python-format
+#~ msgid "Move down one node"
+#~ msgstr "Desplazarse un nodo hacia abajo"
+
+#, python-format
+#~ msgid "Move up one node"
+#~ msgstr "Desplazarse un nodo hacia arriba"
+
+#, python-format
+#~ msgid "Open all nodes"
+#~ msgstr "Abrir todos los nodos"
+
+#, python-format
+#~ msgid "Open the selected node"
+#~ msgstr "Abrir el nodo seleccionado"
+
+#, python-format
+#~ msgid "Refresh"
+#~ msgstr "Actualizar"
+
+#, python-format
+#~ msgid "Show Help"
+#~ msgstr "Mostrar ayuda"
+
+#, python-format
+#~ msgid ""
+#~ "The action button at the top of the view can be used to open,\n"
+#~ " create, edit or delete a node."
+#~ msgstr ""
+#~ "El botón de acción en la parte superior de la vista se puede utilizar "
+#~ "para abrir,\n"
+#~ " crear, editar o eliminar un nodo."
+
+#, python-format
+#~ msgid ""
+#~ "You can change the structure by moving nodes. It is also possible\n"
+#~ " to create new nodes by dragging files and even "
+#~ "entire folder\n"
+#~ " structures on the view."
+#~ msgstr ""
+#~ "Puede cambiar la estructura moviendo nodos. También es posible\n"
+#~ " crear nuevos nodos arrastrando archivos e incluso "
+#~ "estructuras de carpetas\n"
+#~ " completas en la vista."
+
+#, python-format
+#~ msgid ""
+#~ "You can open a context menu by right-clicking on any node. This\n"
+#~ " contains further options for interacting with the "
+#~ "node."
+#~ msgstr ""
+#~ "Puede abrir un menú contextual haciendo clic con el botón derecho en "
+#~ "cualquier nodo. Este\n"
+#~ " contiene más opciones para interactuar con el "
+#~ "nodo."
diff --git a/dms_field/models/__init__.py b/dms_field/models/__init__.py
index 1467298e3..6827de274 100644
--- a/dms_field/models/__init__.py
+++ b/dms_field/models/__init__.py
@@ -1,6 +1,7 @@
+from . import dms_field_mixin
from . import ir_actions_act_window_view
from . import ir_ui_view
from . import dms_storage
from . import dms_directory
from . import dms_field_template
-from . import base
+from . import res_partner
diff --git a/dms_field/models/base.py b/dms_field/models/dms_field_mixin.py
similarity index 94%
rename from dms_field/models/base.py
rename to dms_field/models/dms_field_mixin.py
index a754c37e1..2d311a193 100644
--- a/dms_field/models/base.py
+++ b/dms_field/models/dms_field_mixin.py
@@ -5,8 +5,8 @@
from odoo import api, fields, models
-class Base(models.AbstractModel):
- _inherit = "base"
+class DMSFieldMixin(models.AbstractModel):
+ _name = "dms.field.mixin"
dms_directory_ids = fields.One2many(
"dms.directory",
diff --git a/dms_field/models/dms_field_template.py b/dms_field/models/dms_field_template.py
index 1093c4400..3c570c3da 100644
--- a/dms_field/models/dms_field_template.py
+++ b/dms_field/models/dms_field_template.py
@@ -1,11 +1,12 @@
# Copyright 2024 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
-from odoo.exceptions import ValidationError
+from odoo.exceptions import UserError, ValidationError
class DmsFieldTemplate(models.Model):
_name = "dms.field.template"
+ _inherit = "dms.field.mixin"
_description = "Dms Field Template"
name = fields.Char(required=True)
@@ -72,7 +73,7 @@ def create_dms_directory(self):
"group_ids": record.group_ids.ids,
}
)
- template = self._get_template_from_model(res_model)
+ template = self._get_template_from_model(res_model).sudo()
if not template:
raise ValidationError(_("There is no template linked to this model"))
total_directories = directory_model.search_count(
@@ -86,13 +87,13 @@ def create_dms_directory(self):
raise ValidationError(_("There is already a linked directory created."))
# Create root directory + files
dms_directory_ids = template.dms_directory_ids
- directory = directory_model.create(
+ new_directory = directory_model.create(
template._prepare_directory_vals(dms_directory_ids, record)
)
- self._copy_files_from_directory(dms_directory_ids, directory)
+ self._copy_files_from_directory(dms_directory_ids, new_directory)
# Create child directories
- self._create_child_directories(directory, dms_directory_ids)
- return directory
+ self._create_child_directories(new_directory, dms_directory_ids)
+ return new_directory
def _copy_files_from_directory(self, directory, new_directory):
for file in directory.file_ids:
@@ -101,9 +102,10 @@ def _copy_files_from_directory(self, directory, new_directory):
def _set_groups_from_directory(self, directory, record):
groups = self.env["dms.access.group"]
for group in directory.group_ids:
- group_name = _("Autogenerate group from %(model)s (%(name)s)") % {
+ group_name = _("Autogenerate group from %(model)s (%(name)s) #%(id)s") % {
"model": record._description,
"name": record.display_name,
+ "id": record.id,
}
new_group = group.copy({"name": group_name, "directory_ids": False})
# Apply sudo() because the user may not have permissions to access
@@ -146,3 +148,13 @@ def _prepare_directory_vals(self, directory, record):
"name": directory_name,
"group_ids": [(4, group.id) for group in groups],
}
+
+ @api.constrains("model_id")
+ def _check_model_id(self):
+ for template in self:
+ if self.env["dms.field.template"].search(
+ [("model_id", "=", template.model_id.id), ("id", "!=", template.id)]
+ ):
+ raise UserError(
+ _("There is already a template created for this model.")
+ )
diff --git a/dms_field/models/ir_actions_act_window_view.py b/dms_field/models/ir_actions_act_window_view.py
index 1282c2d12..8d86a780e 100644
--- a/dms_field/models/ir_actions_act_window_view.py
+++ b/dms_field/models/ir_actions_act_window_view.py
@@ -9,5 +9,5 @@ class IrActionsActWindowView(models.Model):
_inherit = "ir.actions.act_window.view"
view_mode = fields.Selection(
- selection_add=[("dms_tree", "DMS Tree")], ondelete={"dms_tree": "cascade"}
+ selection_add=[("dms_list", "DMS Tree")], ondelete={"dms_list": "cascade"}
)
diff --git a/dms_field/models/ir_ui_view.py b/dms_field/models/ir_ui_view.py
index 786a8dace..a7a9e15b8 100644
--- a/dms_field/models/ir_ui_view.py
+++ b/dms_field/models/ir_ui_view.py
@@ -1,11 +1,38 @@
# Copyright 2020 Creu Blanca
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
-from odoo import fields, models
+from odoo import _, fields, models
+
+from odoo.addons.base.models.ir_ui_view import NameManager
class IrUiView(models.Model):
_inherit = "ir.ui.view"
- type = fields.Selection(selection_add=[("dms_tree", "DMS Tree")])
+ type = fields.Selection(selection_add=[("dms_list", "DMS Tree")])
+
+ def _postprocess_tag_dms_list(self, node, name_manager, node_info):
+ parent = node.getparent()
+ if parent_name := parent and parent.get("name"):
+ field = name_manager.model._fields.get(parent_name)
+ if field:
+ model_name = field.comodel_name
+ if model_name not in self.env:
+ self._raise_view_error(
+ _("Model not found: %(model)s", model=model_name), node
+ )
+ model = self.env[model_name]
+ new_name_manager = NameManager(model, parent=name_manager)
+ root_info = {
+ "view_type": node.tag,
+ "view_editable": self._editable_node(node, name_manager),
+ "view_modifiers_from_model": self._modifiers_from_model(node),
+ }
+ new_node_info = dict(
+ root_info,
+ modifiers={},
+ editable=self._editable_node(node, new_name_manager),
+ )
+ for child in node:
+ self._postprocess_tag_field(child, new_name_manager, new_node_info)
diff --git a/dms_field/models/res_partner.py b/dms_field/models/res_partner.py
new file mode 100644
index 000000000..039dce201
--- /dev/null
+++ b/dms_field/models/res_partner.py
@@ -0,0 +1,9 @@
+# Copyright 2024 Tecnativa - Carlos Roca
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import models
+
+
+class ResPartner(models.Model):
+ _name = "res.partner"
+ _inherit = ["res.partner", "dms.field.mixin"]
diff --git a/dms_field/static/description/index.html b/dms_field/static/description/index.html
index ac6cb9831..d9118a608 100644
--- a/dms_field/static/description/index.html
+++ b/dms_field/static/description/index.html
@@ -1,3 +1,4 @@
+
@@ -8,10 +9,11 @@
/*
:Author: David Goodger (goodger@python.org)
-:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
+:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
+Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
@@ -274,7 +276,7 @@
margin-left: 2em ;
margin-right: 2em }
-pre.code .ln { color: grey; } /* line numbers */
+pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -300,7 +302,7 @@
span.pre {
white-space: pre }
-span.problematic {
+span.problematic, pre.problematic {
color: red }
span.section-subtitle {
@@ -366,9 +368,9 @@ DMS Field
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!! source digest: sha256:923426d186000e2da1d7e32f4ba6b770234a94e4f930f56fdbece369f3729153
+!! source digest: sha256:ed7854681f73bbc617938529c1da77fcf81cba2bf46a8ae9387d8f20b360a53b
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-
+
This addon creates a new kind of view and allows to define a folder
related to a record.
Table of contents
@@ -414,7 +416,7 @@
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 to smash it by providing a detailed and welcomed
-feedback .
+feedback .
Do not contact contributors directly about support or help with technical issues.
@@ -440,11 +442,13 @@
This module is maintained by the OCA.
-
+
+
+
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/dms project on GitHub.
+
This module is part of the OCA/dms project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute .
diff --git a/dms_field/static/lib/jsTree/jstree.js b/dms_field/static/lib/jsTree/jstree.js
index c3c123dba..89ee80c9f 100644
--- a/dms_field/static/lib/jsTree/jstree.js
+++ b/dms_field/static/lib/jsTree/jstree.js
@@ -13,7 +13,7 @@
}(function ($, undefined) {
"use strict";
/*!
- * jsTree 3.3.10
+ * jsTree 3.3.16
* http://jstree.com/
*
* Copyright (c) 2014 Ivan Bozhanov (http://vakata.com)
@@ -63,7 +63,7 @@
* specifies the jstree version in use
* @name $.jstree.version
*/
- version : '3.3.10',
+ version : '3.3.16',
/**
* holds all the default options used when creating new instances
* @name $.jstree.defaults
@@ -274,7 +274,7 @@
* You can also pass in a HTML string or a JSON array here.
*
* It is possible to pass in a standard jQuery-like AJAX config and jstree will automatically determine if the response is JSON or HTML and use that to populate the tree.
- * In addition to the standard jQuery ajax options here you can suppy functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node is being loaded, the return value of those functions will be used.
+ * In addition to the standard jQuery ajax options here you can supply functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node is being loaded, the return value of those functions will be used.
*
* The last option is to specify a function, that function will receive the node being loaded as argument and a second param which is a function which should be called with the result.
*
@@ -453,6 +453,12 @@
* @name $.jstree.defaults.core.restore_focus
*/
restore_focus : true,
+ /**
+ * Force to compute and set "aria-setsize" and "aria-posinset" explicitly for each treeitem.
+ * Some browsers may compute incorrect elements position and produce wrong announcements for screen readers. Defaults to `false`
+ * @name $.jstree.defaults.core.compute_elements_positions
+ */
+ compute_elements_positions : false,
/**
* Default keyboard shortcuts (an object where each key is the button name or combo - like 'enter', 'ctrl-space', 'p', etc and the value is the function to execute in the instance's scope)
* @name $.jstree.defaults.core.keyboard
@@ -476,31 +482,31 @@
}
else {
var o = this.get_parent(e.currentTarget);
- if(o && o.id !== $.jstree.root) { this.get_node(o, true).children('.jstree-anchor').focus(); }
+ if(o && o.id !== $.jstree.root) { this.get_node(o, true).children('.jstree-anchor').trigger('focus'); }
}
},
'up': function (e) {
// up
e.preventDefault();
var o = this.get_prev_dom(e.currentTarget);
- if(o && o.length) { o.children('.jstree-anchor').focus(); }
+ if(o && o.length) { o.children('.jstree-anchor').trigger('focus'); }
},
'right': function (e) {
// right
e.preventDefault();
if(this.is_closed(e.currentTarget)) {
- this.open_node(e.currentTarget, function (o) { this.get_node(o, true).children('.jstree-anchor').focus(); });
+ this.open_node(e.currentTarget, function (o) { this.get_node(o, true).children('.jstree-anchor').trigger('focus'); });
}
else if (this.is_open(e.currentTarget)) {
var o = this.get_node(e.currentTarget, true).children('.jstree-children')[0];
- if(o) { $(this._firstChild(o)).children('.jstree-anchor').focus(); }
+ if(o) { $(this._firstChild(o)).children('.jstree-anchor').trigger('focus'); }
}
},
'down': function (e) {
// down
e.preventDefault();
var o = this.get_next_dom(e.currentTarget);
- if(o && o.length) { o.children('.jstree-anchor').focus(); }
+ if(o && o.length) { o.children('.jstree-anchor').trigger('focus'); }
},
'*': function (e) {
// aria defines * on numpad as open_all - not very common
@@ -510,19 +516,24 @@
// home
e.preventDefault();
var o = this._firstChild(this.get_container_ul()[0]);
- if(o) { $(o).children('.jstree-anchor').filter(':visible').focus(); }
+ if(o) { $(o).children('.jstree-anchor').filter(':visible').trigger('focus'); }
},
'end': function (e) {
// end
e.preventDefault();
- this.element.find('.jstree-anchor').filter(':visible').last().focus();
+ this.element.find('.jstree-anchor').filter(':visible').last().trigger('focus');
},
'f2': function (e) {
// f2 - safe to include - if check_callback is false it will fail
e.preventDefault();
this.edit(e.currentTarget);
}
- }
+ },
+ /**
+ * Should reselecting an already selected node trigger the select and changed callbacks
+ * @name $.jstree.defaults.core.allow_reselect
+ */
+ allow_reselect : false
};
$.jstree.core.prototype = {
/**
@@ -602,7 +613,7 @@
return this.nodeType === 3 && (!this.nodeValue || /^\s+$/.test(this.nodeValue));
})
.remove();
- this.element.html("<"+"ul class='jstree-container-ul jstree-children' role='group'><"+"li id='j"+this._id+"_loading' class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='presentation'> <"+"a class='jstree-anchor' role='treeitem' href='#'> " + this.get_string("Loading ...") + "");
+ this.element.html("<"+"ul class='jstree-container-ul jstree-children' role='group'><"+"li id='j"+this._id+"_loading' class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='none'> <"+"a class='jstree-anchor' role='treeitem' href='#'> " + this.get_string("Loading ...") + "");
this.element.attr('aria-activedescendant','j' + this._id + '_loading');
this._data.core.li_height = this.get_container_ul().children("li").first().outerHeight() || 24;
this._data.core.node = this._create_prototype_node();
@@ -643,7 +654,7 @@
*/
_create_prototype_node : function () {
var _node = document.createElement('LI'), _temp1, _temp2;
- _node.setAttribute('role', 'presentation');
+ _node.setAttribute('role', 'none');
_temp1 = document.createElement('I');
_temp1.className = 'jstree-icon jstree-ocl';
_temp1.setAttribute('role', 'presentation');
@@ -686,7 +697,7 @@
if (e.ctrlKey) { parts.push('ctrl'); }
if (e.altKey) { parts.push('alt'); }
if (e.shiftKey) { parts.push('shift'); }
- parts.push(keys[e.which] || e.which);
+ parts.push(keys[e.which] ? keys[e.which].toLowerCase() : e.which);
parts = parts.sort().join('-').toLowerCase();
if (parts === 'shift-shift' || parts === 'ctrl-ctrl' || parts === 'alt-alt') {
return null;
@@ -747,30 +758,30 @@
}
}
})
- .on("mousedown.jstree", $.proxy(function (e) {
+ .on("mousedown.jstree", function (e) {
if(e.target === this.element[0]) {
e.preventDefault(); // prevent losing focus when clicking scroll arrows (FF, Chrome)
was_click = +(new Date()); // ie does not allow to prevent losing focus
}
- }, this))
+ }.bind(this))
.on("mousedown.jstree", ".jstree-ocl", function (e) {
e.preventDefault(); // prevent any node inside from losing focus when clicking the open/close icon
})
- .on("click.jstree", ".jstree-ocl", $.proxy(function (e) {
+ .on("click.jstree", ".jstree-ocl", function (e) {
this.toggle_node(e.target);
- }, this))
- .on("dblclick.jstree", ".jstree-anchor", $.proxy(function (e) {
+ }.bind(this))
+ .on("dblclick.jstree", ".jstree-anchor", function (e) {
if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
if(this.settings.core.dblclick_toggle) {
this.toggle_node(e.target);
}
- }, this))
- .on("click.jstree", ".jstree-anchor", $.proxy(function (e) {
+ }.bind(this))
+ .on("click.jstree", ".jstree-anchor", function (e) {
e.preventDefault();
- if(e.currentTarget !== document.activeElement) { $(e.currentTarget).focus(); }
+ if(e.currentTarget !== document.activeElement) { $(e.currentTarget).trigger('focus'); }
this.activate_node(e.currentTarget, e);
- }, this))
- .on('keydown.jstree', '.jstree-anchor', $.proxy(function (e) {
+ }.bind(this))
+ .on('keydown.jstree', '.jstree-anchor', function (e) {
if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
if(this._data.core.rtl) {
if(e.which === 37) { e.which = 39; }
@@ -783,8 +794,8 @@
return r;
}
}
- }, this))
- .on("load_node.jstree", $.proxy(function (e, data) {
+ }.bind(this))
+ .on("load_node.jstree", function (e, data) {
if(data.status) {
if(data.node.id === $.jstree.root && !this._data.core.loaded) {
this._data.core.loaded = true;
@@ -799,7 +810,7 @@
this.trigger("loaded");
}
if(!this._data.core.ready) {
- setTimeout($.proxy(function() {
+ setTimeout(function() {
if(this.element && !this.get_container_ul().find('.jstree-loading').length) {
this._data.core.ready = true;
if(this._data.core.selected.length) {
@@ -822,12 +833,12 @@
*/
this.trigger("ready");
}
- }, this), 0);
+ }.bind(this), 0);
}
}
- }, this))
+ }.bind(this))
// quick searching when the tree is focused
- .on('keypress.jstree', $.proxy(function (e) {
+ .on('keypress.jstree', function (e) {
if(e.target.tagName && e.target.tagName.toLowerCase() === "input") { return true; }
if(tout) { clearTimeout(tout); }
tout = setTimeout(function () {
@@ -842,50 +853,50 @@
// match for whole word from current node down (including the current node)
if(word.length > 1) {
- col.slice(ind).each($.proxy(function (i, v) {
+ col.slice(ind).each(function (i, v) {
if($(v).text().toLowerCase().indexOf(word) === 0) {
- $(v).focus();
+ $(v).trigger('focus');
end = true;
return false;
}
- }, this));
+ }.bind(this));
if(end) { return; }
// match for whole word from the beginning of the tree
- col.slice(0, ind).each($.proxy(function (i, v) {
+ col.slice(0, ind).each(function (i, v) {
if($(v).text().toLowerCase().indexOf(word) === 0) {
- $(v).focus();
+ $(v).trigger('focus');
end = true;
return false;
}
- }, this));
+ }.bind(this));
if(end) { return; }
}
// list nodes that start with that letter (only if word consists of a single char)
if(new RegExp('^' + chr.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '+$').test(word)) {
// search for the next node starting with that letter
- col.slice(ind + 1).each($.proxy(function (i, v) {
+ col.slice(ind + 1).each(function (i, v) {
if($(v).text().toLowerCase().charAt(0) === chr) {
- $(v).focus();
+ $(v).trigger('focus');
end = true;
return false;
}
- }, this));
+ }.bind(this));
if(end) { return; }
// search from the beginning
- col.slice(0, ind + 1).each($.proxy(function (i, v) {
+ col.slice(0, ind + 1).each(function (i, v) {
if($(v).text().toLowerCase().charAt(0) === chr) {
- $(v).focus();
+ $(v).trigger('focus');
end = true;
return false;
}
- }, this));
+ }.bind(this));
if(end) { return; }
}
- }, this))
+ }.bind(this))
// THEME RELATED
- .on("init.jstree", $.proxy(function () {
+ .on("init.jstree", function () {
var s = this.settings.core.themes;
this._data.core.themes.dots = s.dots;
this._data.core.themes.stripes = s.stripes;
@@ -893,42 +904,44 @@
this._data.core.themes.ellipsis = s.ellipsis;
this.set_theme(s.name || "default", s.url);
this.set_theme_variant(s.variant);
- }, this))
- .on("loading.jstree", $.proxy(function () {
+ }.bind(this))
+ .on("loading.jstree", function () {
this[ this._data.core.themes.dots ? "show_dots" : "hide_dots" ]();
this[ this._data.core.themes.icons ? "show_icons" : "hide_icons" ]();
this[ this._data.core.themes.stripes ? "show_stripes" : "hide_stripes" ]();
this[ this._data.core.themes.ellipsis ? "show_ellipsis" : "hide_ellipsis" ]();
- }, this))
- .on('blur.jstree', '.jstree-anchor', $.proxy(function (e) {
+ }.bind(this))
+ .on('blur.jstree', '.jstree-anchor', function (e) {
this._data.core.focused = null;
$(e.currentTarget).filter('.jstree-hovered').trigger('mouseleave');
this.element.attr('tabindex', '0');
- }, this))
- .on('focus.jstree', '.jstree-anchor', $.proxy(function (e) {
+ $(e.currentTarget).attr('tabindex', '-1');
+ }.bind(this))
+ .on('focus.jstree', '.jstree-anchor', function (e) {
var tmp = this.get_node(e.currentTarget);
- if(tmp && tmp.id) {
+ if(tmp && (tmp.id || tmp.id === 0)) {
this._data.core.focused = tmp.id;
}
this.element.find('.jstree-hovered').not(e.currentTarget).trigger('mouseleave');
$(e.currentTarget).trigger('mouseenter');
this.element.attr('tabindex', '-1');
- }, this))
- .on('focus.jstree', $.proxy(function () {
+ $(e.currentTarget).attr('tabindex', '0');
+ }.bind(this))
+ .on('focus.jstree', function () {
if(+(new Date()) - was_click > 500 && !this._data.core.focused && this.settings.core.restore_focus) {
was_click = 0;
var act = this.get_node(this.element.attr('aria-activedescendant'), true);
if(act) {
- act.find('> .jstree-anchor').focus();
+ act.find('> .jstree-anchor').trigger('focus');
}
}
- }, this))
- .on('mouseenter.jstree', '.jstree-anchor', $.proxy(function (e) {
+ }.bind(this))
+ .on('mouseenter.jstree', '.jstree-anchor', function (e) {
this.hover_node(e.currentTarget);
- }, this))
- .on('mouseleave.jstree', '.jstree-anchor', $.proxy(function (e) {
+ }.bind(this))
+ .on('mouseleave.jstree', '.jstree-anchor', function (e) {
this.dehover_node(e.currentTarget);
- }, this));
+ }.bind(this));
},
/**
* part of the destroying of an instance. Used internally.
@@ -979,7 +992,7 @@
*/
get_string : function (key) {
var a = this.settings.core.strings;
- if($.isFunction(a)) { return a.call(this, key); }
+ if($.vakata.is_function(a)) { return a.call(this, key); }
if(a && a[key]) { return a[key]; }
return key;
},
@@ -1033,7 +1046,7 @@
* @return {Object|jQuery}
*/
get_node : function (obj, as_dom) {
- if(obj && obj.id) {
+ if(obj && (obj.id || obj.id === 0)) {
obj = obj.id;
}
if (obj instanceof $ && obj.length && obj[0].id) {
@@ -1270,8 +1283,8 @@
* @trigger load_node.jstree
*/
load_node : function (obj, callback) {
- var k, l, i, j, c;
- if($.isArray(obj)) {
+ var dom = this.get_node(obj, true), k, l, i, j, c;
+ if($.vakata.is_array(obj)) {
this._load_nodes(obj.slice(), callback);
return true;
}
@@ -1307,8 +1320,13 @@
}
obj.state.failed = false;
obj.state.loading = true;
- this.get_node(obj, true).addClass("jstree-loading").attr('aria-busy',true);
- this._load_node(obj, $.proxy(function (status) {
+ if (obj.id !== $.jstree.root) {
+ dom.children(".jstree-anchor").attr('aria-busy', true);
+ } else {
+ dom.attr('aria-busy', true);
+ }
+ dom.addClass("jstree-loading");
+ this._load_node(obj, function (status) {
obj = this._model.data[obj.id];
obj.state.loading = false;
obj.state.loaded = status;
@@ -1331,7 +1349,12 @@
}
}
}
- dom.removeClass("jstree-loading").attr('aria-busy',false);
+ if (obj.id !== $.jstree.root) {
+ dom.children(".jstree-anchor").attr('aria-busy', false);
+ } else {
+ dom.attr('aria-busy', false);
+ }
+ dom.removeClass("jstree-loading");
/**
* triggered after a node is loaded
* @event
@@ -1343,7 +1366,7 @@
if(callback) {
callback.call(this, obj, status);
}
- }, this));
+ }.bind(this));
return true;
},
/**
@@ -1441,8 +1464,8 @@
}
// return callback.call(this, obj.id === $.jstree.root ? this._append_html_data(obj, this._data.core.original_container_html.clone(true)) : false);
}
- if($.isFunction(s)) {
- return s.call(this, obj, $.proxy(function (d) {
+ if($.vakata.is_function(s)) {
+ return s.call(this, obj, function (d) {
if(d === false) {
callback.call(this, false);
}
@@ -1452,19 +1475,19 @@
});
}
// return d === false ? callback.call(this, false) : callback.call(this, this[typeof d === 'string' ? '_append_html_data' : '_append_json_data'](obj, typeof d === 'string' ? $(d) : d));
- }, this));
+ }.bind(this));
}
if(typeof s === 'object') {
if(s.url) {
s = $.extend(true, {}, s);
- if($.isFunction(s.url)) {
+ if($.vakata.is_function(s.url)) {
s.url = s.url.call(this, obj);
}
- if($.isFunction(s.data)) {
+ if($.vakata.is_function(s.data)) {
s.data = s.data.call(this, obj);
}
return $.ajax(s)
- .done($.proxy(function (d,t,x) {
+ .done(function (d,t,x) {
var type = x.getResponseHeader('Content-Type');
if((type && type.indexOf('json') !== -1) || typeof d === "object") {
return this._append_json_data(obj, d, function (status) { callback.call(this, status); });
@@ -1477,14 +1500,14 @@
this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : x }) };
this.settings.core.error.call(this, this._data.core.last_error);
return callback.call(this, false);
- }, this))
- .fail($.proxy(function (f) {
+ }.bind(this))
+ .fail(function (f) {
this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'core', 'id' : 'core_04', 'reason' : 'Could not load node', 'data' : JSON.stringify({ 'id' : obj.id, 'xhr' : f }) };
callback.call(this, false);
this.settings.core.error.call(this, this._data.core.last_error);
- }, this));
+ }.bind(this));
}
- if ($.isArray(s)) {
+ if ($.vakata.is_array(s)) {
t = $.extend(true, [], s);
} else if ($.isPlainObject(s)) {
t = $.extend(true, {}, s);
@@ -1550,7 +1573,7 @@
p = m[par],
s = this._data.core.selected.length,
tmp, i, j;
- dat.each($.proxy(function (i, v) {
+ dat.each(function (i, v) {
tmp = this._parse_model_from_html($(v), par, p.parents.concat());
if(tmp) {
chd.push(tmp);
@@ -1559,7 +1582,7 @@
dpc = dpc.concat(m[tmp].children_d);
}
}
- }, this));
+ }.bind(this));
p.children = chd;
p.children_d = dpc;
for(i = 0, j = p.parents.length; i < j; i++) {
@@ -1607,7 +1630,7 @@
data = JSON.parse(data);
}
}
- if(!$.isArray(data)) { data = [data]; }
+ if(!$.vakata.is_array(data)) { data = [data]; }
var w = null,
args = {
'df' : this._model.default_state,
@@ -1748,7 +1771,7 @@
tmp.state[i] = df[i];
}
}
- if(d && d.id) { tmp.id = d.id.toString(); }
+ if(d && (d.id || d.id === 0)) { tmp.id = d.id.toString(); }
if(d && d.text) { tmp.text = d.text; }
if(d && d.data && d.data.jstree && d.data.jstree.icon) {
tmp.icon = d.data.jstree.icon;
@@ -1780,10 +1803,10 @@
}
}
}
- if(tmp.li_attr.id && !tmp.id) {
+ if(tmp.li_attr.id && !(tmp.id || tmp.id === 0)) {
tmp.id = tmp.li_attr.id.toString();
}
- if(!tmp.id) {
+ if(!(tmp.id || tmp.id === 0)) {
tmp.id = tid;
}
if(!tmp.li_attr.id) {
@@ -1972,7 +1995,7 @@
if(!this._data.core.working || force_processing) {
this._data.core.working = true;
w = new window.Worker(this._wrk);
- w.onmessage = $.proxy(function (e) {
+ w.onmessage = function (e) {
rslt.call(this, e.data, true);
try { w.terminate(); w = null; } catch(ignore) { }
if(this._data.core.worker_queue.length) {
@@ -1981,7 +2004,16 @@
else {
this._data.core.working = false;
}
- }, this);
+ }.bind(this);
+ w.onerror = function (e) {
+ rslt.call(this, func(args), false);
+ if(this._data.core.worker_queue.length) {
+ this._append_json_data.apply(this, this._data.core.worker_queue.shift());
+ }
+ else {
+ this._data.core.working = false;
+ }
+ }.bind(this);
if(!args.par) {
if(this._data.core.worker_queue.length) {
this._append_json_data.apply(this, this._data.core.worker_queue.shift());
@@ -2047,7 +2079,7 @@
}
tmp = $.vakata.attributes(d, true);
$.each(tmp, function (i, v) {
- v = $.trim(v);
+ v = $.vakata.trim(v);
if(!v.length) { return true; }
data.li_attr[i] = v;
if(i === 'id') {
@@ -2058,7 +2090,7 @@
if(tmp.length) {
tmp = $.vakata.attributes(tmp, true);
$.each(tmp, function (i, v) {
- v = $.trim(v);
+ v = $.vakata.trim(v);
if(v.length) {
data.a_attr[i] = v;
}
@@ -2097,14 +2129,14 @@
} while(m[tid]);
data.id = data.li_attr.id ? data.li_attr.id.toString() : tid;
if(tmp.length) {
- tmp.each($.proxy(function (i, v) {
+ tmp.each(function (i, v) {
c = this._parse_model_from_html($(v), data.id, ps);
e = this._model.data[c];
data.children.push(c);
if(e.children_d.length) {
data.children_d = data.children_d.concat(e.children_d);
}
- }, this));
+ }.bind(this));
data.children_d = data.children_d.concat(data.children);
}
else {
@@ -2259,7 +2291,7 @@
tmp.state[i] = df[i];
}
}
- if(d && d.id) { tmp.id = d.id.toString(); }
+ if(d && (d.id || d.id === 0)) { tmp.id = d.id.toString(); }
if(d && d.text) { tmp.text = d.text; }
if(d && d.data && d.data.jstree && d.data.jstree.icon) {
tmp.icon = d.data.jstree.icon;
@@ -2291,10 +2323,10 @@
}
}
}
- if(tmp.li_attr.id && !tmp.id) {
+ if(tmp.li_attr.id && !(tmp.id || tmp.id === 0)) {
tmp.id = tmp.li_attr.id.toString();
}
- if(!tmp.id) {
+ if(!(tmp.id || tmp.id === 0)) {
tmp.id = tid;
}
if(!tmp.li_attr.id) {
@@ -2349,14 +2381,14 @@
}
if(this._model.force_full_redraw) {
f.className = this.get_container_ul()[0].className;
- f.setAttribute('role','group');
+ f.setAttribute('role','presentation');
this.element.empty().append(f);
//this.get_container_ul()[0].appendChild(f);
}
if(fe !== null && this.settings.core.restore_focus) {
tmp = this.get_node(fe, true);
if(tmp && tmp.length && tmp.children('.jstree-anchor')[0] !== document.activeElement) {
- tmp.children('.jstree-anchor').focus();
+ tmp.children('.jstree-anchor').trigger('focus');
}
else {
this._data.core.focused = null;
@@ -2497,13 +2529,13 @@
if(!obj.a_attr.id) {
obj.a_attr.id = obj.id + '_anchor';
}
- node.setAttribute('aria-selected', !!obj.state.selected);
node.childNodes[1].setAttribute('aria-selected', !!obj.state.selected);
- node.setAttribute('aria-level', obj.parents.length);
node.childNodes[1].setAttribute('aria-level', obj.parents.length);
- node.setAttribute('aria-labelledby', obj.a_attr.id);
+ if(this.settings.core.compute_elements_positions) {
+ node.childNodes[1].setAttribute('aria-setsize', m[obj.parent].children.length);
+ node.childNodes[1].setAttribute('aria-posinset', m[obj.parent].children.indexOf(obj.id) + 1);
+ }
if(obj.state.disabled) {
- node.setAttribute('aria-disabled', true);
node.childNodes[1].setAttribute('aria-disabled', true);
}
@@ -2540,7 +2572,6 @@
}
else {
c += obj.state.opened && obj.state.loaded ? ' jstree-open' : ' jstree-closed';
- node.setAttribute('aria-expanded', (obj.state.opened && obj.state.loaded) );
node.childNodes[1].setAttribute('aria-expanded', (obj.state.opened && obj.state.loaded) );
}
if(last_sibling === obj.id) {
@@ -2633,9 +2664,9 @@
}
if(obj.state.opened && !obj.state.loaded) {
obj.state.opened = false;
- setTimeout($.proxy(function () {
+ setTimeout(function () {
this.open_node(obj.id, false, 0);
- }, this), 0);
+ }.bind(this), 0);
}
return node;
},
@@ -2649,7 +2680,7 @@
*/
open_node : function (obj, callback, animation) {
var t1, t2, d, t;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.open_node(obj[t1], callback, animation);
@@ -2669,9 +2700,9 @@
}
if(!this.is_loaded(obj)) {
if(this.is_loading(obj)) {
- return setTimeout($.proxy(function () {
+ return setTimeout(function () {
this.open_node(obj, callback, animation);
- }, this), 500);
+ }.bind(this), 500);
}
this.load_node(obj, function (o, ok) {
return ok ? this.open_node(o, callback, animation) : (callback ? callback.call(this, o, false) : false);
@@ -2691,14 +2722,13 @@
if(!animation) {
this.trigger('before_open', { "node" : obj });
d[0].className = d[0].className.replace('jstree-closed', 'jstree-open');
- d[0].setAttribute("aria-expanded", true);
d[0].childNodes[1].setAttribute("aria-expanded", true);
}
else {
this.trigger('before_open', { "node" : obj });
d
.children(".jstree-children").css("display","none").end()
- .removeClass("jstree-closed").addClass("jstree-open").attr("aria-expanded", true)
+ .removeClass("jstree-closed").addClass("jstree-open")
.children('.jstree-anchor').attr("aria-expanded", true).end()
.children(".jstree-children").stop(true, true)
.slideDown(animation, function () {
@@ -2769,7 +2799,7 @@
*/
close_node : function (obj, animation) {
var t1, t2, t, d;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.close_node(obj[t1], animation);
@@ -2808,13 +2838,13 @@
if(!animation) {
d[0].className = d[0].className.replace('jstree-open', 'jstree-closed');
d.children('.jstree-anchor').attr("aria-expanded", false);
- d.attr("aria-expanded", false).children('.jstree-children').remove();
+ d.children('.jstree-children').remove();
this.trigger("after_close", { "node" : obj });
}
else {
d
.children(".jstree-children").attr("style","display:block !important").end()
- .removeClass("jstree-open").addClass("jstree-closed").attr("aria-expanded", false)
+ .removeClass("jstree-open").addClass("jstree-closed")
.children('.jstree-anchor').attr("aria-expanded", false).end()
.children(".jstree-children").stop(true, true).slideUp(animation, function () {
this.style.display = "";
@@ -2833,7 +2863,7 @@
*/
toggle_node : function (obj) {
var t1, t2;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.toggle_node(obj[t1]);
@@ -2934,7 +2964,7 @@
*/
enable_node : function (obj) {
var t1, t2;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.enable_node(obj[t1]);
@@ -2963,7 +2993,7 @@
*/
disable_node : function (obj) {
var t1, t2;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.disable_node(obj[t1]);
@@ -3002,7 +3032,7 @@
*/
hide_node : function (obj, skip_redraw) {
var t1, t2;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.hide_node(obj[t1], true);
@@ -3040,7 +3070,7 @@
*/
show_node : function (obj, skip_redraw) {
var t1, t2;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.show_node(obj[t1], true);
@@ -3147,8 +3177,10 @@
this.deselect_node(obj, false, e);
}
else {
- this.deselect_all(true);
- this.select_node(obj, false, false, e);
+ if (this.settings.core.allow_reselect || !this.is_selected(obj) || this._data.core.selected.length !== 1) {
+ this.deselect_all(true);
+ this.select_node(obj, false, false, e);
+ }
this._data.core.last_clicked = this.get_node(obj);
}
}
@@ -3173,13 +3205,18 @@
}
}
else {
- this.deselect_node(p[i], true, e);
+ if (!e.ctrlKey) {
+ this.deselect_node(p[i], true, e);
+ }
}
}
this.trigger('changed', { 'action' : 'select_node', 'node' : this.get_node(obj), 'selected' : this._data.core.selected, 'event' : e });
}
else {
if(!this.is_selected(obj)) {
+ if (e.ctrlKey) {
+ this._data.core.last_clicked = this.get_node(obj);
+ }
this.select_node(obj, false, false, e);
}
else {
@@ -3252,7 +3289,7 @@
*/
select_node : function (obj, supress_event, prevent_open, e) {
var dom, t1, t2, th;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.select_node(obj[t1], supress_event, prevent_open, e);
@@ -3271,7 +3308,7 @@
dom = this._open_to(obj);
}
if(dom && dom.length) {
- dom.attr('aria-selected', true).children('.jstree-anchor').addClass('jstree-clicked').attr('aria-selected', true);
+ dom.children('.jstree-anchor').addClass('jstree-clicked').attr('aria-selected', true);
}
/**
* triggered when an node is selected
@@ -3305,7 +3342,7 @@
*/
deselect_node : function (obj, supress_event, e) {
var t1, t2, dom;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.deselect_node(obj[t1], supress_event, e);
@@ -3321,7 +3358,7 @@
obj.state.selected = false;
this._data.core.selected = $.vakata.array_remove_item(this._data.core.selected, obj.id);
if(dom.length) {
- dom.attr('aria-selected', false).children('.jstree-anchor').removeClass('jstree-clicked').attr('aria-selected', false);
+ dom.children('.jstree-anchor').removeClass('jstree-clicked').attr('aria-selected', false);
}
/**
* triggered when an node is deselected
@@ -3377,7 +3414,7 @@
}
}
this._data.core.selected = [];
- this.element.find('.jstree-clicked').removeClass('jstree-clicked').attr('aria-selected', false).parent().attr('aria-selected', false);
+ this.element.find('.jstree-clicked').removeClass('jstree-clicked').attr('aria-selected', false);
/**
* triggered when all nodes are deselected
* @event
@@ -3410,7 +3447,7 @@
* @return {Array}
*/
get_selected : function (full) {
- return full ? $.map(this._data.core.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.core.selected.slice();
+ return full ? $.map(this._data.core.selected, function (i) { return this.get_node(i); }.bind(this)) : this._data.core.selected.slice();
},
/**
* get an array of all top level selected nodes (ignoring children of selected nodes)
@@ -3437,7 +3474,7 @@
tmp.push(i);
}
}
- return full ? $.map(tmp, $.proxy(function (i) { return this.get_node(i); }, this)) : tmp;
+ return full ? $.map(tmp, function (i) { return this.get_node(i); }.bind(this)) : tmp;
},
/**
* get an array of all bottom level selected nodes (ignoring selected parents)
@@ -3453,7 +3490,7 @@
obj.push(tmp[i].id);
}
}
- return full ? $.map(obj, $.proxy(function (i) { return this.get_node(i); }, this)) : obj;
+ return full ? $.map(obj, function (i) { return this.get_node(i); }.bind(this)) : obj;
},
/**
* gets the current state of the tree so that it can be restored later with `set_state(state)`. Used internally.
@@ -3513,7 +3550,7 @@
if(state.core) {
var res, n, t, _this, i;
if(state.core.loaded) {
- if(!this.settings.core.loaded_state || !$.isArray(state.core.loaded) || !state.core.loaded.length) {
+ if(!this.settings.core.loaded_state || !$.vakata.is_array(state.core.loaded) || !state.core.loaded.length) {
delete state.core.loaded;
this.set_state(state, callback);
}
@@ -3526,7 +3563,7 @@
return false;
}
if(state.core.open) {
- if(!$.isArray(state.core.open) || !state.core.open.length) {
+ if(!$.vakata.is_array(state.core.open) || !state.core.open.length) {
delete state.core.open;
this.set_state(state, callback);
}
@@ -3600,7 +3637,7 @@
*/
refresh : function (skip_loading, forget_state) {
this._data.core.state = forget_state === true ? {} : this.get_state();
- if(forget_state && $.isFunction(forget_state)) { this._data.core.state = forget_state.call(this, this._data.core.state); }
+ if(forget_state && $.vakata.is_function(forget_state)) { this._data.core.state = forget_state.call(this, this._data.core.state); }
this._cnt = 0;
this._model.data = {};
this._model.data[$.jstree.root] = {
@@ -3617,7 +3654,7 @@
var c = this.get_container_ul()[0].className;
if(!skip_loading) {
- this.element.html("<"+"ul class='"+c+"' role='group'><"+"li class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='presentation' id='j"+this._id+"_loading'> <"+"a class='jstree-anchor' role='treeitem' href='#'> " + this.get_string("Loading ...") + "");
+ this.element.html("<"+"ul class='"+c+"' role='group'><"+"li class='jstree-initial-node jstree-loading jstree-leaf jstree-last' role='none' id='j"+this._id+"_loading'> <"+"a class='jstree-anchor' role='treeitem' href='#'> " + this.get_string("Loading ...") + "");
this.element.attr('aria-activedescendant','j'+this._id+'_loading');
}
this.load_node($.jstree.root, function (o, s) {
@@ -3651,7 +3688,7 @@
to_load.push(obj.id);
if(obj.state.opened === true) { opened.push(obj.id); }
this.get_node(obj, true).find('.jstree-open').each(function() { to_load.push(this.id); opened.push(this.id); });
- this._load_nodes(to_load, $.proxy(function (nodes) {
+ this._load_nodes(to_load, function (nodes) {
this.open_node(opened, false, 0);
this.select_node(s);
/**
@@ -3662,7 +3699,7 @@
* @param {Array} nodes - an array of the IDs of the nodes that were reloaded
*/
this.trigger('refresh_node', { 'node' : obj, 'nodes' : nodes });
- }, this), false, true);
+ }.bind(this), false, true);
},
/**
* set (change) the ID of a node
@@ -3734,7 +3771,7 @@
*/
set_text : function (obj, val) {
var t1, t2;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.set_text(obj[t1], val);
@@ -3782,7 +3819,7 @@
'li_attr' : $.extend(true, {}, obj.li_attr),
'a_attr' : $.extend(true, {}, obj.a_attr),
'state' : {},
- 'data' : options && options.no_data ? false : $.extend(true, $.isArray(obj.data)?[]:{}, obj.data)
+ 'data' : options && options.no_data ? false : $.extend(true, $.vakata.is_array(obj.data)?[]:{}, obj.data)
//( this.get_node(obj, true).length ? this.get_node(obj, true).data() : obj.data ),
}, i, j;
if(options && options.flat) {
@@ -3885,7 +3922,7 @@
break;
}
if(pos > par.children.length) { pos = par.children.length; }
- if(!node.id) { node.id = true; }
+ if(node.id === undefined) { node.id = true; }
if(!this.check("create_node", node, par, pos)) {
this.settings.core.error.call(this, this._data.core.last_error);
return false;
@@ -3934,7 +3971,7 @@
*/
rename_node : function (obj, val) {
var t1, t2, old;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.rename_node(obj[t1], val);
@@ -3969,7 +4006,7 @@
*/
delete_node : function (obj) {
var t1, t2, par, pos, tmp, i, j, k, l, c, top, lft;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.delete_node(obj[t1]);
@@ -4026,11 +4063,11 @@
lft = this.element[0].scrollLeft;
if(par.id === $.jstree.root) {
if (this._model.data[$.jstree.root].children[0]) {
- this.get_node(this._model.data[$.jstree.root].children[0], true).children('.jstree-anchor').focus();
+ this.get_node(this._model.data[$.jstree.root].children[0], true).children('.jstree-anchor').trigger('focus');
}
}
else {
- this.get_node(par, true).children('.jstree-anchor').focus();
+ this.get_node(par, true).children('.jstree-anchor').trigger('focus');
}
this.element[0].scrollTop = top;
this.element[0].scrollLeft = lft;
@@ -4052,7 +4089,7 @@
check : function (chk, obj, par, pos, more) {
obj = obj && obj.id ? obj : this.get_node(obj);
par = par && par.id ? par : this.get_node(par);
- var tmp = chk.match(/^move_node|copy_node|create_node$/i) ? par : obj,
+ var tmp = chk.match(/^(move_node|copy_node|create_node)$/i) ? par : obj,
chc = this.settings.core.check_callback;
if(chk === "move_node" || chk === "copy_node") {
if((!more || !more.is_multi) && (chk === "move_node" && $.inArray(obj.id, par.children) === pos)) {
@@ -4071,7 +4108,7 @@
}
return tmp.functions[chk];
}
- if(chc === false || ($.isFunction(chc) && chc.call(this, chk, obj, par, pos, more) === false) || (chc && chc[chk] === false)) {
+ if(chc === false || ($.vakata.is_function(chc) && chc.call(this, chk, obj, par, pos, more) === false) || (chc && chc[chk] === false)) {
this._data.core.last_error = { 'error' : 'check', 'plugin' : 'core', 'id' : 'core_03', 'reason' : 'User config for core.check_callback prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
return false;
}
@@ -4107,7 +4144,7 @@
return this.load_node(par, function () { this.move_node(obj, par, pos, callback, true, false, origin); });
}
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
if(obj.length === 1) {
obj = obj[0];
}
@@ -4123,7 +4160,7 @@
return true;
}
}
- obj = obj && obj.id ? obj : this.get_node(obj);
+ obj = obj && (obj.id !== undefined) ? obj : this.get_node(obj);
if(!obj || obj.id === $.jstree.root) { return false; }
@@ -4280,7 +4317,7 @@
return this.load_node(par, function () { this.copy_node(obj, par, pos, callback, true, false, origin); });
}
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
if(obj.length === 1) {
obj = obj[0];
}
@@ -4296,7 +4333,7 @@
return true;
}
}
- obj = obj && obj.id ? obj : this.get_node(obj);
+ obj = obj && (obj.id !== undefined) ? obj : this.get_node(obj);
if(!obj || obj.id === $.jstree.root) { return false; }
old_par = (obj.parent || $.jstree.root).toString();
@@ -4395,12 +4432,12 @@
*/
cut : function (obj) {
if(!obj) { obj = this._data.core.selected.concat(); }
- if(!$.isArray(obj)) { obj = [obj]; }
+ if(!$.vakata.is_array(obj)) { obj = [obj]; }
if(!obj.length) { return false; }
var tmp = [], o, t1, t2;
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
o = this.get_node(obj[t1]);
- if(o && o.id && o.id !== $.jstree.root) { tmp.push(o); }
+ if(o && (o.id || o.id === 0) && o.id !== $.jstree.root) { tmp.push(o); }
}
if(!tmp.length) { return false; }
ccp_node = tmp;
@@ -4422,12 +4459,12 @@
*/
copy : function (obj) {
if(!obj) { obj = this._data.core.selected.concat(); }
- if(!$.isArray(obj)) { obj = [obj]; }
+ if(!$.vakata.is_array(obj)) { obj = [obj]; }
if(!obj.length) { return false; }
var tmp = [], o, t1, t2;
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
o = this.get_node(obj[t1]);
- if(o && o.id && o.id !== $.jstree.root) { tmp.push(o); }
+ if(o && (o.id !== undefined) && o.id !== $.jstree.root) { tmp.push(o); }
}
if(!tmp.length) { return false; }
ccp_node = tmp;
@@ -4503,7 +4540,7 @@
* @name edit(obj [, default_text, callback])
* @param {mixed} obj
* @param {String} default_text the text to populate the input with (if omitted or set to a non-string value the node's text value is used)
- * @param {Function} callback a function to be called once the text box is blurred, it is called in the instance's scope and receives the node, a status parameter (true if the rename is successful, false otherwise) and a boolean indicating if the user cancelled the edit. You can access the node's title using .text
+ * @param {Function} callback a function to be called once the text box is blurred, it is called in the instance's scope and receives the node, a status parameter (true if the rename is successful, false otherwise), a boolean indicating if the user cancelled the edit and the original unescaped value provided by the user. You can also access the node's title using .text
*/
edit : function (obj, default_text, callback) {
var rtl, w, a, s, t, h1, h2, fn, tmp, cancel = false;
@@ -4522,7 +4559,7 @@
rtl = this._data.core.rtl;
w = this.element.width();
this._data.core.focused = tmp.id;
- a = obj.children('.jstree-anchor').focus();
+ a = obj.children('.jstree-anchor').trigger('focus');
s = $(' ');
/*!
oi = obj.children("i:visible"),
@@ -4545,7 +4582,7 @@
"lineHeight" : (this._data.core.li_height) + "px",
"width" : "150px" // will be set a bit further down
},
- "blur" : $.proxy(function (e) {
+ "blur" : function (e) {
e.stopImmediatePropagation();
e.preventDefault();
var i = s.children(".jstree-rename-input"),
@@ -4564,18 +4601,18 @@
this.set_text(obj, t); // move this up? and fix #483
}
this._data.core.focused = tmp.id;
- setTimeout($.proxy(function () {
+ setTimeout(function () {
var node = this.get_node(tmp.id, true);
if(node.length) {
this._data.core.focused = tmp.id;
- node.children('.jstree-anchor').focus();
+ node.children('.jstree-anchor').trigger('focus');
}
- }, this), 0);
+ }.bind(this), 0);
if(callback) {
- callback.call(this, tmp, nv, cancel);
+ callback.call(this, tmp, nv, cancel, v);
}
h2 = null;
- }, this),
+ }.bind(this),
"keydown" : function (e) {
var key = e.which;
if(key === 27) {
@@ -4615,7 +4652,7 @@
h2.css(fn).width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select();
$(document).one('mousedown.jstree touchstart.jstree dnd_start.vakata', function (e) {
if (h2 && e.target !== h2) {
- $(h2).blur();
+ $(h2).trigger('blur');
}
});
},
@@ -4819,7 +4856,7 @@
*/
set_icon : function (obj, icon) {
var t1, t2, dom, old;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.set_icon(obj[t1], icon);
@@ -4868,7 +4905,7 @@
*/
hide_icon : function (obj) {
var t1, t2;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.hide_icon(obj[t1]);
@@ -4888,7 +4925,7 @@
*/
show_icon : function (obj) {
var t1, t2, dom;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.show_icon(obj[t1]);
@@ -4914,7 +4951,7 @@
if(node && node.attributes) {
$.each(node.attributes, function (i, v) {
if($.inArray(v.name.toLowerCase(),['style','contenteditable','hasfocus','tabindex']) !== -1) { return; }
- if(v.value !== null && $.trim(v.value) !== '') {
+ if(v.value !== null && $.vakata.trim(v.value) !== '') {
if(with_values) { attr[v.name] = v.value; }
else { attr.push(v.name); }
}
@@ -4958,6 +4995,34 @@
}
return d;
};
+ $.vakata.trim = function (text) {
+ return String.prototype.trim ?
+ String.prototype.trim.call(text.toString()) :
+ text.toString().replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
+ };
+ $.vakata.is_function = function(obj) {
+ return typeof obj === "function" && typeof obj.nodeType !== "number";
+ };
+ $.vakata.is_array = Array.isArray || function (obj) {
+ return Object.prototype.toString.call(obj) === "[object Array]";
+ };
+
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind#polyfill
+ if (!Function.prototype.bind) {
+ Function.prototype.bind = function () {
+ var thatFunc = this, thatArg = arguments[0];
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (typeof thatFunc !== 'function') {
+ // closest thing possible to the ECMAScript 5
+ // internal IsCallable function
+ throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
+ }
+ return function(){
+ var funcArgs = args.concat(Array.prototype.slice.call(arguments));
+ return thatFunc.apply(thatArg, funcArgs);
+ };
+ };
+ }
/**
@@ -5091,7 +5156,7 @@
this.settings.checkbox.cascade = 'up+down+undetermined';
}
this.element
- .on("init.jstree", $.proxy(function () {
+ .on("init.jstree", function () {
this._data.checkbox.visible = this.settings.checkbox.visible;
if(!this.settings.checkbox.keep_selected_style) {
this.element.addClass('jstree-checkbox-no-clicked');
@@ -5099,21 +5164,21 @@
if(this.settings.checkbox.tie_selection) {
this.element.addClass('jstree-checkbox-selection');
}
- }, this))
- .on("loading.jstree", $.proxy(function () {
+ }.bind(this))
+ .on("loading.jstree", function () {
this[ this._data.checkbox.visible ? 'show_checkboxes' : 'hide_checkboxes' ]();
- }, this));
+ }.bind(this));
if(this.settings.checkbox.cascade.indexOf('undetermined') !== -1) {
this.element
- .on('changed.jstree uncheck_node.jstree check_node.jstree uncheck_all.jstree check_all.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree', $.proxy(function () {
+ .on('changed.jstree uncheck_node.jstree check_node.jstree uncheck_all.jstree check_all.jstree move_node.jstree copy_node.jstree redraw.jstree open_node.jstree', function () {
// only if undetermined is in setting
if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); }
- this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50);
- }, this));
+ this._data.checkbox.uto = setTimeout(this._undetermined.bind(this), 50);
+ }.bind(this));
}
if(!this.settings.checkbox.tie_selection) {
this.element
- .on('model.jstree', $.proxy(function (e, data) {
+ .on('model.jstree', function (e, data) {
var m = this._model.data,
p = m[data.parent],
dpc = data.nodes,
@@ -5124,11 +5189,11 @@
this._data.checkbox.selected.push(dpc[i]);
}
}
- }, this));
+ }.bind(this));
}
if(this.settings.checkbox.cascade.indexOf('up') !== -1 || this.settings.checkbox.cascade.indexOf('down') !== -1) {
this.element
- .on('model.jstree', $.proxy(function (e, data) {
+ .on('model.jstree', function (e, data) {
var m = this._model.data,
p = m[data.parent],
dpc = data.nodes,
@@ -5176,7 +5241,7 @@
this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
tmp = this.get_node(p, true);
if(tmp && tmp.length) {
- tmp.attr('aria-selected', true).children('.jstree-anchor').addClass( t ? 'jstree-clicked' : 'jstree-checked');
+ tmp.children('.jstree-anchor').attr('aria-selected', true).addClass( t ? 'jstree-clicked' : 'jstree-checked');
}
}
else {
@@ -5188,8 +5253,8 @@
}
this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_unique(this._data[ t ? 'core' : 'checkbox' ].selected);
- }, this))
- .on(this.settings.checkbox.tie_selection ? 'select_node.jstree' : 'check_node.jstree', $.proxy(function (e, data) {
+ }.bind(this))
+ .on(this.settings.checkbox.tie_selection ? 'select_node.jstree' : 'check_node.jstree', function (e, data) {
var self = this,
obj = data.node,
m = this._model.data,
@@ -5229,7 +5294,7 @@
//this._data[ t ? 'core' : 'checkbox' ].selected.push(par.id);
tmp = this.get_node(par, true);
if(tmp && tmp.length) {
- tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
+ tmp.children('.jstree-anchor').attr('aria-selected', true).addClass(t ? 'jstree-clicked' : 'jstree-checked');
}
}
else {
@@ -5246,8 +5311,8 @@
}
}
this._data[ t ? 'core' : 'checkbox' ].selected = cur;
- }, this))
- .on(this.settings.checkbox.tie_selection ? 'deselect_all.jstree' : 'uncheck_all.jstree', $.proxy(function (e, data) {
+ }.bind(this))
+ .on(this.settings.checkbox.tie_selection ? 'deselect_all.jstree' : 'uncheck_all.jstree', function (e, data) {
var obj = this.get_node($.jstree.root),
m = this._model.data,
i, j, tmp;
@@ -5257,8 +5322,8 @@
tmp.original.state.undetermined = false;
}
}
- }, this))
- .on(this.settings.checkbox.tie_selection ? 'deselect_node.jstree' : 'uncheck_node.jstree', $.proxy(function (e, data) {
+ }.bind(this))
+ .on(this.settings.checkbox.tie_selection ? 'deselect_node.jstree' : 'uncheck_node.jstree', function (e, data) {
var self = this,
obj = data.node,
dom = this.get_node(obj, true),
@@ -5287,7 +5352,7 @@
}
tmp = this.get_node(obj.parents[i], true);
if(tmp && tmp.length) {
- tmp.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
+ tmp.children('.jstree-anchor').attr('aria-selected', false).removeClass(t ? 'jstree-clicked' : 'jstree-checked');
}
}
@@ -5297,11 +5362,11 @@
}
this._data[ t ? 'core' : 'checkbox' ].selected = cur;
- }, this));
+ }.bind(this));
}
if(this.settings.checkbox.cascade.indexOf('up') !== -1) {
this.element
- .on('delete_node.jstree', $.proxy(function (e, data) {
+ .on('delete_node.jstree', function (e, data) {
// apply up (whole handler)
var p = this.get_node(data.parent),
m = this._model.data,
@@ -5316,7 +5381,7 @@
this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
tmp = this.get_node(p, true);
if(tmp && tmp.length) {
- tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
+ tmp.children('.jstree-anchor').attr('aria-selected', true).addClass(t ? 'jstree-clicked' : 'jstree-checked');
}
}
else {
@@ -5324,8 +5389,8 @@
}
p = this.get_node(p.parent);
}
- }, this))
- .on('move_node.jstree', $.proxy(function (e, data) {
+ }.bind(this))
+ .on('move_node.jstree', function (e, data) {
// apply up (whole handler)
var is_multi = data.is_multi,
old_par = data.old_parent,
@@ -5344,7 +5409,7 @@
this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
tmp = this.get_node(p, true);
if(tmp && tmp.length) {
- tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
+ tmp.children('.jstree-anchor').attr('aria-selected', true).addClass(t ? 'jstree-clicked' : 'jstree-checked');
}
}
else {
@@ -5365,7 +5430,7 @@
this._data[ t ? 'core' : 'checkbox' ].selected.push(p.id);
tmp = this.get_node(p, true);
if(tmp && tmp.length) {
- tmp.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
+ tmp.children('.jstree-anchor').attr('aria-selected', true).addClass(t ? 'jstree-clicked' : 'jstree-checked');
}
}
}
@@ -5375,7 +5440,7 @@
this._data[ t ? 'core' : 'checkbox' ].selected = $.vakata.array_remove_item(this._data[ t ? 'core' : 'checkbox' ].selected, p.id);
tmp = this.get_node(p, true);
if(tmp && tmp.length) {
- tmp.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
+ tmp.children('.jstree-anchor').attr('aria-selected', false).removeClass(t ? 'jstree-clicked' : 'jstree-checked');
}
}
else {
@@ -5384,7 +5449,7 @@
}
p = this.get_node(p.parent);
}
- }, this));
+ }.bind(this));
}
};
/**
@@ -5495,7 +5560,7 @@
}
if(!is_callback && this.settings.checkbox.cascade.indexOf('undetermined') !== -1) {
if(this._data.checkbox.uto) { clearTimeout(this._data.checkbox.uto); }
- this._data.checkbox.uto = setTimeout($.proxy(this._undetermined, this), 50);
+ this._data.checkbox.uto = setTimeout(this._undetermined.bind(this), 50);
}
return obj;
};
@@ -5548,7 +5613,7 @@
*/
this.disable_checkbox = function (obj) {
var t1, t2, dom;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.disable_checkbox(obj[t1]);
@@ -5584,7 +5649,7 @@
*/
this.enable_checkbox = function (obj) {
var t1, t2, dom;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.enable_checkbox(obj[t1]);
@@ -5633,11 +5698,34 @@
}
this.trigger('activate_node', { 'node' : this.get_node(obj) });
};
+ this.delete_node = function (obj) {
+ if(this.settings.checkbox.tie_selection || $.vakata.is_array(obj)) {
+ return parent.delete_node.call(this, obj);
+ }
+ var tmp, k, l, c = false;
+ obj = this.get_node(obj);
+ if(!obj || obj.id === $.jstree.root) { return false; }
+ tmp = obj.children_d.concat([]);
+ tmp.push(obj.id);
+ for(k = 0, l = tmp.length; k < l; k++) {
+ if(this._model.data[tmp[k]].state.checked) {
+ c = true;
+ break;
+ }
+ }
+ if (c) {
+ this._data.checkbox.selected = $.vakata.array_filter(this._data.checkbox.selected, function (v) {
+ return $.inArray(v, tmp) === -1;
+ });
+ }
+ return parent.delete_node.call(this, obj);
+ };
/**
* Cascades checked state to a node and all its descendants. This function does NOT affect hidden and disabled nodes (or their descendants).
* However if these unaffected nodes are already selected their ids will be included in the returned array.
* @private
+ * @name _cascade_new_checked_state(id, checkedState)
* @param {string} id the node ID
* @param {bool} checkedState should the nodes be checked or not
* @returns {Array} Array of all node id's (in this tree branch) that are checked.
@@ -5677,7 +5765,7 @@
//If a node is undetermined then remove selected class
if (undetermined) {
node.state[ t ? 'selected' : 'checked' ] = false;
- dom.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
+ dom.children('.jstree-anchor').attr('aria-selected', false).removeClass(t ? 'jstree-clicked' : 'jstree-checked');
}
//Otherwise, if the checkedState === true (i.e. the node is being checked now) and all of the node's children are checked (if it has any children),
//check the node and style it correctly.
@@ -5685,11 +5773,11 @@
node.state[ t ? 'selected' : 'checked' ] = checkedState;
selectedNodeIds.push(node.id);
- dom.attr('aria-selected', true).children('.jstree-anchor').addClass(t ? 'jstree-clicked' : 'jstree-checked');
+ dom.children('.jstree-anchor').attr('aria-selected', true).addClass(t ? 'jstree-clicked' : 'jstree-checked');
}
else {
node.state[ t ? 'selected' : 'checked' ] = false;
- dom.attr('aria-selected', false).children('.jstree-anchor').removeClass(t ? 'jstree-clicked' : 'jstree-checked');
+ dom.children('.jstree-anchor').attr('aria-selected', false).removeClass(t ? 'jstree-clicked' : 'jstree-checked');
}
}
else {
@@ -5732,7 +5820,7 @@
this.check_node = function (obj, e) {
if(this.settings.checkbox.tie_selection) { return this.select_node(obj, false, true, e); }
var dom, t1, t2, th;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.check_node(obj[t1], e);
@@ -5772,7 +5860,7 @@
this.uncheck_node = function (obj, e) {
if(this.settings.checkbox.tie_selection) { return this.deselect_node(obj, false, e); }
var t1, t2, dom;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.uncheck_node(obj[t1], e);
@@ -5876,7 +5964,7 @@
*/
this.get_checked = function (full) {
if(this.settings.checkbox.tie_selection) { return this.get_selected(full); }
- return full ? $.map(this._data.checkbox.selected, $.proxy(function (i) { return this.get_node(i); }, this)) : this._data.checkbox.selected.slice();
+ return full ? $.map(this._data.checkbox.selected, function (i) { return this.get_node(i); }.bind(this)) : this._data.checkbox.selected.slice();
};
/**
* get an array of all top level checked nodes (ignoring children of checked nodes) (if tie_selection is on in the settings this function will return the same as get_top_selected)
@@ -5905,7 +5993,7 @@
tmp.push(i);
}
}
- return full ? $.map(tmp, $.proxy(function (i) { return this.get_node(i); }, this)) : tmp;
+ return full ? $.map(tmp, function (i) { return this.get_node(i); }.bind(this)) : tmp;
};
/**
* get an array of all bottom level checked nodes (ignoring selected parents) (if tie_selection is on in the settings this function will return the same as get_bottom_selected)
@@ -5923,11 +6011,11 @@
obj.push(tmp[i].id);
}
}
- return full ? $.map(obj, $.proxy(function (i) { return this.get_node(i); }, this)) : obj;
+ return full ? $.map(obj, function (i) { return this.get_node(i); }.bind(this)) : obj;
};
this.load_node = function (obj, callback) {
var k, l, i, j, c, tmp;
- if(!$.isArray(obj) && !this.settings.checkbox.tie_selection) {
+ if(!$.vakata.is_array(obj) && !this.settings.checkbox.tie_selection) {
tmp = this.get_node(obj);
if(tmp && tmp.state.loaded) {
for(k = 0, l = tmp.children_d.length; k < l; k++) {
@@ -6155,10 +6243,10 @@
var last_ts = 0, cto = null, ex, ey;
this.element
- .on("init.jstree loading.jstree ready.jstree", $.proxy(function () {
+ .on("init.jstree loading.jstree ready.jstree", function () {
this.get_container_ul().addClass('jstree-contextmenu');
- }, this))
- .on("contextmenu.jstree", ".jstree-anchor", $.proxy(function (e, data) {
+ }.bind(this))
+ .on("contextmenu.jstree", ".jstree-anchor", function (e, data) {
if (e.target.tagName.toLowerCase() === 'input') {
return;
}
@@ -6173,13 +6261,13 @@
if(!this.is_loading(e.currentTarget)) {
this.show_contextmenu(e.currentTarget, e.pageX, e.pageY, e);
}
- }, this))
- .on("click.jstree", ".jstree-anchor", $.proxy(function (e) {
+ }.bind(this))
+ .on("click.jstree", ".jstree-anchor", function (e) {
if(this._data.contextmenu.visible && (!last_ts || (+new Date()) - last_ts > 250)) { // work around safari & macOS ctrl+click
$.vakata.context.hide();
}
last_ts = 0;
- }, this))
+ }.bind(this))
.on("touchstart.jstree", ".jstree-anchor", function (e) {
if(!e.originalEvent || !e.originalEvent.changedTouches || !e.originalEvent.changedTouches[0]) {
return;
@@ -6223,15 +6311,16 @@
});
}
*/
- $(document).on("context_hide.vakata.jstree", $.proxy(function (e, data) {
+ $(document).on("context_hide.vakata.jstree", function (e, data) {
this._data.contextmenu.visible = false;
$(data.reference).removeClass('jstree-context');
- }, this));
+ }.bind(this));
};
this.teardown = function () {
if(this._data.contextmenu.visible) {
$.vakata.context.hide();
}
+ $(document).off("context_hide.vakata.jstree");
parent.teardown.call(this);
};
@@ -6263,10 +6352,10 @@
}
i = s.items;
- if($.isFunction(i)) {
- i = i.call(this, obj, $.proxy(function (i) {
+ if($.vakata.is_function(i)) {
+ i = i.call(this, obj, function (i) {
this._show_contextmenu(obj, x, y, i);
- }, this));
+ }.bind(this));
}
if($.isPlainObject(i)) {
this._show_contextmenu(obj, x, y, i);
@@ -6286,11 +6375,11 @@
this._show_contextmenu = function (obj, x, y, i) {
var d = this.get_node(obj, true),
a = d.children(".jstree-anchor");
- $(document).one("context_show.vakata.jstree", $.proxy(function (e, data) {
+ $(document).one("context_show.vakata.jstree", function (e, data) {
var cls = 'jstree-contextmenu jstree-' + this.get_theme() + '-contextmenu';
$(data.element).addClass(cls);
a.addClass('jstree-context');
- }, this));
+ }.bind(this));
this._data.contextmenu.visible = true;
$.vakata.context.show(a, { 'x' : x, 'y' : y }, i);
/**
@@ -6336,7 +6425,7 @@
},
_execute : function (i) {
i = vakata_context.items[i];
- return i && (!i._disabled || ($.isFunction(i._disabled) && !i._disabled({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }))) && i.action ? i.action.call(null, {
+ return i && (!i._disabled || ($.vakata.is_function(i._disabled) && !i._disabled({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }))) && i.action ? i.action.call(null, {
"item" : i,
"reference" : vakata_context.reference,
"element" : vakata_context.element,
@@ -6361,10 +6450,10 @@
if(!val) { return true; }
vakata_context.items.push(val);
if(!sep && val.separator_before) {
- str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> <"+"/a><"+"/li>";
+ str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'class="vakata-context-no-icons"') + "> <"+"/a><"+"/li>";
}
sep = false;
- str += "<"+"li class='" + (val._class || "") + (val._disabled === true || ($.isFunction(val._disabled) && val._disabled({ "item" : val, "reference" : vakata_context.reference, "element" : vakata_context.element })) ? " vakata-contextmenu-disabled " : "") + "' "+(val.shortcut?" data-shortcut='"+val.shortcut+"' ":'')+">";
+ str += "<"+"li class='" + (val._class || "") + (val._disabled === true || ($.vakata.is_function(val._disabled) && val._disabled({ "item" : val, "reference" : vakata_context.reference, "element" : vakata_context.element })) ? " vakata-contextmenu-disabled " : "") + "' "+(val.shortcut?" data-shortcut='"+val.shortcut+"' ":'')+">";
str += "<"+"a href='#' rel='" + (vakata_context.items.length - 1) + "' " + (val.title ? "title='" + val.title + "'" : "") + ">";
if($.vakata.context.settings.icons) {
str += "<"+"i ";
@@ -6374,14 +6463,14 @@
}
str += "><"+"/i><"+"span class='vakata-contextmenu-sep'> <"+"/span>";
}
- str += ($.isFunction(val.label) ? val.label({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }) : val.label) + (val.shortcut?' ':'') + "<"+"/a>";
+ str += ($.vakata.is_function(val.label) ? val.label({ "item" : i, "reference" : vakata_context.reference, "element" : vakata_context.element }) : val.label) + (val.shortcut?' ':'') + "<"+"/a>";
if(val.submenu) {
tmp = $.vakata.context._parse(val.submenu, true);
if(tmp) { str += tmp; }
}
str += "<"+"/li>";
if(val.separator_after) {
- str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> <"+"/a><"+"/li>";
+ str += "<"+"li class='vakata-context-separator'><"+"a href='#' " + ($.vakata.context.settings.icons ? '' : 'class="vakata-context-no-icons"') + "> <"+"/a><"+"/li>";
sep = true;
}
});
@@ -6489,7 +6578,7 @@
vakata_context.element
.css({ "left" : x, "top" : y })
.show()
- .find('a').first().focus().parent().addClass("vakata-context-hover");
+ .find('a').first().trigger('focus').parent().addClass("vakata-context-hover");
vakata_context.is_visible = true;
/**
* triggered on the document when the contextmenu is shown
@@ -6505,7 +6594,7 @@
},
hide : function () {
if(vakata_context.is_visible) {
- vakata_context.element.hide().find("ul").hide().end().find(':focus').blur().end().detach();
+ vakata_context.element.hide().find("ul").hide().end().find(':focus').trigger('blur').end().detach();
vakata_context.is_visible = false;
/**
* triggered on the document when the contextmenu is hidden
@@ -6561,7 +6650,7 @@
e.preventDefault();
//})
//.on("mouseup", "a", function (e) {
- if(!$(this).blur().parent().hasClass("vakata-context-disabled") && $.vakata.context._execute($(this).attr("rel")) !== false) {
+ if(!$(this).trigger('blur').parent().hasClass("vakata-context-disabled") && $.vakata.context._execute($(this).attr("rel")) !== false) {
$.vakata.context.hide();
}
})
@@ -6576,7 +6665,7 @@
break;
case 37:
if(vakata_context.is_visible) {
- vakata_context.element.find(".vakata-context-hover").last().closest("li").first().find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover").end().end().children('a').focus();
+ vakata_context.element.find(".vakata-context-hover").last().closest("li").first().find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover").end().end().children('a').trigger('focus');
e.stopImmediatePropagation();
e.preventDefault();
}
@@ -6585,14 +6674,14 @@
if(vakata_context.is_visible) {
o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").prevAll("li:not(.vakata-context-separator)").first();
if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").last(); }
- o.addClass("vakata-context-hover").children('a').focus();
+ o.addClass("vakata-context-hover").children('a').trigger('focus');
e.stopImmediatePropagation();
e.preventDefault();
}
break;
case 39:
if(vakata_context.is_visible) {
- vakata_context.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover").children('a').focus();
+ vakata_context.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover").children('a').trigger('focus');
e.stopImmediatePropagation();
e.preventDefault();
}
@@ -6601,7 +6690,7 @@
if(vakata_context.is_visible) {
o = vakata_context.element.find("ul:visible").addBack().last().children(".vakata-context-hover").removeClass("vakata-context-hover").nextAll("li:not(.vakata-context-separator)").first();
if(!o.length) { o = vakata_context.element.find("ul:visible").addBack().last().children("li:not(.vakata-context-separator)").first(); }
- o.addClass("vakata-context-hover").children('a').focus();
+ o.addClass("vakata-context-hover").children('a').trigger('focus');
e.stopImmediatePropagation();
e.preventDefault();
}
@@ -6619,7 +6708,7 @@
e.preventDefault();
var a = vakata_context.element.find('.vakata-contextmenu-shortcut-' + e.which).parent();
if(a.parent().not('.vakata-context-disabled')) {
- a.click();
+ a.trigger('click');
}
});
@@ -6720,7 +6809,13 @@
* @name $.jstree.defaults.dnd.use_html5
* @plugin dnd
*/
- use_html5: false
+ use_html5: false,
+ /**
+ * controls whether items can be dropped anywhere on the tree.
+ * @name $.jstree.defaults.dnd.blank_space_drop
+ * @plugin dnd
+ */
+ blank_space_drop: false
};
var drg, elm;
// TODO: now check works by checking for each node individually, how about max_children, unique, etc?
@@ -6733,7 +6828,7 @@
parent.bind.call(this);
this.element
- .on(this.settings.dnd.use_html5 ? 'dragstart.jstree' : 'mousedown.jstree touchstart.jstree', this.settings.dnd.large_drag_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) {
+ .on(this.settings.dnd.use_html5 ? 'dragstart.jstree' : 'mousedown.jstree touchstart.jstree', this.settings.dnd.large_drag_target ? '.jstree-node' : '.jstree-anchor', function (e) {
if(this.settings.dnd.large_drag_target && $(e.target).closest('.jstree-node')[0] !== e.currentTarget) {
return true;
}
@@ -6746,8 +6841,8 @@
if(this.settings.core.force_text) {
txt = $.vakata.html.escape(txt);
}
- if(obj && obj.id && obj.id !== $.jstree.root && (e.which === 1 || e.type === "touchstart" || e.type === "dragstart") &&
- (this.settings.dnd.is_draggable === true || ($.isFunction(this.settings.dnd.is_draggable) && this.settings.dnd.is_draggable.call(this, (mlt > 1 ? this.get_top_selected(true) : [obj]), e)))
+ if(obj && (obj.id || obj.id === 0) && obj.id !== $.jstree.root && (e.which === 1 || e.type === "touchstart" || e.type === "dragstart") &&
+ (this.settings.dnd.is_draggable === true || ($.vakata.is_function(this.settings.dnd.is_draggable) && this.settings.dnd.is_draggable.call(this, (mlt > 1 ? this.get_top_selected(true) : [obj]), e)))
) {
drg = { 'jstree' : true, 'origin' : this, 'obj' : this.get_node(obj,true), 'nodes' : mlt > 1 ? this.get_top_selected() : [obj.id] };
elm = e.currentTarget;
@@ -6755,10 +6850,10 @@
$.vakata.dnd._trigger('start', e, { 'helper': $(), 'element': elm, 'data': drg });
} else {
this.element.trigger('mousedown.jstree');
- return $.vakata.dnd.start(e, drg, ' ' + txt + '+
');
+ return $.vakata.dnd.start(e, drg, ' ' + txt + '+
');
}
}
- }, this));
+ }.bind(this));
if (this.settings.dnd.use_html5) {
this.element
.on('dragover.jstree', function (e) {
@@ -6771,11 +6866,11 @@
// $.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg });
// return false;
// }, this))
- .on('drop.jstree', $.proxy(function (e) {
+ .on('drop.jstree', function (e) {
e.preventDefault();
$.vakata.dnd._trigger('stop', e, { 'helper': $(), 'element': elm, 'data': drg });
return false;
- }, this));
+ }.bind(this));
}
};
this.redraw_node = function(obj, deep, callback, force_render) {
@@ -6857,7 +6952,7 @@
// if are hovering the container itself add a new root node
//console.log(data.event);
- if( (data.event.target === ins.element[0] || data.event.target === ins.get_container_ul()[0]) && ins.get_container_ul().children().length === 0) {
+ if( (data.event.target === ins.element[0] || data.event.target === ins.get_container_ul()[0]) && (ins.get_container_ul().children().length === 0 || ins.settings.dnd.blank_space_drop)) {
ok = true;
for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) {
ok = ok && ins.check( (data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey)) ) ? "copy_node" : "move_node"), (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), $.jstree.root, 'last', { 'dnd' : true, 'ref' : ins.get_node($.jstree.root), 'pos' : 'i', 'origin' : data.data.origin, 'is_multi' : (data.data.origin && data.data.origin !== ins), 'is_foreign' : (!data.data.origin) });
@@ -6876,6 +6971,7 @@
else {
// if we are hovering a tree node
ref = ins.settings.dnd.large_drop_target ? $(data.event.target).closest('.jstree-node').children('.jstree-anchor') : $(data.event.target).closest('.jstree-anchor');
+
if(ref && ref.length && ref.parent().is('.jstree-closed, .jstree-open, .jstree-leaf')) {
off = ref.offset();
rel = (data.event.pageY !== undefined ? data.event.pageY : data.event.originalEvent.pageY) - off.top;
@@ -7206,7 +7302,7 @@
vakata_dnd.scroll_e = false;
$($(e.target).parentsUntil("body").addBack().get().reverse())
.filter(function () {
- return (/^auto|scroll$/).test($(this).css("overflow")) &&
+ return this.ownerDocument && (/^auto|scroll$/).test($(this).css("overflow")) &&
(this.scrollHeight > this.offsetHeight || this.scrollWidth > this.offsetWidth);
})
.each(function () {
@@ -7287,7 +7383,7 @@
}
else {
if(e.type === "touchend" && e.target === vakata_dnd.target) {
- var to = setTimeout(function () { $(e.target).click(); }, 100);
+ var to = setTimeout(function () { $(e.target).trigger('click'); }, 100);
$(e.target).one('click', function() { if(to) { clearTimeout(to); } });
}
}
@@ -7348,8 +7444,8 @@
}
this._data.massload = {};
if (toLoad.length) {
- if($.isFunction(s)) {
- return s.call(this, toLoad, $.proxy(function (data) {
+ if($.vakata.is_function(s)) {
+ return s.call(this, toLoad, function (data) {
var i, j;
if(data) {
for(i in data) {
@@ -7365,18 +7461,18 @@
}
}
parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
- }, this));
+ }.bind(this));
}
if(typeof s === 'object' && s && s.url) {
s = $.extend(true, {}, s);
- if($.isFunction(s.url)) {
+ if($.vakata.is_function(s.url)) {
s.url = s.url.call(this, toLoad);
}
- if($.isFunction(s.data)) {
+ if($.vakata.is_function(s.data)) {
s.data = s.data.call(this, toLoad);
}
return $.ajax(s)
- .done($.proxy(function (data,t,x) {
+ .done(function (data,t,x) {
var i, j;
if(data) {
for(i in data) {
@@ -7392,10 +7488,10 @@
}
}
parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
- }, this))
- .fail($.proxy(function (f) {
+ }.bind(this))
+ .fail(function (f) {
parent._load_nodes.call(this, nodes, callback, is_callback, force_reload);
- }, this));
+ }.bind(this));
}
}
}
@@ -7503,7 +7599,7 @@
this._data.search.hdn = [];
this.element
- .on("search.jstree", $.proxy(function (e, data) {
+ .on("search.jstree", function (e, data) {
if(this._data.search.som && data.res.length) {
var m = this._model.data, i, j, p = [], k, l;
for(i = 0, j = data.res.length; i < j; i++) {
@@ -7524,13 +7620,13 @@
this.show_node(p, true);
this.redraw(true);
}
- }, this))
- .on("clear_search.jstree", $.proxy(function (e, data) {
+ }.bind(this))
+ .on("clear_search.jstree", function (e, data) {
if(this._data.search.som && data.res.length) {
this.show_node(this._data.search.hdn, true);
this.redraw(true);
}
- }, this));
+ }.bind(this));
};
/**
* used to search the tree nodes for a given string
@@ -7544,11 +7640,11 @@
* @trigger search.jstree
*/
this.search = function (str, skip_async, show_only_matches, inside, append, show_only_matches_children) {
- if(str === false || $.trim(str.toString()) === "") {
+ if(str === false || $.vakata.trim(str.toString()) === "") {
return this.clear_search();
}
inside = this.get_node(inside);
- inside = inside && inside.id ? inside.id : null;
+ inside = inside && (inside.id || inside.id === 0) ? inside.id : null;
str = str.toString();
var s = this.settings.search,
a = s.ajax ? s.ajax : false,
@@ -7566,13 +7662,13 @@
show_only_matches_children = s.show_only_matches_children;
}
if(!skip_async && a !== false) {
- if($.isFunction(a)) {
- return a.call(this, str, $.proxy(function (d) {
+ if($.vakata.is_function(a)) {
+ return a.call(this, str, function (d) {
if(d && d.d) { d = d.d; }
- this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () {
+ this._load_nodes(!$.vakata.is_array(d) ? [] : $.vakata.array_unique(d), function () {
this.search(str, true, show_only_matches, inside, append, show_only_matches_children);
});
- }, this), inside);
+ }.bind(this), inside);
}
else {
a = $.extend({}, a);
@@ -7585,16 +7681,16 @@
this._data.search.lastRequest.abort();
}
this._data.search.lastRequest = $.ajax(a)
- .fail($.proxy(function () {
+ .fail(function () {
this._data.core.last_error = { 'error' : 'ajax', 'plugin' : 'search', 'id' : 'search_01', 'reason' : 'Could not load search parents', 'data' : JSON.stringify(a) };
this.settings.core.error.call(this, this._data.core.last_error);
- }, this))
- .done($.proxy(function (d) {
+ }.bind(this))
+ .done(function (d) {
if(d && d.d) { d = d.d; }
- this._load_nodes(!$.isArray(d) ? [] : $.vakata.array_unique(d), function () {
+ this._load_nodes(!$.vakata.is_array(d) ? [] : $.vakata.array_unique(d), function () {
this.search(str, true, show_only_matches, inside, append, show_only_matches_children);
});
- }, this));
+ }.bind(this));
return this._data.search.lastRequest;
}
}
@@ -7736,7 +7832,7 @@
};
}
search = function (text) {
- text = options.caseSensitive ? text : text.toLowerCase();
+ text = options.caseSensitive ? text.toString() : text.toString().toLowerCase();
if(pattern === text || text.indexOf(pattern) !== -1) {
return {
isMatch: true,
@@ -7848,17 +7944,17 @@
this.bind = function () {
parent.bind.call(this);
this.element
- .on("model.jstree", $.proxy(function (e, data) {
+ .on("model.jstree", function (e, data) {
this.sort(data.parent, true);
- }, this))
- .on("rename_node.jstree create_node.jstree", $.proxy(function (e, data) {
+ }.bind(this))
+ .on("rename_node.jstree create_node.jstree", function (e, data) {
this.sort(data.parent || data.node.parent, false);
this.redraw_node(data.parent || data.node.parent, true);
- }, this))
- .on("move_node.jstree copy_node.jstree", $.proxy(function (e, data) {
+ }.bind(this))
+ .on("move_node.jstree copy_node.jstree", function (e, data) {
this.sort(data.parent, false);
this.redraw_node(data.parent, true);
- }, this));
+ }.bind(this));
};
/**
* used to sort a node's children
@@ -7873,7 +7969,7 @@
var i, j;
obj = this.get_node(obj);
if(obj && obj.children && obj.children.length) {
- obj.children.sort($.proxy(this.settings.sort, this));
+ obj.children.sort(this.settings.sort.bind(this));
if(deep) {
for(i = 0, j = obj.children_d.length; i < j; i++) {
this.sort(obj.children_d[i], false);
@@ -7933,11 +8029,11 @@
$.jstree.plugins.state = function (options, parent) {
this.bind = function () {
parent.bind.call(this);
- var bind = $.proxy(function () {
- this.element.on(this.settings.state.events, $.proxy(function () {
+ var bind = function () {
+ this.element.on(this.settings.state.events, function () {
if(to) { clearTimeout(to); }
- to = setTimeout($.proxy(function () { this.save_state(); }, this), 100);
- }, this));
+ to = setTimeout(function () { this.save_state(); }.bind(this), 100);
+ }.bind(this));
/**
* triggered when the state plugin is finished restoring the state (and immediately after ready if there is no state to restore).
* @event
@@ -7945,12 +8041,12 @@
* @plugin state
*/
this.trigger('state_ready');
- }, this);
+ }.bind(this);
this.element
- .on("ready.jstree", $.proxy(function (e, data) {
+ .on("ready.jstree", function (e, data) {
this.element.one("restore_state.jstree", bind);
if(!this.restore_state()) { bind(); }
- }, this));
+ }.bind(this));
};
/**
* save the state
@@ -7975,7 +8071,7 @@
if(!!k) { try { k = JSON.parse(k); } catch(ex) { return false; } }
if(!!k && k.ttl && k.sec && +(new Date()) - k.sec > k.ttl) { return false; }
if(!!k && k.state) { k = k.state; }
- if(!!k && $.isFunction(this.settings.state.filter)) { k = this.settings.state.filter.call(this, k); }
+ if(!!k && $.vakata.is_function(this.settings.state.filter)) { k = this.settings.state.filter.call(this, k); }
if(!!k) {
if (!this.settings.state.preserve_loaded) {
delete k.core.loaded;
@@ -8060,7 +8156,7 @@
};
this.bind = function () {
this.element
- .on('model.jstree', $.proxy(function (e, data) {
+ .on('model.jstree', function (e, data) {
var m = this._model.data,
dpc = data.nodes,
t = this.settings.types,
@@ -8112,7 +8208,7 @@
}
}
m[$.jstree.root].type = $.jstree.root;
- }, this));
+ }.bind(this));
parent.bind.call(this);
};
this.get_json = function (obj, options, flat) {
@@ -8121,9 +8217,9 @@
opt = options ? $.extend(true, {}, options, {no_id:false}) : {},
tmp = parent.get_json.call(this, obj, opt, flat);
if(tmp === false) { return false; }
- if($.isArray(tmp)) {
+ if($.vakata.is_array(tmp)) {
for(i = 0, j = tmp.length; i < j; i++) {
- tmp[i].type = tmp[i].id && m[tmp[i].id] && m[tmp[i].id].type ? m[tmp[i].id].type : "default";
+ tmp[i].type = (tmp[i].id || tmp[i].id === 0) && m[tmp[i].id] && m[tmp[i].id].type ? m[tmp[i].id].type : "default";
if(options && options.no_id) {
delete tmp[i].id;
if(tmp[i].li_attr && tmp[i].li_attr.id) {
@@ -8136,7 +8232,7 @@
}
}
else {
- tmp.type = tmp.id && m[tmp.id] && m[tmp.id].type ? m[tmp.id].type : "default";
+ tmp.type = (tmp.id || tmp.id === 0) && m[tmp.id] && m[tmp.id].type ? m[tmp.id].type : "default";
if(options && options.no_id) {
tmp = this._delete_ids(tmp);
}
@@ -8144,7 +8240,7 @@
return tmp;
};
this._delete_ids = function (tmp) {
- if($.isArray(tmp)) {
+ if($.vakata.is_array(tmp)) {
for(var i = 0, j = tmp.length; i < j; i++) {
tmp[i] = this._delete_ids(tmp[i]);
}
@@ -8157,16 +8253,16 @@
if(tmp.a_attr && tmp.a_attr.id) {
delete tmp.a_attr.id;
}
- if(tmp.children && $.isArray(tmp.children)) {
+ if(tmp.children && $.vakata.is_array(tmp.children)) {
tmp.children = this._delete_ids(tmp.children);
}
return tmp;
};
this.check = function (chk, obj, par, pos, more) {
if(parent.check.call(this, chk, obj, par, pos, more) === false) { return false; }
- obj = obj && obj.id ? obj : this.get_node(obj);
- par = par && par.id ? par : this.get_node(par);
- var m = obj && obj.id ? (more && more.origin ? more.origin : $.jstree.reference(obj.id)) : null, tmp, d, i, j;
+ obj = obj && (obj.id || obj.id === 0) ? obj : this.get_node(obj);
+ par = par && (par.id || par.id === 0) ? par : this.get_node(par);
+ var m = obj && (obj.id || obj.id === 0) ? (more && more.origin ? more.origin : $.jstree.reference(obj.id)) : null, tmp, d, i, j;
m = m && m._model && m._model.data ? m._model.data : null;
switch(chk) {
case "create_node":
@@ -8175,11 +8271,11 @@
if(chk !== 'move_node' || $.inArray(obj.id, par.children) === -1) {
tmp = this.get_rules(par);
if(tmp.max_children !== undefined && tmp.max_children !== -1 && tmp.max_children === par.children.length) {
- this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_01', 'reason' : 'max_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
+ this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_01', 'reason' : 'max_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && (obj.id || obj.id === 0) ? obj.id : false, 'par' : par && (par.id || par.id === 0) ? par.id : false }) };
return false;
}
if(tmp.valid_children !== undefined && tmp.valid_children !== -1 && $.inArray((obj.type || 'default'), tmp.valid_children) === -1) {
- this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_02', 'reason' : 'valid_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
+ this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_02', 'reason' : 'valid_children prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && (obj.id || obj.id === 0) ? obj.id : false, 'par' : par && (par.id || par.id === 0) ? par.id : false }) };
return false;
}
if(m && obj.children_d && obj.parents) {
@@ -8192,7 +8288,7 @@
if(d <= 0 || d === undefined) { d = 1; }
do {
if(tmp.max_depth !== undefined && tmp.max_depth !== -1 && tmp.max_depth < d) {
- this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_03', 'reason' : 'max_depth prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
+ this._data.core.last_error = { 'error' : 'check', 'plugin' : 'types', 'id' : 'types_03', 'reason' : 'max_depth prevents function: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && (obj.id || obj.id === 0) ? obj.id : false, 'par' : par && (par.id || par.id === 0) ? par.id : false }) };
return false;
}
par = this.get_node(par.parent);
@@ -8241,7 +8337,7 @@
*/
this.set_type = function (obj, type) {
var m = this._model.data, t, t1, t2, old_type, old_icon, k, d, a;
- if($.isArray(obj)) {
+ if($.vakata.is_array(obj)) {
obj = obj.slice();
for(t1 = 0, t2 = obj.length; t1 < t2; t1++) {
this.set_type(obj[t1], type);
@@ -8390,7 +8486,7 @@
*/
trim_whitespace : false,
/**
- * A callback executed in the instance's scope when a new node is created and the name is already taken, the two arguments are the conflicting name and the counter. The default will produce results like `New node (2)`.
+ * A callback executed in the instance's scope when a new node is created with no name and a node with the default name already exists, the two arguments are the conflicting name and the counter. The default will produce results like `New node (2)`.
* @name $.jstree.defaults.unique.duplicate
* @plugin unique
*/
@@ -8402,8 +8498,8 @@
$.jstree.plugins.unique = function (options, parent) {
this.check = function (chk, obj, par, pos, more) {
if(parent.check.call(this, chk, obj, par, pos, more) === false) { return false; }
- obj = obj && obj.id ? obj : this.get_node(obj);
- par = par && par.id ? par : this.get_node(par);
+ obj = obj && (obj.id || obj.id === 0) ? obj : this.get_node(obj);
+ par = par && (par.id || par.id === 0) ? par : this.get_node(par);
if(!par || !par.children) { return true; }
var n = chk === "rename_node" ? pos : obj.text,
c = [],
@@ -8435,32 +8531,32 @@
}
i = ($.inArray(n, c) === -1 || (obj.text && t === n));
if(!i) {
- this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_01', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
+ this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_01', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && (obj.id || obj.id === 0) ? obj.id : false, 'par' : par && (par.id || par.id === 0) ? par.id : false }) };
}
return i;
case "create_node":
i = ($.inArray(n, c) === -1);
if(!i) {
- this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_04', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
+ this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_04', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && (obj.id || obj.id === 0) ? obj.id : false, 'par' : par && (par.id || par.id === 0) ? par.id : false }) };
}
return i;
case "copy_node":
i = ($.inArray(n, c) === -1);
if(!i) {
- this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_02', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
+ this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_02', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && (obj.id || obj.id === 0) ? obj.id : false, 'par' : par && (par.id || par.id === 0) ? par.id : false }) };
}
return i;
case "move_node":
i = ( (obj.parent === par.id && (!more || !more.is_multi)) || $.inArray(n, c) === -1);
if(!i) {
- this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_03', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && obj.id ? obj.id : false, 'par' : par && par.id ? par.id : false }) };
+ this._data.core.last_error = { 'error' : 'check', 'plugin' : 'unique', 'id' : 'unique_03', 'reason' : 'Child with name ' + n + ' already exists. Preventing: ' + chk, 'data' : JSON.stringify({ 'chk' : chk, 'pos' : pos, 'obj' : obj && (obj.id || obj.id === 0) ? obj.id : false, 'par' : par && (par.id || par.id === 0) ? par.id : false }) };
}
return i;
}
return true;
};
this.create_node = function (par, node, pos, callback, is_loaded) {
- if(!node || node.text === undefined) {
+ if(!node || (typeof node === 'object' && node.text === undefined)) {
if(par === null) {
par = $.jstree.root;
}
@@ -8530,17 +8626,17 @@
parent.bind.call(this);
this.element
- .on('ready.jstree set_state.jstree', $.proxy(function () {
+ .on('ready.jstree set_state.jstree', function () {
this.hide_dots();
- }, this))
- .on("init.jstree loading.jstree ready.jstree", $.proxy(function () {
+ }.bind(this))
+ .on("init.jstree loading.jstree ready.jstree", function () {
//div.style.height = this._data.core.li_height + 'px';
this.get_container_ul().addClass('jstree-wholerow-ul');
- }, this))
- .on("deselect_all.jstree", $.proxy(function (e, data) {
+ }.bind(this))
+ .on("deselect_all.jstree", function (e, data) {
this.element.find('.jstree-wholerow-clicked').removeClass('jstree-wholerow-clicked');
- }, this))
- .on("changed.jstree", $.proxy(function (e, data) {
+ }.bind(this))
+ .on("changed.jstree", function (e, data) {
this.element.find('.jstree-wholerow-clicked').removeClass('jstree-wholerow-clicked');
var tmp = false, i, j;
for(i = 0, j = data.selected.length; i < j; i++) {
@@ -8549,21 +8645,21 @@
tmp.children('.jstree-wholerow').addClass('jstree-wholerow-clicked');
}
}
- }, this))
- .on("open_node.jstree", $.proxy(function (e, data) {
+ }.bind(this))
+ .on("open_node.jstree", function (e, data) {
this.get_node(data.node, true).find('.jstree-clicked').parent().children('.jstree-wholerow').addClass('jstree-wholerow-clicked');
- }, this))
- .on("hover_node.jstree dehover_node.jstree", $.proxy(function (e, data) {
+ }.bind(this))
+ .on("hover_node.jstree dehover_node.jstree", function (e, data) {
if(e.type === "hover_node" && this.is_disabled(data.node)) { return; }
this.get_node(data.node, true).children('.jstree-wholerow')[e.type === "hover_node"?"addClass":"removeClass"]('jstree-wholerow-hovered');
- }, this))
- .on("contextmenu.jstree", ".jstree-wholerow", $.proxy(function (e) {
+ }.bind(this))
+ .on("contextmenu.jstree", ".jstree-wholerow", function (e) {
if (this._data.contextmenu) {
e.preventDefault();
var tmp = $.Event('contextmenu', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey, pageX : e.pageX, pageY : e.pageY });
$(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp);
}
- }, this))
+ }.bind(this))
/*!
.on("mousedown.jstree touchstart.jstree", ".jstree-wholerow", function (e) {
if(e.target === e.currentTarget) {
@@ -8576,28 +8672,28 @@
.on("click.jstree", ".jstree-wholerow", function (e) {
e.stopImmediatePropagation();
var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey });
- $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus();
+ $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).trigger('focus');
})
.on("dblclick.jstree", ".jstree-wholerow", function (e) {
e.stopImmediatePropagation();
var tmp = $.Event('dblclick', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey });
- $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus();
+ $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).trigger('focus');
})
- .on("click.jstree", ".jstree-leaf > .jstree-ocl", $.proxy(function (e) {
+ .on("click.jstree", ".jstree-leaf > .jstree-ocl", function (e) {
e.stopImmediatePropagation();
var tmp = $.Event('click', { metaKey : e.metaKey, ctrlKey : e.ctrlKey, altKey : e.altKey, shiftKey : e.shiftKey });
- $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).focus();
- }, this))
- .on("mouseover.jstree", ".jstree-wholerow, .jstree-icon", $.proxy(function (e) {
+ $(e.currentTarget).closest(".jstree-node").children(".jstree-anchor").first().trigger(tmp).trigger('focus');
+ }.bind(this))
+ .on("mouseover.jstree", ".jstree-wholerow, .jstree-icon", function (e) {
e.stopImmediatePropagation();
if(!this.is_disabled(e.currentTarget)) {
this.hover_node(e.currentTarget);
}
return false;
- }, this))
- .on("mouseleave.jstree", ".jstree-node", $.proxy(function (e) {
+ }.bind(this))
+ .on("mouseleave.jstree", ".jstree-node", function (e) {
this.dehover_node(e.currentTarget);
- }, this));
+ }.bind(this));
};
this.teardown = function () {
if(this.settings.wholerow) {
diff --git a/dms_field/static/src/js/base/dms_tree_controller.js b/dms_field/static/src/js/base/dms_tree_controller.js
deleted file mode 100644
index 6b57c7c83..000000000
--- a/dms_field/static/src/js/base/dms_tree_controller.js
+++ /dev/null
@@ -1,608 +0,0 @@
-odoo.define("dms.DmsTreeController", function (require) {
- "use strict";
-
- var session = require("web.session");
- var field_utils = require("web.field_utils");
-
- var mimetype = require("dms_field.mimetype");
-
- var Domain = require("web.Domain");
- var DragDrop = require("dms_field.DragDrop");
- var BasicController = require("web.BasicController");
- var FormController = require("web.FormController");
- var preview = require("mail_preview_base.preview");
- var FieldPreviewViewer = preview.FieldPreviewViewer;
- var dialogs = require("web.view_dialogs");
- var core = require("web.core");
- var _t = core._t;
-
- var DMSTreeController = {
- init: function (parent, model, renderer, params) {
- this._super.apply(this, arguments);
- this.setParams(params);
- },
- sanitizeDMSModel: function (model) {
- return model;
- },
- setParams: function (params) {
- var model = params.modelName;
- model = this.sanitizeDMSModel(model);
- var storage_domain = [];
- var directory_domain = [];
- var autocompute_directory = false;
- var show_storage = true;
- if (model === "dms.storage") {
- storage_domain = [["id", "in", params.initialState.res_ids]];
- directory_domain = [];
- } else if (model === "dms.field.template") {
- if (params.initialState.data.storage_id.res_id) {
- storage_domain = [
- ["id", "=", params.initialState.data.storage_id.res_id],
- ];
- } else {
- storage_domain = [["id", "=", 0]];
- }
- directory_domain = [
- [
- "root_directory_id",
- "in",
- params.initialState.data.dms_directory_ids.res_ids,
- ],
- ];
- } else if (model === "dms.directory") {
- storage_domain = [
- ["storage_directory_ids", "in", params.initialState.res_ids],
- ];
- directory_domain = [
- "|",
- ["id", "in", params.initialState.res_ids],
- ["child_directory_ids", "in", params.initialState.res_ids],
- ];
- } else {
- storage_domain = [["field_template_ids.model", "=", model]];
- autocompute_directory = true;
- show_storage = false;
- }
- this.params = $.extend(
- true,
- {},
- {
- storage: {
- domain: storage_domain,
- context: session.user_context,
- show: show_storage,
- },
- directory: {
- domain: directory_domain,
- context: session.user_context,
- autocompute_directory: autocompute_directory,
- },
- file: {
- domain: [],
- context: session.user_context,
- show: true,
- },
- initial: undefined,
- }
- );
- },
- _onDMSLoad: function (ev) {
- var self = this;
- var node = ev.data.node;
- var params = ev.data.params;
- var args = this._buildDMSArgs(params);
- var result = false;
- if (!node || node.id === "#") {
- if (args.initial) {
- result = $.when(args.initial);
- } else {
- result = this._loadInitialData(args);
- }
- } else {
- result = this._loadNode(node, args);
- }
- return result.then(function (data) {
- ev.data.callback.call(self.renderer, data);
- if (self.empty_storages.length > 0) {
- self.renderer.$el
- .find(".o_dms_add_directory")
- .removeClass("o_hidden");
- }
- });
- },
- _buildDMSArgs: function (args) {
- return $.extend(
- true,
- {
- search: {
- operator: "ilike",
- },
- },
- this.params,
- args || {}
- );
- },
- _buildDMSDomain: function (base, domain, autocompute_directory) {
- var result = new Domain(base);
- if (autocompute_directory) {
- result._addSubdomain([["res_id", "=", this.renderer.state.res_id]]);
- } else {
- result._addSubdomain(domain || []);
- }
- return result.toArray();
- },
- _loadStorages: function (args) {
- return this._rpc({
- fields: _.union(args.storage.fields || [], [
- "name",
- "count_storage_directories",
- ]),
- domain: args.storage.domain || [],
- context: args.storage.context || session.user_context,
- model: "dms.storage",
- method: "search_read",
- });
- },
- _loadDirectories: function (operator, value, args) {
- return this._rpc({
- model: "dms.directory",
- method: "search_read_parents",
- kwargs: {
- fields: _.union(args.directory.fields || [], [
- "permission_read",
- "permission_create",
- "permission_write",
- "permission_unlink",
- "count_directories",
- "count_files",
- "name",
- "parent_id",
- "icon_url",
- "count_total_directories",
- "count_total_files",
- "human_size",
- "count_elements",
- "__last_update",
- ]),
- domain: this._buildDMSDomain(
- [["storage_id", operator, value]],
- args.directory.domain,
- args.directory.autocompute_directory
- ),
- context: args.directory.context || session.user_context,
- },
- });
- },
- _loadDirectoriesSingle: function (storage_id, args) {
- return this._loadDirectories("=", storage_id, args);
- },
- _loadSubdirectories: function (operator, value, args) {
- return this._rpc({
- model: "dms.directory",
- method: "search_read",
- fields: _.union(args.directory.fields || [], [
- "permission_read",
- "permission_create",
- "permission_write",
- "permission_unlink",
- "count_directories",
- "count_files",
- "name",
- "parent_id",
- "icon_url",
- "count_total_directories",
- "count_total_files",
- "human_size",
- "count_elements",
- "__last_update",
- ]),
- domain: this._buildDMSDomain(
- [["parent_id", operator, value]],
- args.directory.domain,
- false
- ),
- context: args.file.context || session.user_context,
- });
- },
- _loadSubdirectoriesSingle: function (directory_id, args) {
- return this._loadSubdirectories("=", directory_id, args);
- },
- _loadFiles: function (operator, value, args) {
- return this._rpc({
- model: "dms.file",
- method: "search_read",
- fields: _.union(args.file.fields || [], [
- "permission_read",
- "permission_create",
- "permission_write",
- "permission_unlink",
- "name",
- "mimetype",
- "directory_id",
- "human_size",
- "is_locked",
- "is_lock_editor",
- "extension",
- "__last_update",
- ]),
- domain: this._buildDMSDomain(
- [["directory_id", operator, value]],
- args.file.domain
- ),
- context: args.file.context || session.user_context,
- });
- },
- _loadFilesSingle: function (directory_id, args) {
- return this._loadFiles("=", directory_id, args);
- },
- _loadInitialData: function (args) {
- var self = this;
- var data_loaded = $.Deferred();
- this.empty_storages = [];
- this._loadStorages(args).then(
- function (storages) {
- var loading_data_parts = [];
- _.each(
- storages,
- function (storage, index) {
- if (storage.count_storage_directories > 0) {
- var directory_loaded = $.Deferred();
- loading_data_parts.push(directory_loaded);
- this._loadDirectoriesSingle(storage.id, args).then(
- function (directories) {
- if (directories.length > 0) {
- storages[index].directories = directories;
- } else if (
- self.modelName !== "dms.directory" &&
- self.modelName !== "dms.storage"
- ) {
- self.empty_storages.push(storage);
- }
- directory_loaded.resolve();
- }
- );
- } else if (
- self.modelName !== "dms.directory" &&
- self.modelName !== "dms.storage"
- ) {
- self.empty_storages.push(storage);
- }
- }.bind(this)
- );
- $.when.apply($, loading_data_parts).then(
- function () {
- if (args.storage.show) {
- var result = _.chain(storages)
- .map(
- function (storage) {
- if (!storage.directories) {
- return undefined;
- }
- var children = _.map(
- storage.directories || [],
- function (directory) {
- return this._makeNodeDirectory(
- directory,
- args.file.show
- );
- }.bind(this)
- );
- return this._makeNodeStorage(
- storage,
- children
- );
- }.bind(this)
- )
- .filter(function (node) {
- return node;
- })
- .value();
- data_loaded.resolve(result);
- } else {
- var nodes = [];
- _.each(
- storages,
- function (storage) {
- _.each(
- storage.directories,
- function (directory) {
- nodes.push(
- this._makeNodeDirectory(
- directory,
- args.file.show,
- storage
- )
- );
- }.bind(this)
- );
- }.bind(this)
- );
- data_loaded.resolve(nodes);
- }
- }.bind(this)
- );
- // Launch _update_overlay to show the drag and drop
- this._update_overlay();
- }.bind(this)
- );
- return data_loaded;
- },
- _loadNode: function (node, args) {
- var result = $.Deferred();
- if (node.data && node.data.model === "dms.storage") {
- this._loadDirectoriesSingle(node.data.data.id, args).then(
- function (directories) {
- var directory_nodes = _.map(
- directories,
- function (directory) {
- return this._makeNodeDirectory(
- directory,
- args.file.show
- );
- }.bind(this)
- );
- result.resolve(directory_nodes);
- }.bind(this)
- );
- } else if (node.data && node.data.model === "dms.directory") {
- var files_loaded = $.Deferred();
- var directories_loaded = $.Deferred();
- this._loadSubdirectoriesSingle(node.data.data.id, args).then(
- function (directories) {
- var directory_nodes = _.map(
- directories,
- function (directory) {
- return this._makeNodeDirectory(
- directory,
- args.file.show
- );
- }.bind(this)
- );
- directories_loaded.resolve(directory_nodes);
- }.bind(this)
- );
- if (args.file.show) {
- this._loadFilesSingle(node.data.data.id, args).then(
- function (files) {
- var file_nodes = _.map(
- files,
- function (file) {
- return this._makeNodeFile(file);
- }.bind(this)
- );
- files_loaded.resolve(file_nodes);
- }.bind(this)
- );
- } else {
- files_loaded.resolve([]);
- }
- $.when(directories_loaded, files_loaded).then(function (
- directories,
- files
- ) {
- result.resolve(directories.concat(files));
- });
- } else {
- result.resolve([]);
- }
- return result;
- },
- _makeDataPoint: function (dt) {
- return this.model._makeDataPoint(dt);
- },
- _getDataPoint: function (datapointId, attributes) {
- return this.model.get(datapointId, attributes);
- },
- _makeNodeStorage: function (storage, children) {
- var dt = this._makeDataPoint({
- data: storage,
- modelName: "dms.storage",
- });
- return {
- id: "storage_" + storage.id,
- text: storage.name,
- icon: "fa fa-database",
- type: "storage",
- data: dt,
- children: children,
- };
- },
- _makeNodeDirectory: function (directory, showFiles, storage) {
- var data = _.extend(directory, {
- name: directory.name,
- perm_read: directory.permission_read,
- perm_create: directory.permission_create,
- perm_write: directory.permission_write,
- perm_unlink: directory.permission_unlink,
- icon_url: directory.icon_url,
- count_total_directories: directory.count_total_directories,
- count_total_files: directory.count_total_files,
- human_size: directory.human_size,
- count_elements: directory.count_elements,
- });
- if (
- storage &&
- this.modelName !== "dms.directory" &&
- this.modelName !== "dms.storage"
- ) {
- // We are assuming this is a record directory, so disabling actions
- data.name = storage.name;
- data.storage = true;
- }
- var dt = this._makeDataPoint({
- data: data,
- modelName: "dms.directory",
- });
- dt.parent = directory.parent_id
- ? "directory_" + directory.parent_id[0]
- : "#";
- var directoryNode = {
- id: dt.id,
- text: directory.name,
- icon: "fa fa-folder-o",
- type: "directory",
- data: dt,
- };
- if (showFiles) {
- directoryNode.children =
- directory.count_directories + directory.count_files > 0;
- } else {
- directoryNode.children = directory.count_directories > 0;
- }
- return directoryNode;
- },
- _makeNodeFile: function (file) {
- var data = _.extend(file, {
- filename: file.name,
- display_name: file.name,
- binary_size: field_utils.format.binary_size(file.size),
- perm_read: file.permission_read,
- perm_create:
- file.permission_create && (!file.is_locked || file.is_lock_editor),
- perm_write:
- file.permission_write && (!file.is_locked || file.is_lock_editor),
- perm_unlink:
- file.permission_unlink && (!file.is_locked || file.is_lock_editor),
- });
- var dt = this._makeDataPoint({
- data: data,
- modelName: "dms.file",
- });
- return {
- id: dt.id,
- text: dt.data.display_name,
- icon: mimetype.mimetype2fa(dt.data.mimetype, {prefix: "fa fa-"}),
- type: "file",
- data: dt,
- };
- },
- _onDMSPreviewFile: function (ev) {
- var record = this._getDataPoint(ev.data.id, {raw: true});
- var fieldName = "content";
- var file_mimetype = record.data.mimetype;
- var type = file_mimetype.split("/").shift();
- if (
- type === "video" ||
- type === "image" ||
- file_mimetype === "application/pdf"
- ) {
- var attachmentViewer = new FieldPreviewViewer(
- this,
- [
- {
- mimetype: record.data.mimetype,
- id: record.data.id,
- fileType: record.data.mimetype,
- name: record.data.name,
- },
- ],
- record.data.id,
- record.model,
- fieldName
- );
- attachmentViewer.appendTo($("body"));
- } else {
- window.location =
- "/web/content/" +
- record.model +
- "/" +
- record.data.id +
- "/" +
- fieldName +
- "/" +
- record.data.name +
- "?download=true";
- }
- },
- _onDMSOpenRecord: function (event) {
- event.stopPropagation();
- var self = this;
- var record = this.model.get(event.data.id, {raw: true});
- new dialogs.FormViewDialog(self, {
- context: event.data.context,
- fields_view: event.data.fields_view,
- on_saved: event.data.on_saved,
- on_remove: event.data.on_remove,
- readonly: event.data.readonly,
- deletable: event.data.deletable,
- res_id: record.res_id,
- res_model: record.model,
- title: _t("Open: ") + event.data.string,
- }).open();
- },
- _onDMSEmptyStorages: function (event) {
- event.data.data.model = this.modelName;
- event.data.data.empty_storages = this.empty_storages;
- event.data.data.res_id = this.renderer.state.res_id;
- },
- _onDMSRenameNode: function (event) {
- var record = this._getDataPoint(event.data.node.data.id, {raw: true});
- record.data.name = event.data.text;
- event.data.node.data = record;
- return this._rpc({
- model: event.data.node.data.model,
- method: "write",
- args: [
- [event.data.node.data.res_id],
- {
- name: event.data.text,
- },
- ],
- });
- },
- _onDMSDeleteNode: function (event) {
- return this._rpc({
- model: event.data.node.data.model,
- method: "unlink",
- args: [[event.data.node.data.res_id]],
- });
- },
- _onDMSMoveNode: function (event) {
- var data = {};
- if (event.data.node.data.model === "dms.file") {
- data.directory_id = event.data.new_parent.data.res_id;
- } else if (event.data.node.data.model === "dms.directory") {
- data.parent_id = event.data.new_parent.data.res_id;
- }
- return this._rpc({
- model: event.data.node.data.model,
- method: "write",
- args: [[event.data.node.data.res_id], data],
- });
- },
- };
-
- var custom_events = {
- dms_preview_file: "_onDMSPreviewFile",
- dms_load: "_onDMSLoad",
- dms_open_record: "_onDMSOpenRecord",
- dms_empty_storages: "_onDMSEmptyStorages",
- dms_rename_node: "_onDMSRenameNode",
- dms_delete_node: "_onDMSDeleteNode",
- dms_move_node: "_onDMSMoveNode",
- };
-
- FormController.include(
- _.extend(DMSTreeController, DragDrop, {
- custom_events: _.extend(
- {},
- FormController.prototype.custom_events,
- custom_events
- ),
- })
- );
-
- return {
- Controller: BasicController.extend(
- _.extend(DMSTreeController, DragDrop, {
- custom_events: _.extend(
- {},
- BasicController.prototype.custom_events,
- custom_events
- ),
- })
- ),
- custom_events: custom_events,
- DMSTreeController: DMSTreeController,
- };
-});
diff --git a/dms_field/static/src/js/base/dms_tree_renderer.js b/dms_field/static/src/js/base/dms_tree_renderer.js
deleted file mode 100644
index 4f9c74b24..000000000
--- a/dms_field/static/src/js/base/dms_tree_renderer.js
+++ /dev/null
@@ -1,508 +0,0 @@
-odoo.define("dms.DmsTreeRenderer", function (require) {
- "use strict";
-
- var BasicRenderer = require("web.BasicRenderer");
- var core = require("web.core");
- var ajax = require("web.ajax");
- var dialogs = require("web.view_dialogs");
- var config = require("web.config");
-
- var framework = require("web.framework");
- var session = require("web.session");
- var QWeb = core.qweb;
- var _t = core._t;
-
- var DmsTreeRenderer = BasicRenderer.extend({
- xmlDependencies: ["/dms_field/static/src/xml/tree.xml"],
- cssLibs: ["/dms_field/static/lib/jsTree/themes/proton/style.css"],
- jsLibs: ["/dms_field/static/lib/jsTree/jstree.js"],
- custom_events: _.extend({}, BasicRenderer.prototype.custom_events, {
- tree_changed: "_treeChanged",
- }),
- events: _.extend({}, BasicRenderer.prototype.events || {}, {
- "click .o_preview_file": "_onRecordPreview",
- "click .o_open_file": "_onOpenRecord",
- "click .o_dms_add_directory": "_onDMSAddDirectoryRecord",
- }),
- template: "dms.DocumentTree",
- init: function (parent, params) {
- // eslint-disable-next-line no-param-reassign
- params = _.defaults({}, params, {
- viewType: "dms_tree",
- });
- this._super.apply(this, arguments);
- this.params = params || {};
- this.storage_data = {};
- this.isMobile = config.device.isMobile;
- },
- willStart: function () {
- this.config = this._buildTreeConfig();
- return $.when(ajax.loadLibs(this), this._super.apply(this, arguments));
- },
- _buildTreeConfig: function () {
- var plugins = this.params.plugins || [
- "conditionalselect",
- "massload",
- "wholerow",
- "state",
- "sort",
- "search",
- "types",
- "contextmenu",
- ];
- var tree_config = {
- core: {
- widget: this,
- animation: this.params.animation || 0,
- multiple: false,
- check_callback:
- this.params.check_callback || this._checkCallback.bind(this),
- themes: this.params.themes || {
- name: "proton",
- responsive: true,
- },
- data: this._loadData.bind(this),
- },
- contextmenu: this.params.contextmenu_items || {
- items: this._loadContextMenu.bind(this),
- },
- state: {
- key: this.params.key || "documents",
- },
- conditionalselect:
- this.params.conditionalselect || this._checkSelect.bind(this),
- plugins: plugins,
- sort: function (a, b) {
- // Correctly sort the records according to the type of element
- // (folder or file).
- // Do not use node.icon because they may have (or will have) a
- // different icon for each file according to its extension.
- var node_a = this.get_node(a);
- var node_b = this.get_node(b);
- if (node_a.data.model === node_b.data.model) {
- return node_a.text > node_b.text ? 1 : -1;
- }
- return node_a.data.model > node_b.data.model ? 1 : -1;
- },
- };
- return tree_config;
- },
- _loadData: function (node, callback) {
- this.trigger_up("dms_load", {
- node: node,
- callback: callback,
- });
- },
- start_tree_triggers: function () {
- var self = this;
- this.$tree.on("open_node.jstree", function (e, data) {
- if (data.node.data && data.node.data.model === "dms.directory") {
- data.instance.set_icon(data.node, "fa fa-folder-open-o");
- }
- });
- this.$tree.on("close_node.jstree", function (e, data) {
- if (data.node.data && data.node.data.model === "dms.directory") {
- data.instance.set_icon(data.node, "fa fa-folder-o");
- }
- });
- this.$tree.on("ready.jstree", function (e, data) {
- self.trigger_up("tree_ready", {
- data: data,
- });
- });
- this.$tree.on("changed.jstree", function (e, data) {
- self.trigger_up("tree_changed", {
- data: data,
- });
- });
- this.$tree.on("move_node.jstree", function (e, data) {
- var jstree = self.$tree.jstree(true);
- self.trigger_up("dms_move_node", {
- node: data.node,
- new_parent: jstree.get_node(data.parent),
- old_parent: data.old_parent,
- });
- });
- this.$tree.on("rename_node.jstree", function (e, data) {
- self.trigger_up("dms_rename_node", {
- node: data.node,
- text: data.text,
- old: data.old,
- });
- self._preview_node(data.node);
- });
- this.$tree.on("delete_node.jstree", function (e, data) {
- self.trigger_up("dms_delete_node", {
- node: data.node,
- parent: data.parent,
- });
- });
- this.$tree.on("loaded.jstree", () => {
- this.$tree.jstree("open_all");
- });
- this.$('[data-toggle="tooltip"]').tooltip();
- },
- _treeChanged: function (ev) {
- var data = ev.data.data;
- if (data.selected && data.selected.length === 1) {
- this._preview_node(data.node);
- }
- },
- start: function () {
- var res = this._super.apply(this, arguments);
- this.$tree = this.$(".dms_tree");
- this.$tree.jstree(this.config);
- this.start_tree_triggers();
- return res;
- },
- /*
- This is used to check that the operation is allowed
- */
- _checkCallback: function (operation, node, parent) {
- if (operation === "copy_node" || operation === "move_node") {
- // Prevent moving a root node
- if (node.parent === "#") {
- return false;
- }
- // Prevent moving a child above or below the root
- if (parent.id === "#") {
- return false;
- }
- // Prevent moving a child to a settings object
- if (parent.data && parent.data.model === "dms.storage") {
- return false;
- }
- // Prevent moving a child to a file
- if (parent.data && parent.data.model === "dms.file") {
- return false;
- }
- }
- return true;
- },
- _checkSelect: function (node) {
- if (this.params.filesOnly && node.data.model !== "dms.file") {
- return false;
- }
- return !(node.parent === "#" && node.data.model === "dms.storage");
- },
- _preview_node: function (node) {
- var $buttons = this.$el.find(".o_dms_extra_actions");
- $buttons.empty();
- if (
- node.data &&
- ["dms.directory", "dms.file"].indexOf(node.data.model) !== -1
- ) {
- this.$(".dms_document_preview .o_preview_directory").remove();
- this.$(".dms_document_preview").prepend(
- $(
- QWeb.render("dms.DocumentTreeViewDirectoryPreview", {
- widget: this,
- dms_object: node.data,
- })
- )
- );
- var self = this;
- var menu = this._loadContextMenu(node);
- _.each(menu, function (action) {
- self._generateActionButton(node, action, $buttons);
- });
- }
- },
- _generateActionButton: function (node, action, $buttons) {
- if (action.action) {
- var $button = $("", {
- type: "button",
- class: "btn btn-secondary " + action.icon,
- "data-toggle": "dropdown",
- title: action.label,
- }).on("click", function (event) {
- event.preventDefault();
- event.stopPropagation();
- if (action._disabled && action._disabled()) {
- return;
- }
- action.action();
- });
- $buttons.append($button);
- }
- if (action.submenu) {
- var self = this;
- _.each(action.submenu, function (sub_action) {
- self._generateActionButton(node, sub_action, $buttons);
- });
- }
- },
- _loadContextMenu: function (node) {
- var menu = {};
- var jstree = this.$tree.jstree(true);
- if (node.data) {
- if (node.data.model === "dms.directory") {
- menu = this._loadContextMenuDirectoryBefore(jstree, node, menu);
- menu = this._loadContextMenuBasic(jstree, node, menu);
- menu = this._loadContextMenuDirectory(jstree, node, menu);
- } else if (node.data.model === "dms.file") {
- menu = this._loadContextMenuBasic(jstree, node, menu);
- menu = this._loadContextMenuFile(jstree, node, menu);
- }
- }
- return menu;
- },
- _loadContextMenuBasic: function ($jstree, node, menu) {
- var self = this;
- menu.rename = {
- separator_before: false,
- separator_after: false,
- icon: "fa fa-pencil",
- label: _t("Rename"),
- action: function () {
- $jstree.edit(node);
- },
- _disabled: function () {
- return !node.data.data.perm_write || node.data.data.storage;
- },
- };
- menu.action = {
- separator_before: false,
- separator_after: false,
- icon: "fa fa-bolt",
- label: _t("Actions"),
- action: false,
- submenu: {
- cut: {
- separator_before: false,
- separator_after: false,
- icon: "fa fa-scissors",
- label: _t("Cut"),
- action: function () {
- $jstree.cut(node);
- },
- _disabled: function () {
- return !node.data.data.perm_read || node.data.data.storage;
- },
- },
- },
- _disabled: function () {
- return !node.data.data.perm_read;
- },
- };
- menu.delete = {
- separator_before: false,
- separator_after: false,
- icon: "fa fa-trash-o",
- label: _t("Delete"),
- action: function () {
- $jstree.delete_node(node);
- },
- _disabled: function () {
- return !node.data.data.perm_unlink || node.data.data.storage;
- },
- };
- menu.open = {
- separator_before: false,
- separator_after: false,
- icon: "fa fa-external-link",
- label: _t("Open"),
- action: function () {
- self.trigger_up("dms_open_record", {id: node.id});
- },
- };
- return menu;
- },
- _loadContextMenuDirectoryBefore: function ($jstree, node, menu) {
- var self = this;
- menu.add_directory = {
- separator_before: false,
- separator_after: false,
- icon: "fa fa-folder",
- label: _t("Create directory"),
- action: function () {
- self._onDMSAddDirectory(node);
- },
- _disabled: function () {
- return !node.data.data.perm_create;
- },
- };
- menu.add_file = {
- separator_before: false,
- separator_after: true,
- icon: "fa fa-file",
- label: _t("Create File"),
- action: function () {
- self._onDMSAddFile(node);
- },
- _disabled: function () {
- return !node.data.data.perm_create;
- },
- };
- return menu;
- },
- _loadContextMenuDirectory: function ($jstree, node, menu) {
- if (menu.action && menu.action.submenu) {
- menu.action.submenu.paste = {
- separator_before: false,
- separator_after: false,
- icon: "fa fa-clipboard",
- label: _t("Paste"),
- action: function () {
- $jstree.paste(node);
- },
- _disabled: function () {
- return !$jstree.can_paste() && !node.data.data.perm_create;
- },
- };
- }
- return menu;
- },
- _loadContextMenuFile: function ($jstree, node, menu) {
- var self = this;
- menu.preview = {
- separator_before: false,
- separator_after: false,
- icon: "fa fa-eye",
- label: _t("Download"),
- action: function () {
- self.trigger_up("dms_preview_file", {
- id: node.id,
- });
- },
- };
- menu.download = {
- separator_before: false,
- separator_after: false,
- icon: "fa fa-download",
- label: _t("Download"),
- action: function () {
- framework.blockUI();
- session.get_file({
- url: "/web/content",
- data: {
- id: node.data.data.id,
- download: true,
- field: "content",
- model: "dms.file",
- filename_field: "name",
- filename: node.data.data.filename,
- },
- complete: framework.unblockUI,
- error: () =>
- self.call("crash_manager", "rpc_error", ...arguments),
- });
- },
- };
- return menu;
- },
- _onRecordPreview: function (ev) {
- ev.stopPropagation();
- var id = $(ev.currentTarget).data("id");
- if (id) {
- this.trigger_up("dms_preview_file", {
- id: id,
- target: ev.target,
- });
- }
- },
- _onOpenRecord: function (ev) {
- ev.stopPropagation();
- var id = $(ev.currentTarget).data("id");
- if (id) {
- this.trigger_up("dms_open_record", {
- id: id,
- target: ev.target,
- });
- }
- },
- _onDMSAddDirectory: function (node) {
- var self = this;
- var context = {
- default_parent_directory_id: node.data.res_id,
- };
- new dialogs.FormViewDialog(self, {
- res_model: "dms.directory",
- context: context,
- title: _t("Add Directory: ") + self.string,
- on_saved: function (record, changed) {
- if (changed) {
- const selected_id = self.$tree
- .find(".jstree-clicked")
- .attr("id");
- const model_data = self.$tree.jstree(true)._model.data;
- const state = self.$tree.jstree(true).get_state();
- const open_res_ids = state.core.open.map(
- (id) => model_data[id].data.res_id
- );
- self.$tree.on("refresh_node.jstree", () => {
- const model_data_entries = Object.entries(model_data);
- const ids = model_data_entries
- .filter(
- ([, value]) =>
- value.data &&
- open_res_ids.includes(value.data.res_id) &&
- value.data.model === "dms.directory"
- )
- .map((tuple) => tuple[0]);
- for (var id of ids) {
- self.$tree.jstree(true).open_node(id);
- }
- });
- self.$tree.jstree(true).refresh_node(selected_id);
- }
- },
- }).open();
- },
- _onDMSAddFile: function (node) {
- var self = this;
- var context = {
- default_directory_id: node.data.res_id,
- };
- new dialogs.FormViewDialog(self, {
- res_model: "dms.file",
- context: context,
- title: _t("Add File: ") + self.string,
- on_saved: function (record, changed) {
- if (changed) {
- const selected_id = self.$tree
- .find(".jstree-clicked")
- .attr("id");
- const model_data = self.$tree.jstree(true)._model.data;
- const state = self.$tree.jstree(true).get_state();
- const open_res_ids = state.core.open.map(
- (id) => model_data[id].data.res_id
- );
- self.$tree.on("refresh_node.jstree", () => {
- const model_data_entries = Object.entries(model_data);
- const ids = model_data_entries
- .filter(
- ([, value]) =>
- value.data &&
- open_res_ids.includes(value.data.res_id) &&
- value.data.model === "dms.directory"
- )
- .map((tuple) => tuple[0]);
- for (var id of ids) {
- self.$tree.jstree(true).open_node(id);
- }
- });
- self.$tree.jstree(true).refresh_node(selected_id);
- }
- },
- }).open();
- },
- _onDMSAddDirectoryRecord: function () {
- var self = this;
- var data = {};
- this.trigger_up("dms_empty_storages", {data: data});
- this._rpc({
- context: {
- res_id: data.res_id,
- res_model: data.model,
- },
- model: "dms.field.template",
- method: "create_dms_directory",
- }).then(function () {
- self.trigger_up("reload");
- });
- },
- });
-
- return DmsTreeRenderer;
-});
diff --git a/dms_field/static/src/js/base/dms_tree_view.js b/dms_field/static/src/js/base/dms_tree_view.js
deleted file mode 100644
index 4ea14336f..000000000
--- a/dms_field/static/src/js/base/dms_tree_view.js
+++ /dev/null
@@ -1,27 +0,0 @@
-odoo.define("dms.DmsTreeView", function (require) {
- "use strict";
-
- var BasicView = require("web.BasicView");
-
- var DmsTreeController = require("dms.DmsTreeController");
- var DmsTreeRenderer = require("dms.DmsTreeRenderer");
- var view_registry = require("web.view_registry");
- var core = require("web.core");
- var _lt = core._lt;
-
- var DmsTreeView = BasicView.extend({
- display_name: _lt("DMS"),
- template: "dms.DocumentTree",
- viewType: "dms_tree",
- config: _.extend({}, BasicView.prototype.config, {
- Controller: DmsTreeController.Controller,
- Renderer: DmsTreeRenderer,
- }),
- multi_record: true,
- searchable: false,
- });
-
- view_registry.add("dms_tree", DmsTreeView);
-
- return DmsTreeView;
-});
diff --git a/dms_field/static/src/js/core/mimetype.js b/dms_field/static/src/js/core/mimetype.js
deleted file mode 100644
index f55696a6b..000000000
--- a/dms_field/static/src/js/core/mimetype.js
+++ /dev/null
@@ -1,87 +0,0 @@
-odoo.define("dms_field.mimetype", function () {
- "use strict";
-
- var mapping = [
- ["file-image-o", /^image\//],
- ["file-audio-o", /^audio\//],
- ["file-video-o", /^video\//],
- ["file-pdf-o", "application/pdf"],
- ["file-text-o", "text/plain"],
- ["file-code-o", ["text/html", "text/javascript", "application/javascript"]],
- [
- "file-archive-o",
- [
- /^application\/x-(g?tar|xz|compress|bzip2|g?zip)$/,
- /^application\/x-(7z|rar|zip)-compressed$/,
- /^application\/(zip|gzip|tar)$/,
- ],
- ],
- [
- "file-word-o",
- [
- /ms-?word/,
- "application/vnd.oasis.opendocument.text",
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
- ],
- ],
- [
- "file-powerpoint-o",
- [
- /ms-?powerpoint/,
- "application/vnd.openxmlformats-officedocument.presentationml.presentation",
- ],
- ],
- [
- "file-excel-o",
- [
- /ms-?excel/,
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
- ],
- ],
- ["file-o"],
- ];
-
- function match(mimetype, cond) {
- if (Array.isArray(cond)) {
- return cond.reduce(function (v, c) {
- return v || match(mimetype, c);
- }, false);
- } else if (cond instanceof RegExp) {
- return cond.test(mimetype);
- } else if (cond === undefined) {
- return true;
- }
- return mimetype === cond;
- }
-
- var cache = {};
- function resolve(mimetype) {
- if (cache[mimetype]) {
- return cache[mimetype];
- }
- for (var i = 0; i < mapping.length; i++) {
- if (match(mimetype, mapping[i][1])) {
- cache[mimetype] = mapping[i][0];
- return mapping[i][0];
- }
- }
- }
-
- function mimetype2fa(mimetype, options) {
- if (typeof mimetype === "object") {
- var new_options = mimetype;
- return function (new_mimetype) {
- return mimetype2fa(new_mimetype, new_options);
- };
- }
- var icon = resolve(mimetype);
- if (icon && options && options.prefix) {
- return options.prefix + icon;
- }
- return icon;
- }
-
- return {
- mimetype2fa: mimetype2fa,
- };
-});
diff --git a/dms_field/static/src/js/fields/utils.js b/dms_field/static/src/js/fields/utils.js
deleted file mode 100644
index 9665fd0a8..000000000
--- a/dms_field/static/src/js/fields/utils.js
+++ /dev/null
@@ -1,27 +0,0 @@
-odoo.define("dms_field.field_utils", function (require) {
- "use strict";
-
- var utils = require("web.field_utils");
-
- function formatBinarySize(value, field, options) {
- var new_options = _.defaults(options || {}, {
- si: true,
- });
- var thresh = new_options.si ? 1000 : 1024;
- if (Math.abs(value) < thresh) {
- return utils.format.float(value, field, options) + " B";
- }
- var units = new_options.si
- ? ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
- : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
- var unit = -1;
- var new_value = value;
- do {
- new_value /= thresh;
- ++unit;
- } while (Math.abs(new_value) >= thresh && unit < units.length - 1);
- return utils.format.float(new_value, field, new_options) + " " + units[unit];
- }
-
- utils.format.binary_size = formatBinarySize;
-});
diff --git a/dms_field/static/src/js/views/many_drop_target.js b/dms_field/static/src/js/views/many_drop_target.js
deleted file mode 100644
index a62f9dbb5..000000000
--- a/dms_field/static/src/js/views/many_drop_target.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/* global base64js*/
-/* Copyright 2024 Tecnativa - Carlos Roca
- * License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
-odoo.define("dms_field.DragDrop", function (require) {
- "use strict";
-
- const DropTargetMixin = require("web_drop_target");
-
- return _.extend({}, DropTargetMixin.DropTargetMixin, {
- _drop_zone_selector: ".dms_document_preview",
-
- /**
- * @override
- */
- _handle_drop_items: function (drop_items) {
- _.each(drop_items, this._handle_file_drop_attach, this);
- },
-
- /**
- * @override
- */
- _get_record_id: function () {
- return true;
- },
-
- _get_selection_id: function () {
- return this.$drop_zone
- .find(".o_preview_directory")
- .attr("data-directory-id");
- },
-
- /**
- * @override
- */
- _checkDragOver: function () {
- return Boolean(this._get_selection_id());
- },
-
- /**
- * @override
- */
- _create_attachment: function (file, reader) {
- // Helper to upload an attachment and update the sidebar
- const ctx = this.renderer.state.getContext();
- const directory = parseInt(this._get_selection_id());
- if (this._checkDragOver()) {
- ctx.default_directory_id = directory;
- }
- return this._rpc({
- model: "dms.file",
- method: "create",
- args: [
- {
- name: file.name,
- content: base64js.fromByteArray(new Uint8Array(reader.result)),
- },
- ],
- kwargs: {
- context: ctx,
- },
- }).then(() => {
- const selected_id = $(".jstree-clicked").attr("id");
- const model_data = this.$(".dms_tree").jstree(true)._model.data;
- const state = this.$(".dms_tree").jstree(true).get_state();
- const open_res_ids = state.core.open.map(
- (id) => model_data[id].data.res_id
- );
- this.$(".dms_tree").on("refresh_node.jstree", () => {
- const model_data_entries = Object.entries(model_data);
- const ids = model_data_entries
- .filter(
- ([, value]) =>
- value.data &&
- open_res_ids.includes(value.data.res_id) &&
- value.data.model === "dms.directory"
- )
- .map((tuple) => tuple[0]);
- for (var id of ids) {
- this.$(".dms_tree").jstree(true).open_node(id);
- }
- });
- this.$(".dms_tree").jstree(true).refresh_node(selected_id);
- });
- },
- });
-});
diff --git a/dms_field/static/src/js/widget/field_widget.js b/dms_field/static/src/js/widget/field_widget.js
deleted file mode 100644
index 421947609..000000000
--- a/dms_field/static/src/js/widget/field_widget.js
+++ /dev/null
@@ -1,21 +0,0 @@
-odoo.define("dms_field.DmsItemWidget", function (require) {
- "use strict";
-
- var DmsTreeRenderer = require("dms.DmsTreeRenderer");
- var relational_fields = require("web.relational_fields");
-
- relational_fields.FieldOne2Many.include({
- _getRenderer: function () {
- if (this.view && this.view.arch.tag === "dms_tree") {
- return DmsTreeRenderer;
- }
- return this._super.apply(this, arguments);
- },
- _render: function () {
- if (this.view && this.view.arch.tag === "dms_tree") {
- this.$el.addClass("o_field_x2many_dms_tree");
- }
- return this._super.apply(this, arguments);
- },
- });
-});
diff --git a/dms_field/static/src/scss/base.scss b/dms_field/static/src/scss/base.scss
deleted file mode 100644
index 075dc73eb..000000000
--- a/dms_field/static/src/scss/base.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-.dms_searchview {
- .dms_searchview_info {
- cursor: default;
- position: absolute;
- top: 6px;
- right: 7px;
- }
-}
-.o_field_x2many_dms_tree {
- height: auto;
-}
diff --git a/dms_field/static/src/scss/dialog.scss b/dms_field/static/src/scss/dialog.scss
deleted file mode 100644
index 5b7f8ef3a..000000000
--- a/dms_field/static/src/scss/dialog.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-.dms_info_dialog {
- .dms_info_file_icon,
- .dms_info_directory_icon {
- }
-}
diff --git a/dms_field/static/src/scss/preview.scss b/dms_field/static/src/scss/preview.scss
deleted file mode 100644
index cba50484c..000000000
--- a/dms_field/static/src/scss/preview.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-.o_preview_directory {
- padding: 20px 30px 20px 30px;
-
- .btn-primary {
- margin: 0.1em;
- }
- a.o_preview_file:hover {
- cursor: pointer;
- }
- .right_info p {
- margin-bottom: 0;
- }
-}
diff --git a/dms_field/static/src/utils/format_binary_size.esm.js b/dms_field/static/src/utils/format_binary_size.esm.js
new file mode 100644
index 000000000..73193cc40
--- /dev/null
+++ b/dms_field/static/src/utils/format_binary_size.esm.js
@@ -0,0 +1,22 @@
+/** @odoo-module **/
+import utils from "web.field_utils";
+
+export function formatBinarySize(value, field, options) {
+ var new_options = _.defaults(options || {}, {
+ si: true,
+ });
+ var thresh = new_options.si ? 1000 : 1024;
+ if (Math.abs(value) < thresh) {
+ return utils.format.float(value, field, options) + " B";
+ }
+ var units = new_options.si
+ ? ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
+ : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
+ var unit = -1;
+ var new_value = value;
+ do {
+ new_value /= thresh;
+ ++unit;
+ } while (Math.abs(new_value) >= thresh && unit < units.length - 1);
+ return utils.format.float(new_value, field, new_options) + " " + units[unit];
+}
diff --git a/dms_field/static/src/utils/mimetype.esm.js b/dms_field/static/src/utils/mimetype.esm.js
new file mode 100644
index 000000000..5e88abd37
--- /dev/null
+++ b/dms_field/static/src/utils/mimetype.esm.js
@@ -0,0 +1,81 @@
+/** @odoo-module **/
+
+var mapping = [
+ ["file-image-o", /^image\//],
+ ["file-audio-o", /^audio\//],
+ ["file-video-o", /^video\//],
+ ["file-pdf-o", "application/pdf"],
+ ["file-text-o", "text/plain"],
+ ["file-code-o", ["text/html", "text/javascript", "application/javascript"]],
+ [
+ "file-archive-o",
+ [
+ /^application\/x-(g?tar|xz|compress|bzip2|g?zip)$/,
+ /^application\/x-(7z|rar|zip)-compressed$/,
+ /^application\/(zip|gzip|tar)$/,
+ ],
+ ],
+ [
+ "file-word-o",
+ [
+ /ms-?word/,
+ "application/vnd.oasis.opendocument.text",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ ],
+ ],
+ [
+ "file-powerpoint-o",
+ [
+ /ms-?powerpoint/,
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ ],
+ ],
+ [
+ "file-excel-o",
+ [
+ /ms-?excel/,
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ ],
+ ],
+ ["file-o"],
+];
+
+function match(mimetype, cond) {
+ if (Array.isArray(cond)) {
+ return cond.reduce(function (v, c) {
+ return v || match(mimetype, c);
+ }, false);
+ } else if (cond instanceof RegExp) {
+ return cond.test(mimetype);
+ } else if (cond === undefined) {
+ return true;
+ }
+ return mimetype === cond;
+}
+
+var cache = {};
+function resolve(mimetype) {
+ if (cache[mimetype]) {
+ return cache[mimetype];
+ }
+ for (var i = 0; i < mapping.length; i++) {
+ if (match(mimetype, mapping[i][1])) {
+ cache[mimetype] = mapping[i][0];
+ return mapping[i][0];
+ }
+ }
+}
+
+export function mimetype2fa(mimetype, options) {
+ if (typeof mimetype === "object") {
+ var new_options = mimetype;
+ return function (new_mimetype) {
+ return mimetype2fa(new_mimetype, new_options);
+ };
+ }
+ var icon = resolve(mimetype);
+ if (icon && options && options.prefix) {
+ return options.prefix + icon;
+ }
+ return icon;
+}
diff --git a/dms_field/static/src/views/dms_list/dms_list_arch_parser.esm.js b/dms_field/static/src/views/dms_list/dms_list_arch_parser.esm.js
new file mode 100644
index 000000000..d8e5c04c8
--- /dev/null
+++ b/dms_field/static/src/views/dms_list/dms_list_arch_parser.esm.js
@@ -0,0 +1,37 @@
+/** @odoo-module */
+/* Copyright 2024 Tecnativa - Carlos Roca
+ * License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
+import {addFieldDependencies} from "@web/views/utils";
+import {Field} from "@web/views/fields/field";
+import {XMLParser} from "@web/core/utils/xml";
+
+export class DmsListArchParser extends XMLParser {
+ parseFieldNode(node, models, modelName) {
+ return Field.parseFieldNode(node, models, modelName, "dms_list");
+ }
+
+ parse(arch, models, modelName) {
+ const fieldNodes = {};
+ const activeFields = {};
+ this.visitXML(arch, (node) => {
+ if (node.tagName === "field") {
+ const fieldInfo = this.parseFieldNode(node, models, modelName);
+ fieldNodes[fieldInfo.name] = fieldInfo;
+ node.setAttribute("field_id", fieldInfo.name);
+ addFieldDependencies(
+ activeFields,
+ models[modelName],
+ fieldInfo.FieldComponent.fieldDependencies
+ );
+ return false;
+ }
+ });
+ for (const [key, field] of Object.entries(fieldNodes)) {
+ activeFields[key] = field; // TODO process
+ }
+ return {
+ activeFields,
+ __rawArch: arch,
+ };
+ }
+}
diff --git a/dms_field/static/src/views/dms_list/dms_list_controller.esm.js b/dms_field/static/src/views/dms_list/dms_list_controller.esm.js
new file mode 100644
index 000000000..019837ef4
--- /dev/null
+++ b/dms_field/static/src/views/dms_list/dms_list_controller.esm.js
@@ -0,0 +1,536 @@
+/** @odoo-module */
+/* Copyright 2024 Tecnativa - Carlos Roca
+ * License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
+
+import {Layout} from "@web/search/layout";
+import {useService} from "@web/core/utils/hooks";
+import {useModel} from "@web/views/model";
+const {Component, onRendered} = owl;
+import {session} from "@web/session";
+import {Deferred} from "@web/core/utils/concurrency";
+import {Domain} from "@web/core/domain";
+import {mimetype2fa} from "../../utils/mimetype.esm";
+import {formatBinarySize} from "../../utils/format_binary_size.esm";
+import {patch} from "@web/core/utils/patch";
+import {DynamicRecordList} from "@web/views/relational_model";
+
+export const DMSListControllerObject = {
+ setup() {
+ this._super(...arguments);
+ this.orm = useService("orm");
+ this.actionService = useService("action");
+ this.http = useService("http");
+ const {rootState} = this.props.state || {};
+ this.model =
+ (this.props.record && this.props.record.model) ||
+ useModel(this.props.Model, {
+ resModel: this.props.resModel,
+ fields: this.props.fields,
+ activeFields: this.props.archInfo.activeFields,
+ viewMode: "dms_list",
+ rootState,
+ });
+ this.resModel = this.props.resModel || this.props.record.resModel;
+ this.rendererActions = {
+ onDMSCreateEmptyStorages: this.onDMSCreateEmptyStorages.bind(this),
+ onDMSLoad: this.onDMSLoad.bind(this),
+ onDMSRenameNode: this.onDMSRenameNode.bind(this),
+ onDMSMoveNode: this.onDMSMoveNode.bind(this),
+ onDMSDeleteNode: this.onDMSDeleteNode.bind(this),
+ onDMSDroppedFile: this.onDMSDroppedFile.bind(this),
+ };
+ onRendered(() => {
+ this.processProps();
+ });
+ },
+ sanitizeDMSModel(model) {
+ return model;
+ },
+ processProps() {
+ const model = this.sanitizeDMSModel(this.resModel);
+ var storage_domain = [];
+ var directory_domain = [];
+ var autocompute_directory = false;
+ var show_storage = true;
+ if (model === "dms.storage") {
+ if (this.model.root.data && this.model.root.data.id) {
+ storage_domain = [["id", "=", this.model.root.data.id]];
+ } else {
+ storage_domain = [
+ [
+ "id",
+ "in",
+ this.model.root.records.map((record) => {
+ return record.resId;
+ }),
+ ],
+ ];
+ }
+ directory_domain = [];
+ } else if (model === "dms.field.template") {
+ if (this.model.root.resId) {
+ storage_domain = [["id", "=", this.model.root.data.storage_id[0]]];
+ } else {
+ storage_domain = [["id", "=", 0]];
+ }
+ directory_domain = [
+ [
+ "root_directory_id",
+ "in",
+ this.model.root.data.dms_directory_ids.records.map((record) => {
+ return record.resId;
+ }),
+ ],
+ ];
+ } else {
+ storage_domain = [["field_template_ids.model", "=", model]];
+ autocompute_directory = true;
+ show_storage = false;
+ }
+ this.params = {
+ storage: {
+ domain: storage_domain,
+ context: session.user_context,
+ show: show_storage,
+ },
+ directory: {
+ domain: directory_domain,
+ context: session.user_context,
+ autocompute_directory: autocompute_directory,
+ },
+ file: {
+ domain: [],
+ context: session.user_context,
+ show: true,
+ },
+ };
+ },
+ async onDMSLoad(node) {
+ await this.model.root.load();
+ this.model.notify();
+ this.processProps();
+ var args = this.buildDMSArgs();
+ var result = false;
+ if (!node || node.id === "#") {
+ result = this.loadInitialData(args);
+ } else {
+ result = this.loadNode(node, args);
+ }
+ return {result, empty_storages: this.empty_storages};
+ },
+ loadInitialData(args) {
+ var self = this;
+ var data_loaded = new Deferred();
+ this.empty_storages = [];
+ this.loadStorages(args).then(
+ function (storages) {
+ var loading_data_parts = [];
+ _.each(
+ storages,
+ function (storage, index) {
+ if (storage.count_storage_directories > 0) {
+ var directory_loaded = new Deferred();
+ loading_data_parts.push(directory_loaded);
+ this.loadDirectoriesSingle(storage.id, args).then(function (
+ directories
+ ) {
+ if (directories.length > 0) {
+ storages[index].directories = directories;
+ } else if (
+ self.props.resModel !== "dms.directory" &&
+ self.props.resModel !== "dms.storage"
+ ) {
+ self.empty_storages.push(storage);
+ }
+ directory_loaded.resolve();
+ });
+ } else if (
+ self.props.resModel !== "dms.directory" &&
+ self.props.resModel !== "dms.storage"
+ ) {
+ self.empty_storages.push(storage);
+ }
+ }.bind(this)
+ );
+ $.when.apply($, loading_data_parts).then(
+ function () {
+ if (args.storage.show) {
+ var result = _.chain(storages)
+ .map(
+ function (storage) {
+ if (!storage.directories) {
+ return undefined;
+ }
+ var children = _.map(
+ storage.directories || [],
+ function (directory) {
+ return this.makeNodeDirectory(
+ directory,
+ args.file.show
+ );
+ }.bind(this)
+ );
+ return this.makeNodeStorage(storage, children);
+ }.bind(this)
+ )
+ .filter(function (node) {
+ return node;
+ })
+ .value();
+ data_loaded.resolve(result);
+ } else {
+ var nodes = [];
+ _.each(
+ storages,
+ function (storage) {
+ _.each(
+ storage.directories,
+ function (directory) {
+ nodes.push(
+ this.makeNodeDirectory(
+ directory,
+ args.file.show,
+ storage
+ )
+ );
+ }.bind(this)
+ );
+ }.bind(this)
+ );
+ data_loaded.resolve(nodes);
+ }
+ }.bind(this)
+ );
+ // Launch _update_overlay to show the drag and drop
+ // this._update_overlay();
+ }.bind(this)
+ );
+ return data_loaded;
+ },
+ loadNode(node, args) {
+ var result = new Deferred();
+ if (node.data && node.data.resModel === "dms.storage") {
+ this.loadDirectoriesSingle(node.data.data.id, args).then(
+ function (directories) {
+ var directory_nodes = _.map(
+ directories,
+ function (directory) {
+ return this.makeNodeDirectory(directory, args.file.show);
+ }.bind(this)
+ );
+ result.resolve(directory_nodes);
+ }.bind(this)
+ );
+ } else if (node.data && node.data.resModel === "dms.directory") {
+ var files_loaded = new Deferred();
+ var directories_loaded = new Deferred();
+ this.loadSubdirectoriesSingle(node.data.data.id, args).then(
+ function (directories) {
+ var directory_nodes = _.map(
+ directories,
+ function (directory) {
+ return this.makeNodeDirectory(directory, args.file.show);
+ }.bind(this)
+ );
+ directories_loaded.resolve(directory_nodes);
+ }.bind(this)
+ );
+ if (args.file.show) {
+ this.loadFilesSingle(node.data.data.id, args).then(
+ function (files) {
+ var file_nodes = _.map(
+ files,
+ function (file) {
+ return this.makeNodeFile(file);
+ }.bind(this)
+ );
+ files_loaded.resolve(file_nodes);
+ }.bind(this)
+ );
+ } else {
+ files_loaded.resolve([]);
+ }
+ $.when(directories_loaded, files_loaded).then(function (
+ directories,
+ files
+ ) {
+ result.resolve(directories.concat(files));
+ });
+ } else {
+ result.resolve([]);
+ }
+ return result;
+ },
+ makeNodeDirectory(directory, showFiles, storage) {
+ var data = _.extend(directory, {
+ name: directory.name,
+ perm_read: directory.permission_read,
+ perm_create: directory.permission_create,
+ perm_write: directory.permission_write,
+ perm_unlink: directory.permission_unlink,
+ icon_url: directory.icon_url,
+ count_total_directories: directory.count_total_directories,
+ count_total_files: directory.count_total_files,
+ human_size: directory.human_size,
+ count_elements: directory.count_elements,
+ });
+ if (
+ storage &&
+ this.resModel !== "dms.directory" &&
+ this.resModel !== "dms.storage"
+ ) {
+ // We are assuming this is a record directory, so disabling actions
+ data.name = storage.name;
+ data.storage = true;
+ }
+ var dt = this.makeDataPoint({
+ data: data,
+ resModel: "dms.directory",
+ });
+ dt.parent = directory.parent_id ? "directory_" + directory.parent_id[0] : "#";
+ var directoryNode = {
+ id: dt.id,
+ text: directory.name,
+ icon: "fa fa-folder-o",
+ type: "directory",
+ data: dt,
+ };
+ if (showFiles) {
+ directoryNode.children =
+ directory.count_directories + directory.count_files > 0;
+ } else {
+ directoryNode.children = directory.count_directories > 0;
+ }
+ return directoryNode;
+ },
+ makeNodeFile(file) {
+ var data = _.extend(file, {
+ filename: file.name,
+ display_name: file.name,
+ binary_size: formatBinarySize(file.size),
+ perm_read: file.permission_read,
+ perm_create:
+ file.permission_create && (!file.is_locked || file.is_lock_editor),
+ perm_write:
+ file.permission_write && (!file.is_locked || file.is_lock_editor),
+ perm_unlink:
+ file.permission_unlink && (!file.is_locked || file.is_lock_editor),
+ });
+ var dt = this.makeDataPoint({
+ data: data,
+ resModel: "dms.file",
+ });
+ return {
+ id: dt.id,
+ text: dt.data.display_name,
+ icon: mimetype2fa(dt.data.mimetype, {prefix: "fa fa-"}),
+ type: "file",
+ data: dt,
+ };
+ },
+ makeNodeStorage(storage, children) {
+ var dt = this.makeDataPoint({
+ data: storage,
+ resModel: "dms.storage",
+ });
+ return {
+ id: "storage_" + storage.id,
+ text: storage.name,
+ icon: "fa fa-database",
+ type: "storage",
+ data: dt,
+ children: children,
+ };
+ },
+ makeDataPoint(dt) {
+ return new DynamicRecordList(this.model, dt);
+ },
+ loadDirectories(operator, value, args) {
+ return this.orm.call("dms.directory", "search_read_parents", [], {
+ fields: _.union(args.directory.fields || [], [
+ "permission_read",
+ "permission_create",
+ "permission_write",
+ "permission_unlink",
+ "count_directories",
+ "count_files",
+ "name",
+ "parent_id",
+ "icon_url",
+ "count_total_directories",
+ "count_total_files",
+ "human_size",
+ "count_elements",
+ "__last_update",
+ ]),
+ domain: this.buildDMSDomain(
+ [["storage_id", operator, value]],
+ args.directory.domain,
+ args.directory.autocompute_directory
+ ),
+ context: args.directory.context || session.user_context,
+ });
+ },
+ loadDirectoriesSingle(storage_id, args) {
+ return this.loadDirectories("=", storage_id, args);
+ },
+ loadSubdirectories(operator, value, args) {
+ const domain = this.buildDMSDomain(
+ [["parent_id", operator, value]],
+ args.directory.domain,
+ false
+ );
+ const fields = _.union(args.directory.fields || [], [
+ "permission_read",
+ "permission_create",
+ "permission_write",
+ "permission_unlink",
+ "count_directories",
+ "count_files",
+ "name",
+ "parent_id",
+ "icon_url",
+ "count_total_directories",
+ "count_total_files",
+ "human_size",
+ "count_elements",
+ "__last_update",
+ ]);
+ return this.orm.searchRead("dms.directory", domain, fields, {
+ context: args.file.context || session.user_context,
+ });
+ },
+ loadSubdirectoriesSingle(directory_id, args) {
+ return this.loadSubdirectories("=", directory_id, args);
+ },
+ loadFiles(operator, value, args) {
+ const domain = this.buildDMSDomain(
+ [["directory_id", operator, value]],
+ args.file.domain
+ );
+ const fields = _.union(args.file.fields || [], [
+ "permission_read",
+ "permission_create",
+ "permission_write",
+ "permission_unlink",
+ "name",
+ "mimetype",
+ "directory_id",
+ "human_size",
+ "is_locked",
+ "is_lock_editor",
+ "extension",
+ "__last_update",
+ ]);
+ return this.orm.searchRead("dms.file", domain, fields, {
+ context: args.file.context || session.user_context,
+ });
+ },
+ loadFilesSingle(directory_id, args) {
+ return this.loadFiles("=", directory_id, args);
+ },
+ loadStorages(args) {
+ const fields = _.union(args.storage.fields || [], [
+ "name",
+ "count_storage_directories",
+ ]);
+ return this.orm.searchRead("dms.storage", args.storage.domain || [], fields, {
+ context: args.storage.context || session.user_context,
+ });
+ },
+ buildDMSDomain(base, domain, autocompute_directory) {
+ var result = new Domain(base);
+ if (autocompute_directory) {
+ result = Domain.and([
+ result,
+ new Domain([["res_id", "=", this.model.root.resId]]),
+ ]);
+ } else {
+ result = Domain.and([result, new Domain(domain || [])]);
+ }
+ return result.toList();
+ },
+ buildDMSArgs() {
+ return {
+ ...this.params,
+ search: {
+ operator: "ilike",
+ },
+ };
+ },
+ onDMSCreateEmptyStorages() {
+ var data = {
+ model: this.resModel,
+ empty_storages: this.empty_storages,
+ res_id: this.props.record.resId,
+ };
+ return this.orm.call("dms.field.template", "create_dms_directory", [], {
+ context: {
+ res_id: data.res_id,
+ res_model: data.model,
+ },
+ });
+ },
+ onDMSRenameNode(node, text) {
+ node.data.data.name = text;
+ return this.orm.write(node.data.resModel, [node.data.data.id], {
+ name: text,
+ });
+ },
+ onDMSMoveNode(node, newParent) {
+ var data = {};
+ if (node.data.resModel === "dms.file") {
+ data.directory_id = newParent.data.data.id;
+ } else if (node.data.resModel === "dms.directory") {
+ data.parent_id = newParent.data.data.id;
+ }
+ return this.orm.write(node.data.resModel, [node.data.data.id], data);
+ },
+ onDMSDeleteNode(node) {
+ return this.orm.unlink(node.data.resModel, [node.data.data.id]);
+ },
+ async onDMSDroppedFile(directoryId, files) {
+ const params = {
+ csrf_token: odoo.csrf_token,
+ ufile: [...files],
+ model: "dms.file",
+ id: 0,
+ };
+ const fileData = await this.http.post(
+ "/web/binary/upload_attachment",
+ params,
+ "text"
+ );
+ const attachments = JSON.parse(fileData);
+ if (attachments.error) {
+ throw new Error(attachments.error);
+ }
+ const attachmentIds = attachments.map((a) => a.id);
+ const ctx = this.props.context || this.props.record.context;
+ if (!attachmentIds.length) {
+ return "no_attachments";
+ }
+ ctx.default_directory_id = directoryId;
+ const attachment_datas = await this.orm.call(
+ "dms.file",
+ "get_dms_files_from_attachments",
+ ["", attachmentIds]
+ );
+ const attachments_args = [];
+ attachment_datas.forEach((attachment_data) => {
+ attachments_args.push({
+ name: attachment_data.name,
+ content: attachment_data.datas,
+ mimetype: attachment_data.mimetype,
+ });
+ });
+ return this.orm.call("dms.file", "create", [attachments_args], {
+ context: ctx,
+ });
+ },
+};
+
+export class DmsListController extends Component {}
+patch(DmsListController.prototype, "DmsListControllerPatch", DMSListControllerObject);
+DmsListController.template = "dms_field.View";
+DmsListController.components = {Layout};
diff --git a/dms_field/static/src/views/dms_list/dms_list_controller.xml b/dms_field/static/src/views/dms_list/dms_list_controller.xml
new file mode 100644
index 000000000..2ff6d95ab
--- /dev/null
+++ b/dms_field/static/src/views/dms_list/dms_list_controller.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js b/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js
new file mode 100644
index 000000000..cc058d454
--- /dev/null
+++ b/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js
@@ -0,0 +1,531 @@
+/** @odoo-module */
+/* Copyright 2024 Tecnativa - Carlos Roca
+ * License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
+
+import {_lt} from "@web/core/l10n/translation";
+import {useService} from "@web/core/utils/hooks";
+import {loadCSS, loadJS} from "@web/core/assets";
+const {Component, onMounted, onWillStart, useEffect, useRef, useState} = owl;
+import {download} from "@web/core/network/download";
+import {FormViewDialog} from "@web/views/view_dialogs/form_view_dialog";
+
+export class DmsListRenderer extends Component {
+ setup() {
+ this.js_tree = useRef("jstree");
+ this.extra_actions = useRef("extra_actions");
+ this.dms_add_directory = useRef("dms_add_directory");
+ this.nodeSelectedState = useState({data: {}});
+ this.messaging = useService("messaging");
+ this.notification = useService("notification");
+ this.dragState = useState({
+ showDragZone: false,
+ });
+ this.dropZone = useRef("dropZone");
+
+ useEffect(
+ (el) => {
+ if (!el) {
+ return;
+ }
+ const highlight = this.highlight.bind(this);
+ const unhighlight = this.unhighlight.bind(this);
+ const drop = this.onDrop.bind(this);
+ el.addEventListener("dragover", highlight);
+ el.addEventListener("dragleave", unhighlight);
+ el.addEventListener("drop", drop);
+ return () => {
+ el.removeEventListener("dragover", highlight);
+ el.removeEventListener("dragleave", unhighlight);
+ el.removeEventListener("drop", drop);
+ };
+ },
+
+ () => [this.dropZone.el]
+ );
+ onWillStart(async () => {
+ await loadJS("/dms_field/static/lib/jsTree/jstree.js");
+ await loadCSS("/dms_field/static/lib/jsTree/themes/proton/style.css");
+ this.config = this.buildTreeConfig();
+ });
+ onMounted(() => {
+ this.$tree = $(this.js_tree.el);
+ this.$tree.jstree(this.config);
+ this.startTreeTriggers();
+ });
+ }
+ buildTreeConfig() {
+ var plugins = [
+ "conditionalselect",
+ "massload",
+ "wholerow",
+ "state",
+ "sort",
+ "search",
+ "types",
+ "contextmenu",
+ ];
+ return {
+ core: {
+ widget: this,
+ animation: 0,
+ multiple: false,
+ check_callback: this.checkCallback.bind(this),
+ themes: {
+ name: "proton",
+ responsive: true,
+ },
+ data: this.loadData.bind(this),
+ },
+ contextmenu: {
+ items: this.loadContextMenu.bind(this),
+ },
+ state: {
+ key: "documents",
+ },
+ conditionalselect: this.checkSelect.bind(this),
+ plugins: plugins,
+ sort: function (a, b) {
+ // Correctly sort the records according to the type of element
+ // (folder or file).
+ // Do not use node.icon because they may have (or will have) a
+ // different icon for each file according to its extension.
+ var node_a = this.get_node(a);
+ var node_b = this.get_node(b);
+ if (node_a.data.resModel === node_b.data.resModel) {
+ return node_a.text > node_b.text ? 1 : -1;
+ }
+ return node_a.data.resModel > node_b.data.resModel ? 1 : -1;
+ },
+ };
+ }
+ startTreeTriggers() {
+ this.$tree.on("open_node.jstree", (e, data) => {
+ if (data.node.data && data.node.data.resModel === "dms.directory") {
+ data.instance.set_icon(data.node, "fa fa-folder-open-o");
+ }
+ });
+ this.$tree.on("close_node.jstree", (e, data) => {
+ if (data.node.data && data.node.data.resModel === "dms.directory") {
+ data.instance.set_icon(data.node, "fa fa-folder-o");
+ }
+ });
+ this.$tree.on("changed.jstree", (e, data) => {
+ this.treeChanged(data);
+ });
+ this.$tree.on("move_node.jstree", (e, data) => {
+ var jstree = this.$tree.jstree(true);
+ this.props.rendererActions.onDMSMoveNode(
+ data.node,
+ jstree.get_node(data.parent)
+ );
+ });
+ this.$tree.on("rename_node.jstree", (e, data) => {
+ this.props.rendererActions.onDMSRenameNode(data.node, data.text);
+ this.updatePreview(data.node);
+ });
+ this.$tree.on("delete_node.jstree", (e, data) => {
+ this.props.rendererActions.onDMSDeleteNode(data.node);
+ });
+ this.$tree.on("loaded.jstree", () => {
+ this.$tree.jstree("open_all");
+ });
+ }
+
+ treeChanged(data) {
+ if (
+ data.action === "select_node" &&
+ data.selected &&
+ data.selected.length === 1
+ ) {
+ this.updatePreview(data.node);
+ }
+ }
+
+ updatePreview(node) {
+ var $buttons = $(this.extra_actions.el);
+ $buttons.empty();
+ if (
+ node.data &&
+ ["dms.directory", "dms.file"].indexOf(node.data.resModel) !== -1
+ ) {
+ this.nodeSelectedState.data = {};
+ this.nodeSelectedState.data = node.data;
+ var menu = this.loadContextMenu(node);
+ _.each(menu, (action) => {
+ this.generateActionButton(node, action, $buttons);
+ });
+ }
+ }
+
+ loadContextMenu(node) {
+ var menu = {};
+ var jstree = this.$tree.jstree(true);
+ if (node.data) {
+ if (node.data.resModel === "dms.directory") {
+ menu = this.loadContextMenuDirectoryBefore(jstree, node, menu);
+ menu = this.loadContextMenuBasic(jstree, node, menu);
+ menu = this.loadContextMenuDirectory(jstree, node, menu);
+ } else if (node.data.resModel === "dms.file") {
+ menu = this.loadContextMenuBasic(jstree, node, menu);
+ menu = this.loadContextMenuFile(jstree, node, menu);
+ }
+ }
+ return menu;
+ }
+
+ loadContextMenuBasic($jstree, node, menu) {
+ menu.rename = {
+ separator_before: false,
+ separator_after: false,
+ icon: "fa fa-pencil",
+ label: _lt("Rename"),
+ action: () => {
+ $jstree.edit(node);
+ },
+ _disabled: () => {
+ return !node.data.data.perm_write || node.data.data.storage;
+ },
+ };
+ menu.action = {
+ separator_before: false,
+ separator_after: false,
+ icon: "fa fa-bolt",
+ label: _lt("Actions"),
+ action: false,
+ submenu: {
+ cut: {
+ separator_before: false,
+ separator_after: false,
+ icon: "fa fa-scissors",
+ label: _lt("Cut"),
+ action: () => {
+ $jstree.cut(node);
+ },
+ _disabled: () => {
+ return !node.data.data.perm_read || node.data.data.storage;
+ },
+ },
+ },
+ _disabled: () => {
+ return !node.data.data.perm_read;
+ },
+ };
+ menu.delete = {
+ separator_before: false,
+ separator_after: false,
+ icon: "fa fa-trash-o",
+ label: _lt("Delete"),
+ action: () => {
+ $jstree.delete_node(node);
+ },
+ _disabled: () => {
+ return !node.data.data.perm_unlink || node.data.data.storage;
+ },
+ };
+ menu.open = {
+ separator_before: false,
+ separator_after: false,
+ icon: "fa fa-external-link",
+ label: _lt("Open"),
+ action: () => {
+ this.onDMSOpenRecord(node);
+ },
+ };
+ return menu;
+ }
+
+ loadContextMenuDirectoryBefore($jstree, node, menu) {
+ menu.add_directory = {
+ separator_before: false,
+ separator_after: false,
+ icon: "fa fa-folder",
+ label: _lt("Create directory"),
+ action: () => {
+ this.onDMSAddDirectory(node);
+ },
+ _disabled: () => {
+ return !node.data.data.perm_create;
+ },
+ };
+ menu.add_file = {
+ separator_before: false,
+ separator_after: true,
+ icon: "fa fa-file",
+ label: _lt("Create File"),
+ action: () => {
+ this.onDMSAddFile(node);
+ },
+ _disabled: () => {
+ return !node.data.data.perm_create;
+ },
+ };
+ return menu;
+ }
+
+ loadContextMenuDirectory($jstree, node, menu) {
+ if (menu.action && menu.action.submenu) {
+ menu.action.submenu.paste = {
+ separator_before: false,
+ separator_after: false,
+ icon: "fa fa-clipboard",
+ label: _lt("Paste"),
+ action: () => {
+ $jstree.paste(node);
+ },
+ _disabled: () => {
+ return !$jstree.can_paste() && !node.data.data.perm_create;
+ },
+ };
+ }
+ return menu;
+ }
+
+ loadContextMenuFile($jstree, node, menu) {
+ menu.preview = {
+ separator_before: false,
+ separator_after: false,
+ icon: "fa fa-eye",
+ label: _lt("Preview"),
+ action: () => {
+ this.onDMSPreviewFile(node);
+ },
+ };
+ menu.download = {
+ separator_before: false,
+ separator_after: false,
+ icon: "fa fa-download",
+ label: _lt("Download"),
+ action: () => {
+ download({
+ url: "/web/content",
+ data: {
+ id: node.data.data.id,
+ download: true,
+ field: "content",
+ model: "dms.file",
+ filename_field: "name",
+ filename: node.data.data.filename,
+ },
+ });
+ },
+ };
+ return menu;
+ }
+
+ generateActionButton(node, action, $buttons) {
+ if (action.action) {
+ var $button = $("", {
+ type: "button",
+ class: "btn btn-secondary " + action.icon,
+ "data-toggle": "dropdown",
+ title: action.label,
+ }).on("click", (event) => {
+ event.preventDefault();
+ event.stopPropagation();
+ if (action._disabled && action._disabled()) {
+ return;
+ }
+ action.action();
+ });
+ $buttons.append($button);
+ }
+ if (action.submenu) {
+ _.each(action.submenu, (sub_action) => {
+ this.generateActionButton(node, sub_action, $buttons);
+ });
+ }
+ }
+
+ async loadData(node, callback) {
+ const {result, empty_storages} = await this.props.rendererActions.onDMSLoad(
+ node
+ );
+ result.then((data) => {
+ callback.call(this, data);
+ if (empty_storages.length > 0) {
+ $(this.dms_add_directory.el).removeClass("o_hidden");
+ }
+ });
+ }
+
+ /*
+ This is used to check that the operation is allowed
+ */
+ checkCallback(operation, node, parent) {
+ if (operation === "copy_node" || operation === "move_node") {
+ // Prevent moving a root node
+ if (node.parent === "#") {
+ return false;
+ }
+ // Prevent moving a child above or below the root
+ if (parent.id === "#") {
+ return false;
+ }
+ // Prevent moving a child to a settings object
+ if (parent.data && parent.data.resModel === "dms.storage") {
+ return false;
+ }
+ // Prevent moving a child to a file
+ if (parent.data && parent.data.resModel === "dms.file") {
+ return false;
+ }
+ }
+ return true;
+ }
+ checkSelect(node) {
+ if (this.props.filesOnly && node.data.resModel !== "dms.file") {
+ return false;
+ }
+ return !(node.parent === "#" && node.data.resModel === "dms.storage");
+ }
+ onDMSAddDirectory(node) {
+ var context = {
+ default_parent_directory_id: node.data.data.id,
+ };
+ Component.env.services.dialog.add(FormViewDialog, {
+ resModel: "dms.directory",
+ context: context,
+ title: _lt("Add Directory: ") + node.data.data.name,
+ onRecordSaved: () => {
+ const selected_id = this.$tree.find(".jstree-clicked").attr("id");
+ const model_data = this.$tree.jstree(true)._model.data;
+ const state = this.$tree.jstree(true).get_state();
+ const open_res_ids = state.core.open.map(
+ (id) => model_data[id].data.data.id
+ );
+ this.$tree.on("refresh_node.jstree", () => {
+ const model_data_entries = Object.entries(model_data);
+ const ids = model_data_entries
+ .filter(
+ ([, value]) =>
+ value.data &&
+ open_res_ids.includes(value.data.data.id) &&
+ value.data.resModel === "dms.directory"
+ )
+ .map((tuple) => tuple[0]);
+ for (var id of ids) {
+ this.$tree.jstree(true).open_node(id);
+ }
+ });
+ this.$tree.jstree(true).refresh_node(selected_id);
+ },
+ });
+ }
+ onDMSAddFile(node) {
+ var context = {
+ default_directory_id: node.data.data.id,
+ };
+ Component.env.services.dialog.add(FormViewDialog, {
+ resModel: "dms.file",
+ context: context,
+ title: _lt("Add File: ") + node.data.data.name,
+ onRecordSaved: () => {
+ const selected_id = this.$tree.find(".jstree-clicked").attr("id");
+ const model_data = this.$tree.jstree(true)._model.data;
+ const state = this.$tree.jstree(true).get_state();
+ const open_res_ids = state.core.open.map(
+ (id) => model_data[id].data.data.id
+ );
+ this.$tree.on("refresh_node.jstree", () => {
+ const model_data_entries = Object.entries(model_data);
+ const ids = model_data_entries
+ .filter(
+ ([, value]) =>
+ value.data &&
+ open_res_ids.includes(value.data.data.id) &&
+ value.data.model === "dms.directory"
+ )
+ .map((tuple) => tuple[0]);
+ for (var id of ids) {
+ this.$tree.jstree(true).open_node(id);
+ }
+ });
+ this.$tree.jstree(true).refresh_node(selected_id);
+ },
+ });
+ }
+ onDMSAddDirectoryRecord() {
+ this.props.rendererActions.onDMSCreateEmptyStorages().then(() => {
+ this.$tree.jstree(true).refresh();
+ $(this.dms_add_directory.el).addClass("o_hidden");
+ });
+ }
+ onDMSOpenRecord(node) {
+ Component.env.services.dialog.add(FormViewDialog, {
+ resModel: node.data.resModel,
+ title: _lt("Open: ") + node.data.data.name,
+ resId: node.data.data.id,
+ });
+ }
+ onDMSPreviewFile(node) {
+ this.messaging.get().then((messaging) => {
+ const attachmentList = messaging.models.AttachmentList.insert({
+ selectedAttachment: messaging.models.Attachment.insert({
+ id: node.data.data.id,
+ filename: node.data.data.name,
+ name: node.data.data.name,
+ mimetype: node.data.data.mimetype,
+ model_name: node.data.resModel,
+ }),
+ });
+ Component.env.services.dialog = messaging.models.Dialog.insert({
+ attachmentListOwnerAsAttachmentView: attachmentList,
+ });
+ });
+ }
+ get showDragZone() {
+ return (
+ this.nodeSelectedState.data.resModel === "dms.directory" &&
+ this.dragState.showDragZone
+ );
+ }
+ highlight(ev) {
+ ev.stopPropagation();
+ ev.preventDefault();
+ this.dragState.showDragZone = true;
+ }
+ unhighlight(ev) {
+ ev.stopPropagation();
+ ev.preventDefault();
+ this.dragState.showDragZone = false;
+ }
+ async onDrop(ev) {
+ ev.preventDefault();
+ const directoryId = this.nodeSelectedState.data.data.id;
+ const res = await this.props.rendererActions
+ .onDMSDroppedFile(directoryId, ev.dataTransfer.files)
+ .catch((error) => {
+ this.notification.add(error.data.message, {
+ type: "danger",
+ });
+ });
+ if (res === "no_attachments") {
+ this.notification.add(_lt("An error occurred during the upload"));
+ } else {
+ const selected_id = this.$tree.find(".jstree-clicked").attr("id");
+ const model_data = this.$tree.jstree(true)._model.data;
+ const state = this.$tree.jstree(true).get_state();
+ const open_res_ids = state.core.open.map(
+ (id) => model_data[id].data.data.id
+ );
+ this.$tree.on("refresh_node.jstree", () => {
+ const model_data_entries = Object.entries(model_data);
+ const ids = model_data_entries
+ .filter(
+ ([, value]) =>
+ value.data &&
+ open_res_ids.includes(value.data.data.id) &&
+ value.data.model === "dms.directory"
+ )
+ .map((tuple) => tuple[0]);
+ for (var id of ids) {
+ this.$tree.jstree(true).open_node(id);
+ }
+ });
+ this.$tree.jstree(true).refresh_node(selected_id);
+ }
+ this.unhighlight(ev);
+ }
+}
+
+DmsListRenderer.template = "dms_list.Renderer";
diff --git a/dms_field/static/src/scss/main.scss b/dms_field/static/src/views/dms_list/dms_list_renderer.scss
similarity index 80%
rename from dms_field/static/src/scss/main.scss
rename to dms_field/static/src/views/dms_list/dms_list_renderer.scss
index f216cbc1d..bcecae874 100644
--- a/dms_field/static/src/scss/main.scss
+++ b/dms_field/static/src/views/dms_list/dms_list_renderer.scss
@@ -18,6 +18,25 @@
}
}
+.dms_document_col_preview {
+ position: relative;
+ .o_dropzone {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ background-color: #aaaa;
+ z-index: 2;
+ left: 0;
+ top: 0;
+ i {
+ justify-content: center;
+ display: flex;
+ align-items: center;
+ height: 100%;
+ }
+ }
+}
+
.dms_treeview {
height: 100%;
.dms_document_container {
diff --git a/dms_field/static/src/views/dms_list/dms_list_renderer.xml b/dms_field/static/src/views/dms_list/dms_list_renderer.xml
new file mode 100644
index 000000000..bbf5e3b2a
--- /dev/null
+++ b/dms_field/static/src/views/dms_list/dms_list_renderer.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Subdirectories:
+ Files:
+ Size:
+ Elements:
+
+
+ Size:
+
+
+
+
+
+
+
diff --git a/dms_field/static/src/views/dms_list/dms_list_view.esm.js b/dms_field/static/src/views/dms_list/dms_list_view.esm.js
new file mode 100644
index 000000000..836e36b6c
--- /dev/null
+++ b/dms_field/static/src/views/dms_list/dms_list_view.esm.js
@@ -0,0 +1,33 @@
+/** @odoo-module */
+
+import {registry} from "@web/core/registry";
+import {DmsListController} from "./dms_list_controller.esm";
+import {DmsListArchParser} from "./dms_list_arch_parser.esm";
+import {RelationalModel} from "@web/views/relational_model";
+import {DmsListRenderer} from "./dms_list_renderer.esm";
+
+export const dmsListView = {
+ type: "dms_list",
+ display_name: "Dms Tree",
+ icon: "fa fa-file-o",
+ multiRecord: true,
+ Controller: DmsListController,
+ ArchParser: DmsListArchParser,
+ Renderer: DmsListRenderer,
+ Model: RelationalModel,
+
+ props(genericProps, view) {
+ const {ArchParser} = view;
+ const {arch, relatedModels, resModel} = genericProps;
+ const archInfo = new ArchParser().parse(arch, relatedModels, resModel);
+
+ return {
+ ...genericProps,
+ Model: view.Model,
+ Renderer: view.Renderer,
+ archInfo,
+ };
+ },
+};
+
+registry.category("views").add("dms_list", dmsListView);
diff --git a/dms_field/static/src/views/fields/x2many/x2many_field.esm.js b/dms_field/static/src/views/fields/x2many/x2many_field.esm.js
new file mode 100644
index 000000000..cba7b359a
--- /dev/null
+++ b/dms_field/static/src/views/fields/x2many/x2many_field.esm.js
@@ -0,0 +1,27 @@
+/** @odoo-module */
+/* Copyright 2024 Tecnativa - Carlos Roca
+ * License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). */
+import {X2ManyField} from "@web/views/fields/x2many/x2many_field";
+import {patch} from "@web/core/utils/patch";
+import {DmsListRenderer} from "../../dms_list/dms_list_renderer.esm";
+import {DMSListControllerObject} from "../../dms_list/dms_list_controller.esm";
+
+patch(X2ManyField.prototype, "dms_field.X2ManyField", {
+ ...DMSListControllerObject,
+ get rendererProps() {
+ const archInfo = this.activeField.views[this.viewMode];
+ const props = {
+ archInfo,
+ list: this.list,
+ openRecord: this.openRecord.bind(this),
+ };
+ if (this.viewMode === "dms_list") {
+ props.archInfo = archInfo;
+ props.readonly = this.props.readonly;
+ props.rendererActions = this.rendererActions;
+ return props;
+ }
+ return this._super(...arguments);
+ },
+});
+X2ManyField.components = {...X2ManyField.components, DmsListRenderer};
diff --git a/dms_field/static/src/views/fields/x2many/x2many_field.xml b/dms_field/static/src/views/fields/x2many/x2many_field.xml
new file mode 100644
index 000000000..bdc14cabd
--- /dev/null
+++ b/dms_field/static/src/views/fields/x2many/x2many_field.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/dms_field/static/src/xml/controls.xml b/dms_field/static/src/xml/controls.xml
deleted file mode 100644
index 8bbab23cd..000000000
--- a/dms_field/static/src/xml/controls.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
- Open
-
-
-
- Create
-
-
-
- Edit
-
-
-
- Delete
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dms_field/static/src/xml/dialogs.xml b/dms_field/static/src/xml/dialogs.xml
deleted file mode 100644
index 13ad674d6..000000000
--- a/dms_field/static/src/xml/dialogs.xml
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
Keyboard Shortcuts
-
-
-
-
-
-
-
-
-
-
- Move up one node
-
-
-
-
-
-
-
-
-
-
-
-
-
- Close the selected node
-
-
-
-
-
-
-
-
-
-
-
-
-
- Open the selected node
-
-
-
-
-
-
-
-
-
-
-
-
-
- Move down one node
-
-
-
-
-
-
-
-
-
-
-
-
-
- Open all nodes
-
-
-
-
-
-
-
-
- F2
-
-
-
-
- Edit the selected node
-
-
-
-
-
-
-
-
- HOME
-
-
-
-
- Jump to the top
-
-
-
-
-
-
-
-
- END
-
-
-
-
- Jump to the bottom
-
-
-
-
-
-
-
-
Context Menu
-
- You can open a context menu by right-clicking on any node. This
- contains further options for interacting with the node.
-
-
Drag and Drop
-
- You can change the structure by moving nodes. It is also possible
- to create new nodes by dragging files and even entire folder
- structures on the view.
-
-
Action Buttons
-
- The action button at the top of the view can be used to open,
- create, edit or delete a node.
-
-
-
-
-
-
diff --git a/dms_field/static/src/xml/preview.xml b/dms_field/static/src/xml/preview.xml
deleted file mode 100644
index 9b7efee21..000000000
--- a/dms_field/static/src/xml/preview.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- Subdirectories:
- Files:
- Size:
- Elements:
-
-
- Size:
-
-
-
-
-
-
-
diff --git a/dms_field/static/src/xml/tree.xml b/dms_field/static/src/xml/tree.xml
deleted file mode 100644
index 54accea90..000000000
--- a/dms_field/static/src/xml/tree.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
diff --git a/dms_field/tests/test_dms_field.py b/dms_field/tests/test_dms_field.py
index c26b2c6ee..b593172d0 100644
--- a/dms_field/tests/test_dms_field.py
+++ b/dms_field/tests/test_dms_field.py
@@ -41,7 +41,7 @@ def setUpClass(cls):
res_model=cls.template._name, res_id=cls.template.id
)
template_ctx.create_dms_directory()
- cls.template.refresh()
+ cls.template.invalidate_cache()
cls.directory = cls.template.dms_directory_ids
cls.subdirectory_1 = cls.env["dms.directory"].create(
{
@@ -111,7 +111,7 @@ def test_creation_process_01(self):
res_model=self.partner._name, res_id=self.partner.id
)
template.create_dms_directory()
- self.partner.refresh()
+ self.partner.invalidate_cache()
self.assertEqual(self.partner.dms_directory_ids.name, self.partner.display_name)
child_names = self.partner.dms_directory_ids.mapped("child_directory_ids.name")
directory_0 = self.partner.dms_directory_ids[0]
@@ -127,14 +127,14 @@ def test_creation_process_01(self):
def test_creation_process_02(self):
partner_1 = self.env["res.partner"].create({"name": "Test partner 1"})
- partner_1.refresh()
+ partner_1.invalidate_cache()
self.assertTrue(partner_1.dms_directory_ids)
partner_2 = (
self.env["res.partner"]
.with_context(skip_track_dms_field_template=True)
.create({"name": "Test partner 2"})
)
- partner_2.refresh()
+ partner_2.invalidate_cache()
self.assertFalse(partner_2.dms_directory_ids)
def test_creation_process_03(self):
@@ -142,7 +142,7 @@ def test_creation_process_03(self):
partner_1 = self.env["res.partner"].create(
{"name": "TEST-PARTNER1", "ref": "CUSTOM-REF"}
)
- partner_1.refresh()
+ partner_1.invalidate_cache()
self.assertEqual(
partner_1.dms_directory_ids.name, "%s-%s" % (partner_1.name, partner_1.ref)
)
diff --git a/dms_field/views/dms_directory.xml b/dms_field/views/dms_directory.xml
index 447fc0e26..2e090c416 100644
--- a/dms_field/views/dms_directory.xml
+++ b/dms_field/views/dms_directory.xml
@@ -5,10 +5,11 @@
dms.directory.dms_tree (in dms_field)
dms.directory
+ dms_list
-
+
-
+
diff --git a/dms_field/views/dms_field_template_views.xml b/dms_field/views/dms_field_template_views.xml
index da8085124..3ae09bbae 100644
--- a/dms_field/views/dms_field_template_views.xml
+++ b/dms_field/views/dms_field_template_views.xml
@@ -43,7 +43,11 @@
string="Documents"
attrs="{'invisible':['|', ('storage_id', '=', False), ('model_id', '=', False)]}"
>
-
+
diff --git a/dms_field/views/dms_storage.xml b/dms_field/views/dms_storage.xml
index 538e1c4e8..e39308c77 100644
--- a/dms_field/views/dms_storage.xml
+++ b/dms_field/views/dms_storage.xml
@@ -5,16 +5,17 @@
dms.storage.dms_tree (in dms_field)
dms.storage
+ dms_list
-
+
-
+
Documents
dms.storage
- dms_tree
+ dms_list
[]
{}