Initial commit: OCA Technical packages (595 packages)
44
odoo-bringout-oca-dms-dms_field/README.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# DMS Field
|
||||
|
||||
Odoo addon: dms_field
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install odoo-bringout-oca-dms-dms_field
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
This addon depends on:
|
||||
- dms
|
||||
|
||||
## Manifest Information
|
||||
|
||||
- **Name**: DMS Field
|
||||
- **Version**: 16.0.1.1.5
|
||||
- **Category**: N/A
|
||||
- **License**: LGPL-3
|
||||
- **Installable**: False
|
||||
|
||||
## Source
|
||||
|
||||
Based on [OCA/dms](https://github.com/OCA/dms) branch 16.0, addon `dms_field`.
|
||||
|
||||
## License
|
||||
|
||||
This package maintains the original LGPL-3 license from the upstream Odoo project.
|
||||
|
||||
## Documentation
|
||||
|
||||
- Overview: doc/OVERVIEW.md
|
||||
- Architecture: doc/ARCHITECTURE.md
|
||||
- Models: doc/MODELS.md
|
||||
- Controllers: doc/CONTROLLERS.md
|
||||
- Wizards: doc/WIZARDS.md
|
||||
- Install: doc/INSTALL.md
|
||||
- Usage: doc/USAGE.md
|
||||
- Configuration: doc/CONFIGURATION.md
|
||||
- Dependencies: doc/DEPENDENCIES.md
|
||||
- Troubleshooting: doc/TROUBLESHOOTING.md
|
||||
- FAQ: doc/FAQ.md
|
||||
117
odoo-bringout-oca-dms-dms_field/dms_field/README.rst
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
=========
|
||||
DMS Field
|
||||
=========
|
||||
|
||||
..
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:4c2029fa91a7142bb6adb4fa9c78281736dbf3f2b2bce45b90ae068dba046f41
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Beta
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
|
||||
: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/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-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=16.0
|
||||
:alt: Try me on Runboat
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||
|
||||
This addon creates a new kind of view and allows to define a folder
|
||||
related to a record.
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
To use the embedded view in any module, the module must inherit from the mixin
|
||||
dms.field.mixin (You have an example with res.partner in this module).
|
||||
|
||||
Once this is done, in the form view of the model we will have to add the following:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<field name="dms_directory_ids" mode="dms_list" />
|
||||
|
||||
In addition, it will be necessary to create an Embedded DMS template for this model.
|
||||
|
||||
#. *Go to Documents > Configuration > Embedded DMS templates* and create a new record.
|
||||
#. Set a storage, a model (res.partner for example) and the access groups you want.
|
||||
#. You can also use expressions in "Directory format name", for example: {{object.name}}
|
||||
#. Click on the "Documents" tab icon and a folder hierarchy will be created.
|
||||
#. You can set here the hierarchy of directories, subdirectories and files you need, this hierarchy will be used as a base when creating a new record (res.partner for example).
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
#. Go to the form view of an existing partner and click on the "DMS" tab icon, a hierarchy of
|
||||
folders and files linked to that record will be created.
|
||||
#. Create a new partner. A hierarchy of folders and files linked to that record will be created.
|
||||
|
||||
|
||||
Known issues / Roadmap
|
||||
======================
|
||||
|
||||
- Add drag & drop compatibility to the dms_tree mode
|
||||
- Multiple selection support (e.g. cut several files and paste to another folder).
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/dms/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 <https://github.com/OCA/dms/issues/new?body=module:%20dms_field%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Creu Blanca
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Enric Tobella <etobella@creublanca.es>
|
||||
* Jaime Arroyo <jaime.arroyo@creublanca.es>
|
||||
|
||||
* `Tecnativa <https://www.tecnativa.com>`_:
|
||||
|
||||
* Víctor Martínez
|
||||
* Carlos Roca
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
This module is part of the `OCA/dms <https://github.com/OCA/dms/tree/16.0/dms_field>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
1
odoo-bringout-oca-dms-dms_field/dms_field/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from . import models
|
||||
33
odoo-bringout-oca-dms-dms_field/dms_field/__manifest__.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Copyright 2020 Creu Blanca
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
{
|
||||
"name": "DMS Field",
|
||||
"summary": """
|
||||
Create DMS View and allow to use them inside a record""",
|
||||
"version": "16.0.1.1.5",
|
||||
"license": "LGPL-3",
|
||||
"author": "Creu Blanca,Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/dms",
|
||||
"depends": ["dms"],
|
||||
"data": [
|
||||
"views/dms_access_group_views.xml",
|
||||
"views/dms_directory.xml",
|
||||
"views/dms_field_template_views.xml",
|
||||
"views/dms_storage.xml",
|
||||
"security/ir.model.access.csv",
|
||||
"security/security.xml",
|
||||
],
|
||||
"assets": {
|
||||
"web.assets_backend": [
|
||||
"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",
|
||||
),
|
||||
],
|
||||
},
|
||||
"demo": ["demo/partner_dms.xml"],
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="view_partner_form" model="ir.ui.view">
|
||||
<field name="name">res.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form" />
|
||||
<field name="arch" type="xml">
|
||||
<notebook position="inside">
|
||||
<page
|
||||
name="dms"
|
||||
string="DMS"
|
||||
attrs="{'invisible': [('id', '=', False)]}"
|
||||
>
|
||||
<field name="dms_directory_ids" mode="dms_list" />
|
||||
</page>
|
||||
</notebook>
|
||||
</field>
|
||||
</record>
|
||||
<record id="access_group_demo" model="dms.access.group">
|
||||
<field name="name">Admin (dms_field module)</field>
|
||||
<field name="perm_create">True</field>
|
||||
<field name="perm_write">True</field>
|
||||
<field name="perm_unlink">True</field>
|
||||
<field
|
||||
name="explicit_user_ids"
|
||||
eval="[(6, 0, [ref('base.user_admin'), ref('base.user_demo')])]"
|
||||
/>
|
||||
</record>
|
||||
<record id="field_template_partner" model="dms.field.template">
|
||||
<field name="name">Partner</field>
|
||||
<field name="storage_id" ref="dms.storage_demo" />
|
||||
<field name="model_id" ref="base.model_res_partner" />
|
||||
<field name="group_ids" eval="[(6, 0, [ref('dms_field.access_group_demo')])]" />
|
||||
</record>
|
||||
</odoo>
|
||||
395
odoo-bringout-oca-dms-dms_field/dms_field/i18n/bs.po
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * dms_field
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_ir_actions_act_window_view
|
||||
msgid "Action Window View"
|
||||
msgstr "Radni prozor"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Actions"
|
||||
msgstr "Akcije"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Add Directory: "
|
||||
msgstr "Dodaj direktorij: "
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Add File: "
|
||||
msgstr "Dodaj datoteku: "
|
||||
|
||||
#. module: dms_field
|
||||
#: model:dms.access.group,name:dms_field.access_group_demo
|
||||
msgid "Admin (dms_field module)"
|
||||
msgstr "Administrator (dms_field modul)"
|
||||
|
||||
#. 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 "Došlo je do pogreške tijekom učitavanja"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/dms_field_template.py:0
|
||||
#, python-format
|
||||
msgid "Autogenerated group from %(model)s (%(name)s) #%(id)s"
|
||||
msgstr "Automatski generisana grupa iz %(model)s (%(name)s) #%(id)s"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__company_id
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__company_id
|
||||
msgid "Company"
|
||||
msgstr "Preduzeće"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_res_partner
|
||||
msgid "Contact"
|
||||
msgstr "Kontakt"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Create File"
|
||||
msgstr "Kreiraj datoteku"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Create directory"
|
||||
msgstr "Kreiraj direktorij"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Kreirao"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Kreirano"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Cut"
|
||||
msgstr "Izreži"
|
||||
|
||||
#. module: dms_field
|
||||
#: model_terms:ir.ui.view,arch_db:dms_field.view_partner_form
|
||||
msgid "DMS"
|
||||
msgstr "DMS"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_mixin__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_res_partner__dms_directory_ids
|
||||
#: model:ir.model.fields,field_description:dms_field.field_res_users__dms_directory_ids
|
||||
msgid "DMS Directories"
|
||||
msgstr "DMS direktoriji"
|
||||
|
||||
#. module: dms_field
|
||||
#: 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 "DMS stablo"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__dms_field_ref
|
||||
msgid "DMS field reference"
|
||||
msgstr "Referenca DMS polja"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Delete"
|
||||
msgstr "Obriši"
|
||||
|
||||
#. 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"
|
||||
msgstr "Direktoriji ovog skladišta moraju biti povezani sa zapisom"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_directory
|
||||
msgid "Directory"
|
||||
msgstr "Imenik"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__directory_format_name
|
||||
msgid "Directory format name"
|
||||
msgstr "Format naziva direktorija"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Prikazani naziv"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_field_template
|
||||
msgid "Dms Field Template"
|
||||
msgstr "DMS šablon polja"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.actions.act_window,name:dms_field.dms_storage_act_window
|
||||
#: model:ir.ui.menu,name:dms_field.dms_storage_menu
|
||||
#: model_terms:ir.ui.view,arch_db:dms_field.view_dms_field_template_form
|
||||
msgid "Documents"
|
||||
msgstr "Dokumenti"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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 "Preuzimanje"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Elements:"
|
||||
msgstr "Elementi:"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.actions.act_window,name:dms_field.action_dms_field_template
|
||||
#: model:ir.ui.menu,name:dms_field.menu_dms_field_template
|
||||
msgid "Embedded DMS templates"
|
||||
msgstr "Ugrađeni DMS šabloni"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_storage__field_template_ids
|
||||
msgid "File templated ids"
|
||||
msgstr "ID-jevi datoteka šablona"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Files:"
|
||||
msgstr "Datoteke:"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__group_ids
|
||||
msgid "Groups"
|
||||
msgstr "Grupe"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__id
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Zadnje mijenjano"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Zadnji ažurirao"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Zadnje ažurirano"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_field_mixin
|
||||
msgid "Mixin to use DMS Field"
|
||||
msgstr "Mješavina za korištenje DMS polja"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__model_id
|
||||
msgid "Model"
|
||||
msgstr "Model"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__model
|
||||
msgid "Model name"
|
||||
msgstr "Model"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/ir_ui_view.py:0
|
||||
#, python-format
|
||||
msgid "Model not found: %(model)s"
|
||||
msgstr "Model nije pronađen: %(model)s"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__name
|
||||
msgid "Name"
|
||||
msgstr "Naziv:"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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 "Otvori"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Open: "
|
||||
msgstr "Otvori: "
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_directory__parent_id
|
||||
msgid "Parent Directory"
|
||||
msgstr "Roditeljski direktorij"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__parent_directory_id
|
||||
msgid "Parent directory"
|
||||
msgstr "Roditeljski direktorij"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Paste"
|
||||
msgstr "Zalijepi"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Preview"
|
||||
msgstr "Pregled"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_access_group
|
||||
msgid "Record Access Groups"
|
||||
msgstr "Grupe pristupa zapisa"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Rename"
|
||||
msgstr "Preimenuj"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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 "Veličina:"
|
||||
|
||||
#. 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"
|
||||
msgstr "Neki direktoriji su nekonzistentni sa modelima skladišta"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_storage
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__storage_id
|
||||
msgid "Storage"
|
||||
msgstr "Skladište"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Subdirectories:"
|
||||
msgstr "Poddirektoriji:"
|
||||
|
||||
#. 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 "Postoje direktoriji koji nisu povezani sa zapisom"
|
||||
|
||||
#. 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 "Već je kreiran povezani direktorij."
|
||||
|
||||
#. 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 "Već je kreiran šablon za ovaj model."
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/dms_access_group.py:0
|
||||
#, python-format
|
||||
msgid "There is already an access group created for this record."
|
||||
msgstr "Već je kreirana grupa pristupa za ovaj zapis."
|
||||
|
||||
#. 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 "Nema šablona povezanog sa ovim modelom"
|
||||
|
||||
#. 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"
|
||||
msgstr "Ovaj zapis je već povezan u ovom skladištu"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__user_field_id
|
||||
msgid "User field"
|
||||
msgstr "Korisničko polje"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_ir_ui_view
|
||||
msgid "View"
|
||||
msgstr "Pregled"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_window_view__view_mode
|
||||
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_view__type
|
||||
msgid "View Type"
|
||||
msgstr "Vrsta pregleda"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,help:dms_field.field_dms_field_template__directory_format_name
|
||||
msgid ""
|
||||
"You can set expressions to be used for the directory name,\n"
|
||||
" e.g.: {{object.name}}"
|
||||
msgstr ""
|
||||
395
odoo-bringout-oca-dms-dms_field/dms_field/i18n/dms_field.pot
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * dms_field
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_ir_actions_act_window_view
|
||||
msgid "Action Window View"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
#: model:dms.access.group,name:dms_field.access_group_demo
|
||||
msgid "Admin (dms_field module)"
|
||||
msgstr ""
|
||||
|
||||
#. 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 ""
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/dms_field_template.py:0
|
||||
#, python-format
|
||||
msgid "Autogenerated group from %(model)s (%(name)s) #%(id)s"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__company_id
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__company_id
|
||||
msgid "Company"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_res_partner
|
||||
msgid "Contact"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Create directory"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__create_uid
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__create_date
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#: model_terms:ir.ui.view,arch_db:dms_field.view_partner_form
|
||||
msgid "DMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_mixin__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_res_partner__dms_directory_ids
|
||||
#: model:ir.model.fields,field_description:dms_field.field_res_users__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_list
|
||||
#: model:ir.model.fields.selection,name:dms_field.selection__ir_ui_view__type__dms_list
|
||||
msgid "DMS Tree"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__dms_field_ref
|
||||
msgid "DMS field reference"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_directory
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__directory_format_name
|
||||
msgid "Directory format name"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_field_template
|
||||
msgid "Dms Field Template"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.actions.act_window,name:dms_field.dms_storage_act_window
|
||||
#: model:ir.ui.menu,name:dms_field.dms_storage_menu
|
||||
#: model_terms:ir.ui.view,arch_db:dms_field.view_dms_field_template_form
|
||||
msgid "Documents"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Elements:"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.actions.act_window,name:dms_field.action_dms_field_template
|
||||
#: model:ir.ui.menu,name:dms_field.menu_dms_field_template
|
||||
msgid "Embedded DMS templates"
|
||||
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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Files:"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__group_ids
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_field_mixin
|
||||
msgid "Mixin to use DMS Field"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__model_id
|
||||
msgid "Model"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__model
|
||||
msgid "Model name"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/ir_ui_view.py:0
|
||||
#, python-format
|
||||
msgid "Model not found: %(model)s"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__name
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Open: "
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_directory__parent_id
|
||||
msgid "Parent Directory"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__parent_directory_id
|
||||
msgid "Parent directory"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Preview"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_access_group
|
||||
msgid "Record Access Groups"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. 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"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_storage
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__storage_id
|
||||
msgid "Storage"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Subdirectories:"
|
||||
msgstr ""
|
||||
|
||||
#. 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 ""
|
||||
|
||||
#. 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 ""
|
||||
|
||||
#. 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 ""
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/dms_access_group.py:0
|
||||
#, python-format
|
||||
msgid "There is already an access group created for this record."
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__user_field_id
|
||||
msgid "User field"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_ir_ui_view
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_window_view__view_mode
|
||||
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_view__type
|
||||
msgid "View Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,help:dms_field.field_dms_field_template__directory_format_name
|
||||
msgid ""
|
||||
"You can set expressions to be used for the directory name,\n"
|
||||
" e.g.: {{object.name}}"
|
||||
msgstr ""
|
||||
519
odoo-bringout-oca-dms-dms_field/dms_field/i18n/es.po
Normal file
|
|
@ -0,0 +1,519 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * dms_field
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 15.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-16 11:00+0000\n"
|
||||
"PO-Revision-Date: 2024-04-16 13:01+0200\n"
|
||||
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Poedit 3.0.1\n"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_ir_actions_act_window_view
|
||||
msgid "Action Window View"
|
||||
msgstr "Vista de la ventana de acción"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
#: model:dms.access.group,name:dms_field.access_group_demo
|
||||
msgid "Admin (dms_field module)"
|
||||
msgstr ""
|
||||
|
||||
#. 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 "Autogenerated group from %(model)s (%(name)s) #%(id)s"
|
||||
msgstr "Grupo autogenerado desde %(model)s (%(name)s) #%(id)s"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__company_id
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__company_id
|
||||
msgid "Company"
|
||||
msgstr "Compañía"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_res_partner
|
||||
msgid "Contact"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. 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"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Creado por"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Creado el"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#: model_terms:ir.ui.view,arch_db:dms_field.view_partner_form
|
||||
msgid "DMS"
|
||||
msgstr "DMS"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_mixin__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_res_partner__dms_directory_ids
|
||||
#: model:ir.model.fields,field_description:dms_field.field_res_users__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_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
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__dms_field_ref
|
||||
msgid "DMS field reference"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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"
|
||||
msgstr ""
|
||||
"Los directorios de este almacenamiento deben estar relacionados con un "
|
||||
"registro"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_directory
|
||||
msgid "Directory"
|
||||
msgstr "Directorio"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__directory_format_name
|
||||
msgid "Directory format name"
|
||||
msgstr "Formato de nombre del directorio"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nombre a Mostrar"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_field_template
|
||||
msgid "Dms Field Template"
|
||||
msgstr "Plantilla de Campo Dms"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.actions.act_window,name:dms_field.dms_storage_act_window
|
||||
#: model:ir.ui.menu,name:dms_field.dms_storage_menu
|
||||
#: model_terms:ir.ui.view,arch_db:dms_field.view_dms_field_template_form
|
||||
msgid "Documents"
|
||||
msgstr "Documentos"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Elements:"
|
||||
msgstr "Elementos:"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.actions.act_window,name:dms_field.action_dms_field_template
|
||||
#: model:ir.ui.menu,name:dms_field.menu_dms_field_template
|
||||
msgid "Embedded DMS templates"
|
||||
msgstr "Plantillas DMS embebidas"
|
||||
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Files:"
|
||||
msgstr "Archivos:"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__group_ids
|
||||
msgid "Groups"
|
||||
msgstr "Grupos"
|
||||
|
||||
#. 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
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Última Modificación el"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Última actualización por"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Última Actualización el"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_field_mixin
|
||||
msgid "Mixin to use DMS Field"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__model_id
|
||||
msgid "Model"
|
||||
msgstr "Modelo"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__model
|
||||
msgid "Model name"
|
||||
msgstr "Nombre de modelo"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/ir_ui_view.py:0
|
||||
#, python-format
|
||||
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
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Open: "
|
||||
msgstr "Abrir "
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_directory__parent_id
|
||||
msgid "Parent Directory"
|
||||
msgstr "Directorio parental"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__parent_directory_id
|
||||
msgid "Parent directory"
|
||||
msgstr "Carpeta padre"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Preview"
|
||||
msgstr "Previsualizar"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_access_group
|
||||
msgid "Record Access Groups"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. 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"
|
||||
msgstr ""
|
||||
"Algunos directorios tienen incompatibilidades con los modelos de "
|
||||
"almacenamiento"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_storage
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__storage_id
|
||||
msgid "Storage"
|
||||
msgstr "Almacenamiento"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. 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_access_group.py:0
|
||||
#, python-format
|
||||
msgid "There is already an access group created for this record."
|
||||
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 "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"
|
||||
msgstr "Este registro ya está relacionado en este almacenamiento"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__user_field_id
|
||||
msgid "User field"
|
||||
msgstr "Campo de usuario"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_ir_ui_view
|
||||
msgid "View"
|
||||
msgstr "Vista"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_window_view__view_mode
|
||||
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_view__type
|
||||
msgid "View Type"
|
||||
msgstr "Tipo de vista"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,help:dms_field.field_dms_field_template__directory_format_name
|
||||
msgid ""
|
||||
"You can set expressions to be used for the directory name,\n"
|
||||
" e.g.: {{object.name}}"
|
||||
msgstr ""
|
||||
"Puede utilizar expresiones para definir el nombre del directorio,\n"
|
||||
"\tejemplo: {{object.name}}"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "A file with the same name already exists"
|
||||
#~ msgstr "Ya existe un archivo con el mismo nombre"
|
||||
|
||||
#~ msgid "Base"
|
||||
#~ msgstr "Base/Fuente"
|
||||
|
||||
#, 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."
|
||||
395
odoo-bringout-oca-dms-dms_field/dms_field/i18n/fr.po
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * dms_field
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 12.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_ir_actions_act_window_view
|
||||
msgid "Action Window View"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
#: model:dms.access.group,name:dms_field.access_group_demo
|
||||
msgid "Admin (dms_field module)"
|
||||
msgstr ""
|
||||
|
||||
#. 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 ""
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/dms_field_template.py:0
|
||||
#, python-format
|
||||
msgid "Autogenerated group from %(model)s (%(name)s) #%(id)s"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__company_id
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__company_id
|
||||
msgid "Company"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_res_partner
|
||||
msgid "Contact"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Create directory"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__create_uid
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__create_date
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#: model_terms:ir.ui.view,arch_db:dms_field.view_partner_form
|
||||
msgid "DMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_mixin__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_res_partner__dms_directory_ids
|
||||
#: model:ir.model.fields,field_description:dms_field.field_res_users__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_list
|
||||
#: model:ir.model.fields.selection,name:dms_field.selection__ir_ui_view__type__dms_list
|
||||
msgid "DMS Tree"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__dms_field_ref
|
||||
msgid "DMS field reference"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_directory
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__directory_format_name
|
||||
msgid "Directory format name"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_field_template
|
||||
msgid "Dms Field Template"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.actions.act_window,name:dms_field.dms_storage_act_window
|
||||
#: model:ir.ui.menu,name:dms_field.dms_storage_menu
|
||||
#: model_terms:ir.ui.view,arch_db:dms_field.view_dms_field_template_form
|
||||
msgid "Documents"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Elements:"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.actions.act_window,name:dms_field.action_dms_field_template
|
||||
#: model:ir.ui.menu,name:dms_field.menu_dms_field_template
|
||||
msgid "Embedded DMS templates"
|
||||
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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Files:"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__group_ids
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_field_mixin
|
||||
msgid "Mixin to use DMS Field"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__model_id
|
||||
msgid "Model"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__model
|
||||
msgid "Model name"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/ir_ui_view.py:0
|
||||
#, python-format
|
||||
msgid "Model not found: %(model)s"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__name
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Open: "
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_directory__parent_id
|
||||
msgid "Parent Directory"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__parent_directory_id
|
||||
msgid "Parent directory"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Preview"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_access_group
|
||||
msgid "Record Access Groups"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. 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
|
||||
#. odoo-javascript
|
||||
#: 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"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_storage
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__storage_id
|
||||
msgid "Storage"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Subdirectories:"
|
||||
msgstr ""
|
||||
|
||||
#. 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 ""
|
||||
|
||||
#. 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 ""
|
||||
|
||||
#. 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 ""
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/dms_access_group.py:0
|
||||
#, python-format
|
||||
msgid "There is already an access group created for this record."
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__user_field_id
|
||||
msgid "User field"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_ir_ui_view
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_window_view__view_mode
|
||||
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_view__type
|
||||
msgid "View Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,help:dms_field.field_dms_field_template__directory_format_name
|
||||
msgid ""
|
||||
"You can set expressions to be used for the directory name,\n"
|
||||
" e.g.: {{object.name}}"
|
||||
msgstr ""
|
||||
586
odoo-bringout-oca-dms-dms_field/dms_field/i18n/it.po
Normal file
|
|
@ -0,0 +1,586 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * dms_field
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 15.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2024-11-26 20:06+0000\n"
|
||||
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.6.2\n"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_ir_actions_act_window_view
|
||||
msgid "Action Window View"
|
||||
msgstr "Vista maschera azione"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Actions"
|
||||
msgstr "Azioni"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Add Directory: "
|
||||
msgstr "Aggiungi cartella: "
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Add File: "
|
||||
msgstr "Aggiungi file: "
|
||||
|
||||
#. module: dms_field
|
||||
#: model:dms.access.group,name:dms_field.access_group_demo
|
||||
msgid "Admin (dms_field module)"
|
||||
msgstr "Amministratore (modulo dms_field)"
|
||||
|
||||
#. 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 "Si è verificato un errore durante il caricamento"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/dms_field_template.py:0
|
||||
#, python-format
|
||||
msgid "Autogenerated group from %(model)s (%(name)s) #%(id)s"
|
||||
msgstr "Gruppo autogenerato da %(model)s (%(name)s) n°%(id)s"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__company_id
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__company_id
|
||||
msgid "Company"
|
||||
msgstr "Azienda"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_res_partner
|
||||
msgid "Contact"
|
||||
msgstr "Contatto"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Create File"
|
||||
msgstr "Crea file"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Create directory"
|
||||
msgstr "Crea cartella"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Creato da"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Creato il"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Cut"
|
||||
msgstr "Taglia"
|
||||
|
||||
#. module: dms_field
|
||||
#: model_terms:ir.ui.view,arch_db:dms_field.view_partner_form
|
||||
msgid "DMS"
|
||||
msgstr "DMS"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_mixin__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_res_partner__dms_directory_ids
|
||||
#: model:ir.model.fields,field_description:dms_field.field_res_users__dms_directory_ids
|
||||
msgid "DMS Directories"
|
||||
msgstr "Cartelle DMS"
|
||||
|
||||
#. module: dms_field
|
||||
#: 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 "Albero DMS"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__dms_field_ref
|
||||
msgid "DMS field reference"
|
||||
msgstr "Riferimento campo DMS"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Delete"
|
||||
msgstr "Elimina"
|
||||
|
||||
#. 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"
|
||||
msgstr "Le cartelle di questo storage devono essere collegate ad un record"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_directory
|
||||
msgid "Directory"
|
||||
msgstr "Cartella"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__directory_format_name
|
||||
msgid "Directory format name"
|
||||
msgstr "Nome formato cartella"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nome visualizzato"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_field_template
|
||||
msgid "Dms Field Template"
|
||||
msgstr "Modello campo DMS"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.actions.act_window,name:dms_field.dms_storage_act_window
|
||||
#: model:ir.ui.menu,name:dms_field.dms_storage_menu
|
||||
#: model_terms:ir.ui.view,arch_db:dms_field.view_dms_field_template_form
|
||||
msgid "Documents"
|
||||
msgstr "Documenti"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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 "Scarica"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Elements:"
|
||||
msgstr "Elementi:"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.actions.act_window,name:dms_field.action_dms_field_template
|
||||
#: model:ir.ui.menu,name:dms_field.menu_dms_field_template
|
||||
msgid "Embedded DMS templates"
|
||||
msgstr "Modelli DMS incorporati"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_storage__field_template_ids
|
||||
msgid "File templated ids"
|
||||
msgstr "ID file modelli"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Files:"
|
||||
msgstr "File:"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__group_ids
|
||||
msgid "Groups"
|
||||
msgstr "Gruppi"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__id
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Ultima modifica il"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Ultimo aggiornamento di"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Ultimo aggiornamento il"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_field_mixin
|
||||
msgid "Mixin to use DMS Field"
|
||||
msgstr "Mixin per utilizzo campo DMS"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__model_id
|
||||
msgid "Model"
|
||||
msgstr "Modello"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__model
|
||||
msgid "Model name"
|
||||
msgstr "Nome modello"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/ir_ui_view.py:0
|
||||
#, python-format
|
||||
msgid "Model not found: %(model)s"
|
||||
msgstr "Modello non trovato: %(model)s"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__name
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#. module: dms_field
|
||||
#. 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 "Apri"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Open: "
|
||||
msgstr "Apri: "
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_directory__parent_id
|
||||
msgid "Parent Directory"
|
||||
msgstr "Cartella padre"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__parent_directory_id
|
||||
msgid "Parent directory"
|
||||
msgstr "Cartella padre"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Paste"
|
||||
msgstr "Incolla"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Preview"
|
||||
msgstr "Anteprima"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_access_group
|
||||
msgid "Record Access Groups"
|
||||
msgstr "Gruppi di accesso al record"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0
|
||||
#, python-format
|
||||
msgid "Rename"
|
||||
msgstr "Rinomina"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Size:"
|
||||
msgstr "Dimensione:"
|
||||
|
||||
#. 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"
|
||||
msgstr "Alcune cartelle non sono coerenti con i modelli dello storage"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_dms_storage
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__storage_id
|
||||
msgid "Storage"
|
||||
msgstr "Deposito"
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-javascript
|
||||
#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.xml:0
|
||||
#, python-format
|
||||
msgid "Subdirectories:"
|
||||
msgstr "Sottocartelle:"
|
||||
|
||||
#. 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 "Sono presenti cartelle non associate ad un record"
|
||||
|
||||
#. 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 "Esiste già una cartella collegata."
|
||||
|
||||
#. 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 "Esiste già uno schema creato per questo modello."
|
||||
|
||||
#. module: dms_field
|
||||
#. odoo-python
|
||||
#: code:addons/dms_field/models/dms_access_group.py:0
|
||||
#, python-format
|
||||
msgid "There is already an access group created for this record."
|
||||
msgstr "Esiste già un gruppo di accesso creato per questo record."
|
||||
|
||||
#. 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 "Non c'è uno schema collegato a questo modello"
|
||||
|
||||
#. 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"
|
||||
msgstr "Questo record è già correlato a questo storage"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_dms_field_template__user_field_id
|
||||
msgid "User field"
|
||||
msgstr "Campo utente"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model,name:dms_field.model_ir_ui_view
|
||||
msgid "View"
|
||||
msgstr "Vista"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_window_view__view_mode
|
||||
#: model:ir.model.fields,field_description:dms_field.field_ir_ui_view__type
|
||||
msgid "View Type"
|
||||
msgstr "Tipo vista"
|
||||
|
||||
#. module: dms_field
|
||||
#: model:ir.model.fields,help:dms_field.field_dms_field_template__directory_format_name
|
||||
msgid ""
|
||||
"You can set expressions to be used for the directory name,\n"
|
||||
" e.g.: {{object.name}}"
|
||||
msgstr ""
|
||||
"Si possono impostare espressioni da utilizzare per il nome della cartella,\n"
|
||||
" es.: {{object.name}}"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Action Buttons"
|
||||
#~ msgstr "Pulsanti azione"
|
||||
|
||||
#~ msgid "Base"
|
||||
#~ msgstr "Base"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Close the selected node"
|
||||
#~ msgstr "Chiudi il nodo selezionato"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Context Menu"
|
||||
#~ msgstr "Menù contestuale"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Create"
|
||||
#~ msgstr "Crea"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Directory %s must be root in order to be related to a record"
|
||||
#~ msgstr "La cartella %s deve essere radice per essere collegata ad un record"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Drag and Drop"
|
||||
#~ msgstr "Tascina e rilascia"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "END"
|
||||
#~ msgstr "FINE"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Edit"
|
||||
#~ msgstr "Modifica"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Edit the selected node"
|
||||
#~ msgstr "Modifica il nodo selezionato"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "F2"
|
||||
#~ msgstr "F2"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "HOME"
|
||||
#~ msgstr "HOME"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Jump to the bottom"
|
||||
#~ msgstr "Salta fino in fondo"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Jump to the top"
|
||||
#~ msgstr "Salta in cima"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Keyboard Shortcuts"
|
||||
#~ msgstr "Scorciatoie tastiera"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Move down one node"
|
||||
#~ msgstr "Scendi di un nodo"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Move up one node"
|
||||
#~ msgstr "Sali di un nodo"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Open all nodes"
|
||||
#~ msgstr "Apri tutti i nodi"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Open the selected node"
|
||||
#~ msgstr "Apri il nodo selezionato"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Refresh"
|
||||
#~ msgstr "Aggiorna"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Show Help"
|
||||
#~ msgstr "Mostra aiuto"
|
||||
|
||||
#, 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 ""
|
||||
#~ "Il pulsante azione nella parte superiore della vista può essere "
|
||||
#~ "utilizzato per aprire,\n"
|
||||
#~ " creare, modificare o eliminare 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 ""
|
||||
#~ "Puoi cambiare la struttura spostando i nodi. È anche possibile\n"
|
||||
#~ " creare nuovi nodi trascinando file e anche "
|
||||
#~ "intere strutture\n"
|
||||
#~ " di cartelle nella 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 ""
|
||||
#~ "È possibile aprire un menu contestuale facendo clic con il tasto destro "
|
||||
#~ "su qualsiasi nodo. Questo\n"
|
||||
#~ " contiene ulteriori opzioni per interagire con il "
|
||||
#~ "nodo."
|
||||
|
||||
#~ msgid "Add Directory to a DMS Record"
|
||||
#~ msgstr "Aggiungi cartella a un record DMS"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Add new root directory"
|
||||
#~ msgstr "Aggiungi una nuova cartella radice"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Create:"
|
||||
#~ msgstr "Crea:"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Delete:"
|
||||
#~ msgstr "Elimina:"
|
||||
|
||||
#~ msgid "Dms Add Directory Record"
|
||||
#~ msgstr "Aggiungi record cartella DMS"
|
||||
|
||||
#~ msgid "Everyone for Partner DMS"
|
||||
#~ msgstr "Tutti per il DMS del partner"
|
||||
|
||||
#~ msgid "Field Default Group"
|
||||
#~ msgstr "Campo gruppo predefinito"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Name:"
|
||||
#~ msgstr "Nome:"
|
||||
|
||||
#~ msgid "Possible storages"
|
||||
#~ msgstr "Storage possibili"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Preview/download"
|
||||
#~ msgstr "Anteprima/download"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Read:"
|
||||
#~ msgstr "Leggi:"
|
||||
|
||||
#~ msgid "Res"
|
||||
#~ msgstr "Res"
|
||||
|
||||
#~ msgid "Res Model"
|
||||
#~ msgstr "Modello res"
|
||||
|
||||
#, python-format
|
||||
#~ msgid ""
|
||||
#~ "Storage %s should need to be assigned to a model in order to relate the "
|
||||
#~ "directory to a record"
|
||||
#~ msgstr ""
|
||||
#~ "Dovrebbe essere necessario assegnare lo storage %s a un modello per "
|
||||
#~ "correlare la cartella a un record"
|
||||
|
||||
#, python-format
|
||||
#~ msgid ""
|
||||
#~ "Storage %s should need to be assigned to a model related to the storage"
|
||||
#~ msgstr ""
|
||||
#~ "Dovrebbe essere necessario assegnare lo storage %s a un modello correlato "
|
||||
#~ "allo storage"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Write:"
|
||||
#~ msgstr "Scrivi:"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "no"
|
||||
#~ msgstr "no"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "yes"
|
||||
#~ msgstr "si"
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
from . import dms_field_mixin
|
||||
from . import ir_actions_act_window_view
|
||||
from . import ir_ui_view
|
||||
from . import dms_access_group
|
||||
from . import dms_storage
|
||||
from . import dms_directory
|
||||
from . import dms_field_template
|
||||
from . import res_partner
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
# Copyright 2024 Tecnativa - Víctor Martínez
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class DmsAccessGroups(models.Model):
|
||||
_inherit = "dms.access.group"
|
||||
|
||||
dms_field_ref = fields.Reference(
|
||||
selection="_selection_reference_value",
|
||||
string="DMS field reference",
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
compute="_compute_company_id",
|
||||
comodel_name="res.company",
|
||||
string="Company",
|
||||
store=True,
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _selection_reference_value(self):
|
||||
models = (
|
||||
self.env["ir.model"]
|
||||
.sudo()
|
||||
.search([("transient", "=", False)], order="name asc")
|
||||
)
|
||||
return [(model.model, model.name) for model in models]
|
||||
|
||||
@api.depends("dms_field_ref")
|
||||
def _compute_company_id(self):
|
||||
self.company_id = False
|
||||
for item in self.filtered("dms_field_ref"):
|
||||
item.company_id = (
|
||||
item.dms_field_ref.company_id
|
||||
if "company_id" in item.dms_field_ref._fields
|
||||
else False
|
||||
)
|
||||
|
||||
def _get_item_from_dms_field_ref(self, record):
|
||||
return self.env["dms.access.group"].search(
|
||||
[("dms_field_ref", "=", "%s,%s" % (record._name, record.id))]
|
||||
)
|
||||
|
||||
@api.constrains("dms_field_ref")
|
||||
def _check_dms_field_ref(self):
|
||||
for item in self.filtered("dms_field_ref"):
|
||||
dms_field_ref = "%s,%s" % (item.dms_field_ref._name, item.dms_field_ref.id)
|
||||
if self.search(
|
||||
[("dms_field_ref", "=", dms_field_ref), ("id", "!=", item.id)]
|
||||
):
|
||||
raise UserError(
|
||||
_("There is already an access group created for this record.")
|
||||
)
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
# Copyright 2020 Creu Blanca
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.osv import expression
|
||||
|
||||
|
||||
class DmsDirectory(models.Model):
|
||||
_inherit = "dms.directory"
|
||||
|
||||
parent_id = fields.Many2one(default=lambda self: self._default_parent())
|
||||
|
||||
@api.model
|
||||
def _default_parent(self):
|
||||
return self.env.context.get("default_parent_directory_id", False)
|
||||
|
||||
@api.constrains("res_id", "is_root_directory", "storage_id", "res_model")
|
||||
def _check_resource(self):
|
||||
for directory in self:
|
||||
if directory.storage_id.save_type == "attachment":
|
||||
continue
|
||||
if (
|
||||
directory.is_root_directory
|
||||
and directory.storage_id.model_ids
|
||||
and not directory.res_id
|
||||
):
|
||||
raise ValidationError(
|
||||
_("Directories of this storage must be related to a record")
|
||||
)
|
||||
if not directory.res_id:
|
||||
continue
|
||||
if self.search(
|
||||
[
|
||||
("storage_id", "=", directory.storage_id.id),
|
||||
("id", "!=", directory.id),
|
||||
("res_id", "=", directory.res_id),
|
||||
("res_model", "=", directory.res_model),
|
||||
],
|
||||
limit=1,
|
||||
):
|
||||
raise ValidationError(
|
||||
_("This record is already related in this storage")
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _build_documents_view_directory(self, directory):
|
||||
return {
|
||||
"id": "directory_%s" % directory.id,
|
||||
"text": directory.name,
|
||||
"icon": "fa fa-folder-o",
|
||||
"type": "directory",
|
||||
"data": {"odoo_id": directory.id, "odoo_model": "dms.directory"},
|
||||
"children": directory.count_elements > 0,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _check_parent_field(self):
|
||||
if self._parent_name not in self._fields:
|
||||
raise TypeError("The parent (%s) field does not exist." % self._parent_name)
|
||||
|
||||
@api.model
|
||||
def search_read_parents(
|
||||
self, domain=False, fields=None, offset=0, limit=None, order=None
|
||||
):
|
||||
"""This method finds the top level elements of the hierarchy
|
||||
for a given search query.
|
||||
|
||||
:param domain: a search domain <reference/orm/domains> (default: empty list)
|
||||
:param fields: a list of fields to read (default: all fields of the model)
|
||||
:param offset: the number of results to ignore (default: none)
|
||||
:param limit: maximum number of records to return (default: all)
|
||||
:param order: a string to define the sort order of the query
|
||||
(default: none)
|
||||
:returns: the top level elements for the given search query
|
||||
"""
|
||||
if not domain:
|
||||
domain = []
|
||||
records = self.search_parents(
|
||||
domain=domain, offset=offset, limit=limit, order=order
|
||||
)
|
||||
if not records:
|
||||
return []
|
||||
if fields and fields == ["id"]:
|
||||
return [{"id": record.id} for record in records]
|
||||
result = records.read(fields)
|
||||
if len(result) <= 1:
|
||||
return result
|
||||
index = {vals["id"]: vals for vals in result}
|
||||
return [index[record.id] for record in records if record.id in index]
|
||||
|
||||
@api.model
|
||||
def search_parents(
|
||||
self, domain=False, offset=0, limit=None, order=None, count=False
|
||||
):
|
||||
"""This method finds the top level elements of the
|
||||
hierarchy for a given search query.
|
||||
|
||||
:param domain: a search domain <reference/orm/domains> (default: empty list)
|
||||
:param offset: the number of results to ignore (default: none)
|
||||
:param limit: maximum number of records to return (default: all)
|
||||
:param order: a string to define the sort order of the query
|
||||
(default: none)
|
||||
:param count: counts and returns the number of matching records
|
||||
(default: False)
|
||||
:returns: the top level elements for the given search query
|
||||
"""
|
||||
if not domain:
|
||||
domain = []
|
||||
res = self._search_parents(
|
||||
domain=domain, offset=offset, limit=limit, order=order, count=count
|
||||
)
|
||||
return res if count else self.browse(res)
|
||||
|
||||
@api.model
|
||||
def _search_parents(
|
||||
self, domain=False, offset=0, limit=None, order=None, count=False
|
||||
):
|
||||
if not domain:
|
||||
domain = []
|
||||
self._check_parent_field()
|
||||
self.check_access_rights("read")
|
||||
if expression.is_false(self, domain):
|
||||
return []
|
||||
query = self._where_calc(domain)
|
||||
self._apply_ir_rules(query, "read")
|
||||
from_clause, where_clause, where_clause_arguments = query.get_sql()
|
||||
parent_where = where_clause and (" WHERE %s" % where_clause) or ""
|
||||
parent_query = 'SELECT "%s".id FROM ' % self._table + from_clause + parent_where
|
||||
no_parent_clause = '"{table}"."{field}" IS NULL'.format(
|
||||
table=self._table, field=self._parent_name
|
||||
)
|
||||
no_access_clause = '"{table}"."{field}" NOT IN ({query})'.format(
|
||||
table=self._table, field=self._parent_name, query=parent_query
|
||||
)
|
||||
parent_clause = "({} OR {})".format(no_parent_clause, no_access_clause)
|
||||
order_by = self._generate_order_by(order, query)
|
||||
from_clause, where_clause, where_clause_params = query.get_sql()
|
||||
where_str = (
|
||||
where_clause
|
||||
and (" WHERE {} AND {}".format(where_clause, parent_clause))
|
||||
or (" WHERE %s" % parent_clause)
|
||||
)
|
||||
if count:
|
||||
# pylint: disable=sql-injection
|
||||
query_str = "SELECT count(1) FROM " + from_clause + where_str
|
||||
self._cr.execute(query_str, where_clause_params)
|
||||
return self._cr.fetchone()[0]
|
||||
limit_str = limit and " limit %s" or ""
|
||||
offset_str = offset and " offset %s" or ""
|
||||
query_str = (
|
||||
'SELECT "%s".id FROM ' % (self._table)
|
||||
+ from_clause
|
||||
+ where_str
|
||||
+ order_by
|
||||
+ limit_str
|
||||
+ offset_str
|
||||
)
|
||||
complete_where_clause_params = where_clause_params + where_clause_arguments
|
||||
if limit:
|
||||
complete_where_clause_params.append(limit)
|
||||
if offset:
|
||||
complete_where_clause_params.append(offset)
|
||||
# pylint: disable=sql-injection
|
||||
self._cr.execute(query_str, complete_where_clause_params)
|
||||
return list({x[0] for x in self._cr.fetchall()})
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
# Copyright 2020 Creu Blanca
|
||||
# Copyright 2024 Tecnativa - Víctor Martínez
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools import config
|
||||
|
||||
|
||||
class DMSFieldMixin(models.AbstractModel):
|
||||
_name = "dms.field.mixin"
|
||||
_description = "Mixin to use DMS Field"
|
||||
|
||||
dms_directory_ids = fields.One2many(
|
||||
"dms.directory",
|
||||
"res_id",
|
||||
string="DMS Directories",
|
||||
domain=lambda self: [
|
||||
("res_model", "=", self._name),
|
||||
("storage_id.save_type", "!=", "attachment"),
|
||||
],
|
||||
auto_join=True,
|
||||
)
|
||||
|
||||
@api.model
|
||||
def models_to_track_dms_field_template(self):
|
||||
"""Models to be tracked for dms field templates
|
||||
:args:
|
||||
:returns: list of models
|
||||
"""
|
||||
return self.env["dms.field.template"].sudo().search([]).mapped("model_id.model")
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
"""Create a dms directory when creating the record if exist a template.
|
||||
We need to avoid applying a template except when testing functionality
|
||||
with dms_field* modules to avoid the error that a directory with the same
|
||||
name already exists (example: create partner).
|
||||
"""
|
||||
result = super().create(vals_list)
|
||||
test_condition = not config["test_enable"] or self.env.context.get(
|
||||
"test_dms_field"
|
||||
)
|
||||
if (
|
||||
test_condition
|
||||
and not self.env.context.get("skip_track_dms_field_template")
|
||||
and self._name in self.models_to_track_dms_field_template()
|
||||
):
|
||||
template = self.env["dms.field.template"].with_context(res_model=self._name)
|
||||
for item in result:
|
||||
template.with_context(res_id=item.id).create_dms_directory()
|
||||
return result
|
||||
|
||||
def write(self, vals):
|
||||
"""When modifying a record that has linked directories and changing the
|
||||
user_id field it is necessary to update the auto-generated access group
|
||||
(name and explicit_user_ids).
|
||||
"""
|
||||
res = super().write(vals)
|
||||
# Apply sudo() in case the user does not have access to the directory
|
||||
for item in self.sudo().filtered("dms_directory_ids"):
|
||||
if "user_id" in vals:
|
||||
template = self.env["dms.field.template"]._get_template_from_model(
|
||||
item._name
|
||||
)
|
||||
if template:
|
||||
template.sudo()._get_autogenerated_group(item)
|
||||
return res
|
||||
|
||||
def unlink(self):
|
||||
"""When deleting a record, we also delete the linked directories and the
|
||||
auto-generated access group.
|
||||
"""
|
||||
# Apply sudo() in case the user does not have access to the directory
|
||||
for record in self.sudo().filtered("dms_directory_ids"):
|
||||
group = (
|
||||
self.env["dms.access.group"].sudo()._get_item_from_dms_field_ref(record)
|
||||
)
|
||||
record.sudo().dms_directory_ids.unlink()
|
||||
group.unlink()
|
||||
return super().unlink()
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
# 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 UserError, ValidationError
|
||||
|
||||
|
||||
class DmsFieldTemplate(models.Model):
|
||||
_name = "dms.field.template"
|
||||
_inherit = "dms.field.mixin"
|
||||
_description = "Dms Field Template"
|
||||
|
||||
name = fields.Char(required=True)
|
||||
company_id = fields.Many2one(
|
||||
comodel_name="res.company",
|
||||
string="Company",
|
||||
store=True,
|
||||
index=True,
|
||||
)
|
||||
storage_id = fields.Many2one(
|
||||
comodel_name="dms.storage",
|
||||
domain=[("save_type", "!=", "attachment")],
|
||||
string="Storage",
|
||||
)
|
||||
parent_directory_id = fields.Many2one(
|
||||
comodel_name="dms.directory",
|
||||
domain="[('storage_id', '=', storage_id)]",
|
||||
string="Parent directory",
|
||||
)
|
||||
model_id = fields.Many2one(
|
||||
comodel_name="ir.model",
|
||||
string="Model",
|
||||
domain=[("transient", "=", False), ("model", "!=", "dms.field.template")],
|
||||
index=True,
|
||||
)
|
||||
model = fields.Char(
|
||||
compute="_compute_model", compute_sudo=True, store=True, string="Model name"
|
||||
)
|
||||
group_ids = fields.Many2many(
|
||||
comodel_name="dms.access.group",
|
||||
string="Groups",
|
||||
)
|
||||
user_field_id = fields.Many2one(
|
||||
comodel_name="ir.model.fields",
|
||||
domain="[('model_id', '=', model_id),('relation', '=', 'res.users')]",
|
||||
string="User field",
|
||||
)
|
||||
directory_format_name = fields.Char(
|
||||
string="Directory format name",
|
||||
default="{{object.display_name}}",
|
||||
help="""You can set expressions to be used for the directory name,
|
||||
e.g.: {{object.name}}""",
|
||||
)
|
||||
|
||||
@api.depends("model_id")
|
||||
def _compute_model(self):
|
||||
for item in self:
|
||||
item.model = item.model_id.model
|
||||
|
||||
def _get_template_from_model(self, model):
|
||||
return self.search([("model", "=", model)], limit=1)
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
"""Create dms directory automatically in the creation in install mode."""
|
||||
result = super().create(vals_list)
|
||||
if self.env.context.get("install_mode"):
|
||||
for item in result:
|
||||
item_ctx = item.with_context(res_model=item._name, res_id=item.id)
|
||||
item_ctx.create_dms_directory()
|
||||
return result
|
||||
|
||||
@api.model
|
||||
def create_dms_directory(self):
|
||||
"""According to the model, create the directory linked to that record
|
||||
and the subdirectories."""
|
||||
res_model = self.env.context.get("res_model")
|
||||
res_id = self.env.context.get("res_id")
|
||||
record = self.env[res_model].browse(res_id)
|
||||
directory_model = self.env["dms.directory"].sudo()
|
||||
if res_model == "dms.field.template":
|
||||
return directory_model.create(
|
||||
{
|
||||
"storage_id": record.storage_id.id,
|
||||
"res_id": record.id,
|
||||
"res_model": record._name,
|
||||
"is_root_directory": True,
|
||||
"name": record.display_name,
|
||||
"group_ids": record.group_ids.ids,
|
||||
}
|
||||
)
|
||||
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(
|
||||
[
|
||||
("parent_id", "=", self.parent_directory_id.id),
|
||||
("res_model", "=", res_model),
|
||||
("res_id", "=", res_id),
|
||||
]
|
||||
)
|
||||
if total_directories > 0:
|
||||
raise ValidationError(_("There is already a linked directory created."))
|
||||
# Create root directory + files
|
||||
dms_directory_ids = template.dms_directory_ids
|
||||
new_directory = directory_model.create(
|
||||
template._prepare_directory_vals(dms_directory_ids, record)
|
||||
)
|
||||
self._copy_files_from_directory(dms_directory_ids, new_directory)
|
||||
# Create child directories
|
||||
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:
|
||||
file.copy({"directory_id": new_directory.id})
|
||||
|
||||
def _prepare_autogenerated_group(self, record):
|
||||
group_name = _("Autogenerated group from %(model)s (%(name)s) #%(id)s") % {
|
||||
"model": record._description,
|
||||
"name": record.display_name,
|
||||
"id": record.id,
|
||||
}
|
||||
vals = {
|
||||
"name": group_name,
|
||||
# We need to set all the permissions so that the user can manage their
|
||||
# documents (directories and files)
|
||||
"perm_create": True,
|
||||
"perm_write": True,
|
||||
"perm_unlink": True,
|
||||
"dms_field_ref": "%s,%s" % (record._name, record.id),
|
||||
"explicit_user_ids": [(5, 0)],
|
||||
}
|
||||
# Apply sudo() because the user may not have permissions to access
|
||||
# ir.model.fields.
|
||||
user_field = self.sudo().user_field_id
|
||||
if user_field:
|
||||
user = record[user_field.name]
|
||||
if user:
|
||||
vals["explicit_user_ids"] += [(4, user.id)]
|
||||
return vals
|
||||
|
||||
def _get_autogenerated_group(self, record):
|
||||
"""Get the existing auto-generated group or create a new one.
|
||||
The permissions of the auto-generated group should be changed
|
||||
to make sure you have the correct data.
|
||||
"""
|
||||
group_model = self.env["dms.access.group"]
|
||||
group_ref = group_model._get_item_from_dms_field_ref(record)
|
||||
if group_ref:
|
||||
group_ref.write(self._prepare_autogenerated_group(record))
|
||||
return group_ref
|
||||
# Create the autogenerated group linked to the record
|
||||
return group_model.create(self._prepare_autogenerated_group(record))
|
||||
|
||||
def _create_child_directories(self, parent, directory):
|
||||
# Create child directories (all leves) + files
|
||||
directory_model = self.env["dms.directory"].sudo()
|
||||
for child_directory in directory.child_directory_ids:
|
||||
child = directory_model.create(
|
||||
{
|
||||
"name": child_directory.name,
|
||||
"is_root_directory": False,
|
||||
"parent_id": parent.id,
|
||||
}
|
||||
)
|
||||
self._copy_files_from_directory(child_directory, child)
|
||||
self._create_child_directories(child, child_directory)
|
||||
|
||||
def _prepare_directory_vals(self, directory, record):
|
||||
# Groups of the new directory will be those of the template + auto-generate
|
||||
groups = directory.group_ids
|
||||
groups += self._get_autogenerated_group(record)
|
||||
directory_name = self.env["mail.render.mixin"]._render_template(
|
||||
self.directory_format_name,
|
||||
record._name,
|
||||
record.ids,
|
||||
engine="inline_template",
|
||||
)[record.id]
|
||||
vals = {
|
||||
"storage_id": directory.storage_id.id,
|
||||
"res_id": record.id,
|
||||
"res_model": record._name,
|
||||
"name": directory_name,
|
||||
"group_ids": [(4, group.id) for group in groups],
|
||||
}
|
||||
if not self.parent_directory_id:
|
||||
vals.update({"is_root_directory": True})
|
||||
else:
|
||||
vals.update(
|
||||
{"parent_id": self.parent_directory_id.id, "inherit_group_ids": False}
|
||||
)
|
||||
return vals
|
||||
|
||||
@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.")
|
||||
)
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
# Copyright 2020 Creu Blanca
|
||||
# Copyright 2024 Tecnativa - Víctor Martínez
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class DmsStorage(models.Model):
|
||||
_inherit = "dms.storage"
|
||||
|
||||
field_template_ids = fields.One2many(
|
||||
comodel_name="dms.field.template",
|
||||
inverse_name="storage_id",
|
||||
string="File templated ids",
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _build_documents_storage(self, storage):
|
||||
storage_directories = []
|
||||
model = self.env["dms.directory"]
|
||||
directories = model.search_parents([["storage_id", "=", storage.id]])
|
||||
for record in directories:
|
||||
storage_directories.append(model._build_documents_view_directory(record))
|
||||
return {
|
||||
"id": "storage_%s" % storage.id,
|
||||
"text": storage.name,
|
||||
"icon": "fa fa-database",
|
||||
"type": "storage",
|
||||
"data": {"odoo_id": storage.id, "odoo_model": "dms.storage"},
|
||||
"children": storage_directories,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def get_js_tree_data(self):
|
||||
return [record._build_documents_storage(record) for record in self.search([])]
|
||||
|
||||
@api.constrains("model_ids", "save_type")
|
||||
def _constrain_model_ids(self):
|
||||
for storage in self:
|
||||
if storage.save_type == "attachment":
|
||||
continue
|
||||
if self.env["dms.directory"].search(
|
||||
[
|
||||
("storage_id", "=", storage.id),
|
||||
("is_root_directory", "=", True),
|
||||
(
|
||||
"res_model",
|
||||
"not in",
|
||||
storage.mapped("model_ids.model"),
|
||||
),
|
||||
]
|
||||
):
|
||||
raise ValidationError(
|
||||
_("Some directories are inconsistent with the storage models")
|
||||
)
|
||||
if storage.model_ids and self.env["dms.directory"].search(
|
||||
[
|
||||
("storage_id", "=", storage.id),
|
||||
("is_root_directory", "=", True),
|
||||
("res_model", "=", False),
|
||||
]
|
||||
):
|
||||
raise ValidationError(
|
||||
_("There are directories not associated to a record")
|
||||
)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# Copyright 2020 Creu Blanca
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class IrActionsActWindowView(models.Model):
|
||||
|
||||
_inherit = "ir.actions.act_window.view"
|
||||
|
||||
view_mode = fields.Selection(
|
||||
selection_add=[("dms_list", "DMS Tree")], ondelete={"dms_list": "cascade"}
|
||||
)
|
||||
|
|
@ -0,0 +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.addons.base.models.ir_ui_view import NameManager
|
||||
|
||||
|
||||
class IrUiView(models.Model):
|
||||
|
||||
_inherit = "ir.ui.view"
|
||||
|
||||
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)
|
||||
|
|
@ -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"]
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
To use the embedded view in any module, the module must inherit from the mixin
|
||||
dms.field.mixin (You have an example with res.partner in this module).
|
||||
|
||||
Once this is done, in the form view of the model we will have to add the following:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<field name="dms_directory_ids" mode="dms_list" />
|
||||
|
||||
In addition, it will be necessary to create an Embedded DMS template for this model.
|
||||
|
||||
#. *Go to Documents > Configuration > Embedded DMS templates* and create a new record.
|
||||
#. Set a storage, a model (res.partner for example) and the access groups you want.
|
||||
#. You can also use expressions in "Directory format name", for example: {{object.name}}
|
||||
#. Click on the "Documents" tab icon and a folder hierarchy will be created.
|
||||
#. You can set here the hierarchy of directories, subdirectories and files you need, this hierarchy will be used as a base when creating a new record (res.partner for example).
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
* Enric Tobella <etobella@creublanca.es>
|
||||
* Jaime Arroyo <jaime.arroyo@creublanca.es>
|
||||
|
||||
* `Tecnativa <https://www.tecnativa.com>`_:
|
||||
|
||||
* Víctor Martínez
|
||||
* Carlos Roca
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
This addon creates a new kind of view and allows to define a folder
|
||||
related to a record.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
- Add drag & drop compatibility to the dms_tree mode
|
||||
- Multiple selection support (e.g. cut several files and paste to another folder).
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#. Go to the form view of an existing partner and click on the "DMS" tab icon, a hierarchy of
|
||||
folders and files linked to that record will be created.
|
||||
#. Create a new partner. A hierarchy of folders and files linked to that record will be created.
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_dms_field_template_user,dms_field_template_user,model_dms_field_template,base.group_user,1,0,0,0
|
||||
access_dms_field_template_manager,dms_field_template_manager,model_dms_field_template,dms.group_dms_manager,1,1,1,1
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="rule_multi_company_dms_field_template" model="ir.rule">
|
||||
<field name="name">DMS Field Template multi-company</field>
|
||||
<field name="model_id" ref="model_dms_field_template" />
|
||||
<field name="global" eval="True" />
|
||||
<field
|
||||
name="domain_force"
|
||||
>['|',('company_id','=',False),('company_id','in',company_ids)]</field>
|
||||
</record>
|
||||
<record id="rule_multi_company_dms_access_group" model="ir.rule">
|
||||
<field name="name">DMS Access Group multi-company</field>
|
||||
<field name="model_id" ref="model_dms_access_group" />
|
||||
<field name="global" eval="True" />
|
||||
<field
|
||||
name="domain_force"
|
||||
>['|',('company_id','=',False),('company_id','in',company_ids)]</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
After Width: | Height: | Size: 9.2 KiB |
|
|
@ -0,0 +1,463 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
|
||||
<title>DMS Field</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
: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.
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title, .code .error {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
.align-center {
|
||||
clear: both ;
|
||||
text-align: center }
|
||||
|
||||
.align-right {
|
||||
text-align: right }
|
||||
|
||||
/* reset inner alignment in figures */
|
||||
div.align-right {
|
||||
text-align: inherit }
|
||||
|
||||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font: inherit }
|
||||
|
||||
pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
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 }
|
||||
pre.code .literal.string, code .literal.string { color: #0C5404 }
|
||||
pre.code .name.builtin, code .name.builtin { color: #352B84 }
|
||||
pre.code .deleted, code .deleted { background-color: #DEB0A1}
|
||||
pre.code .inserted, code .inserted { background-color: #A3D289}
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic, pre.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
/* "booktabs" style (no vertical lines) */
|
||||
table.docutils.booktabs {
|
||||
border: 0px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.docutils.booktabs * {
|
||||
border: 0px;
|
||||
}
|
||||
table.docutils.booktabs th {
|
||||
border-bottom: thin solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="dms-field">
|
||||
<h1 class="title">DMS Field</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:4c2029fa91a7142bb6adb4fa9c78281736dbf3f2b2bce45b90ae068dba046f41
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/dms/tree/16.0/dms_field"><img alt="OCA/dms" src="https://img.shields.io/badge/github-OCA%2Fdms-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/dms-16-0/dms-16-0-dms_field"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/dms&target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
||||
<p>This addon creates a new kind of view and allows to define a folder
|
||||
related to a record.</p>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
|
||||
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
|
||||
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-3">Known issues / Roadmap</a></li>
|
||||
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-4">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="toc-entry-5">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="toc-entry-6">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="toc-entry-7">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="toc-entry-8">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="configuration">
|
||||
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
|
||||
<p>To use the embedded view in any module, the module must inherit from the mixin
|
||||
dms.field.mixin (You have an example with res.partner in this module).</p>
|
||||
<p>Once this is done, in the form view of the model we will have to add the following:</p>
|
||||
<pre class="code xml literal-block">
|
||||
<span class="nt"><field</span><span class="w"> </span><span class="na">name=</span><span class="s">"dms_directory_ids"</span><span class="w"> </span><span class="na">mode=</span><span class="s">"dms_list"</span><span class="w"> </span><span class="nt">/></span>
|
||||
</pre>
|
||||
<p>In addition, it will be necessary to create an Embedded DMS template for this model.</p>
|
||||
<ol class="arabic simple">
|
||||
<li><em>Go to Documents > Configuration > Embedded DMS templates</em> and create a new record.</li>
|
||||
<li>Set a storage, a model (res.partner for example) and the access groups you want.</li>
|
||||
<li>You can also use expressions in “Directory format name”, for example: {{object.name}}</li>
|
||||
<li>Click on the “Documents” tab icon and a folder hierarchy will be created.</li>
|
||||
<li>You can set here the hierarchy of directories, subdirectories and files you need, this hierarchy will be used as a base when creating a new record (res.partner for example).</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="section" id="usage">
|
||||
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
|
||||
<p>#. Go to the form view of an existing partner and click on the “DMS” tab icon, a hierarchy of
|
||||
folders and files linked to that record will be created.
|
||||
#. Create a new partner. A hierarchy of folders and files linked to that record will be created.</p>
|
||||
</div>
|
||||
<div class="section" id="known-issues-roadmap">
|
||||
<h1><a class="toc-backref" href="#toc-entry-3">Known issues / Roadmap</a></h1>
|
||||
<ul class="simple">
|
||||
<li>Add drag & drop compatibility to the dms_tree mode</li>
|
||||
<li>Multiple selection support (e.g. cut several files and paste to another folder).</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#toc-entry-4">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/dms/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/OCA/dms/issues/new?body=module:%20dms_field%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#toc-entry-5">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-6">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Creu Blanca</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-7">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Enric Tobella <<a class="reference external" href="mailto:etobella@creublanca.es">etobella@creublanca.es</a>></li>
|
||||
<li>Jaime Arroyo <<a class="reference external" href="mailto:jaime.arroyo@creublanca.es">jaime.arroyo@creublanca.es</a>></li>
|
||||
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
|
||||
<li>Víctor Martínez</li>
|
||||
<li>Carlos Roca</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#toc-entry-8">Maintainers</a></h2>
|
||||
<p>This module is maintained by the OCA.</p>
|
||||
<a class="reference external image-reference" href="https://odoo-community.org">
|
||||
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
|
||||
</a>
|
||||
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.</p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/dms/tree/16.0/dms_field">OCA/dms</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2014 Ivan Bozhanov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
After Width: | Height: | Size: 3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2014 Orange Hill Development
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
|
@ -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];
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// This code is necessary to avoid an incompatibility with the definition
|
||||
// .o_field_widget input, .o_field_widget textarea {color: inherit} added by
|
||||
// web_responsive. This causes the text to appear white when editing the name of
|
||||
// the selected file/directory on field mode (Example: field added on hr.employee by
|
||||
// hr_dms_field), making it impossible to see the content. It is necessary to maintain
|
||||
// it in version 16.0, and if migrating to higher versions, check if it remains
|
||||
// necessary.
|
||||
.jstree-proton .jstree-clicked {
|
||||
color: #000000 !important;
|
||||
i {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.jstree-proton a.jstree-clicked {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,538 @@
|
|||
/** @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),
|
||||
icon_url: file.icon_url,
|
||||
});
|
||||
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",
|
||||
"icon_url",
|
||||
"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.sanitizeDMSModel(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};
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="dms_field.View" owl="1">
|
||||
<Layout display="props.display" className="'h-100 overflow-auto'">
|
||||
<t t-component="props.Renderer" rendererActions="rendererActions" />
|
||||
</Layout>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,532 @@
|
|||
/** @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.dialog = useService("dialog");
|
||||
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 = $("<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,
|
||||
};
|
||||
this.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,
|
||||
};
|
||||
this.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) {
|
||||
this.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";
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
.dms_document_controls {
|
||||
padding: 5px 0 10px 0;
|
||||
}
|
||||
|
||||
.dms_document_preview {
|
||||
height: 100% !important;
|
||||
.o_preview_directory_body {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-right: -16px;
|
||||
margin-left: -16px;
|
||||
.o_preview_directory_icon {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
.o_preview_directory_table_body {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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 {
|
||||
height: 100%;
|
||||
.dms_document_col {
|
||||
padding: 0;
|
||||
width: 50%;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
width: 100%;
|
||||
.dms_document_col {
|
||||
width: 100%;
|
||||
}
|
||||
.dms_document_col_preview {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 769px) {
|
||||
.dms_document_col_tree > div {
|
||||
border-right-width: 3px;
|
||||
border-right-style: solid;
|
||||
border-right-color: #888;
|
||||
}
|
||||
}
|
||||
.dms_document_row {
|
||||
height: 100% !important;
|
||||
.dms_document_col_tree > div {
|
||||
height: 100%;
|
||||
.dms_document_tree {
|
||||
height: 100%;
|
||||
.dms_content,
|
||||
.dms_tree {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vakata-context {
|
||||
z-index: 9999;
|
||||
|
||||
.vakata-context-parent + ul {
|
||||
list-style: none;
|
||||
left: 100%;
|
||||
margin-top: -2.58em;
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="dms_list.Renderer" owl="1">
|
||||
<div class="dms_treeview">
|
||||
<div class="container-fluid dms_document_container ">
|
||||
<div class="row o_dms_header btn-group">
|
||||
<button
|
||||
class="btn btn-secondary o_dms_add_directory fa fa-database o_hidden"
|
||||
t-ref="dms_add_directory"
|
||||
t-on-click="onDMSAddDirectoryRecord"
|
||||
/>
|
||||
<div class="o_dms_extra_actions btn-group" t-ref="extra_actions" />
|
||||
</div>
|
||||
<div
|
||||
t-attf-class="row dms_document_row #{env.isSmall ? 'dms_document_mobile' : 'dms_document_desktop'}"
|
||||
>
|
||||
<div class="dms_document_col dms_document_col_tree">
|
||||
<div class="dms_document_tree">
|
||||
<div class="dms_content">
|
||||
<div class="dms_tree" t-ref="jstree" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="dms_document_col dms_document_col_preview"
|
||||
t-ref="dropZone"
|
||||
>
|
||||
<div t-if="showDragZone" class="o_dropzone">
|
||||
<i class="fa fa-cloud-upload fa-10x" />
|
||||
</div>
|
||||
<div class="dms_document_preview">
|
||||
<t t-call="dms_list.DocumentTreeViewDirectoryPreview" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="dms_list.DocumentTreeViewDirectoryPreview" owl="1">
|
||||
<div
|
||||
class="o_preview_directory"
|
||||
t-if="Object.entries(nodeSelectedState.data).length !== 0"
|
||||
t-att-data-directory-id="nodeSelectedState.data.resModel === 'dms.directory' ? nodeSelectedState.data.res_id : ''"
|
||||
>
|
||||
<div class="top_info row">
|
||||
<div class="left_info col-4">
|
||||
<div class="o_preview_directory_icon" align="center">
|
||||
<div>
|
||||
<img
|
||||
t-if="nodeSelectedState.data.resModel === 'dms.directory'"
|
||||
class="h-100 w-100"
|
||||
t-att-src="nodeSelectedState.data.data.icon_url"
|
||||
/>
|
||||
<a
|
||||
t-if="nodeSelectedState.data.resModel === 'dms.file'"
|
||||
class="o_preview_file"
|
||||
t-att-data-id="nodeSelectedState.data.id"
|
||||
>
|
||||
<img
|
||||
class="h-100 w-100"
|
||||
t-att-src="nodeSelectedState.data.data.icon_url"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right_info col-8">
|
||||
<h3>
|
||||
<t t-esc="nodeSelectedState.data.data.name" />
|
||||
</h3>
|
||||
<t t-if="nodeSelectedState.data.resModel === 'dms.directory'">
|
||||
<p><b>Subdirectories:</b> <span
|
||||
t-esc="nodeSelectedState.data.data.count_total_directories"
|
||||
/></p>
|
||||
<p><b>Files:</b> <span
|
||||
t-esc="nodeSelectedState.data.data.count_total_files"
|
||||
/></p>
|
||||
<p><b>Size:</b> <span
|
||||
t-if="nodeSelectedState.data.data.human_size"
|
||||
t-esc="nodeSelectedState.data.data.human_size"
|
||||
/></p>
|
||||
<p><b>Elements:</b> <span
|
||||
t-esc="nodeSelectedState.data.data.count_elements"
|
||||
/></p>
|
||||
</t>
|
||||
<t t-if="nodeSelectedState.data.resModel === 'dms.file'">
|
||||
<p><b>Size:</b> <span
|
||||
t-esc="nodeSelectedState.data.data.human_size"
|
||||
/></p>
|
||||
</t>
|
||||
<div class="bottom_buttons">
|
||||
<a
|
||||
t-if="nodeSelectedState.data.resModel === 'dms.file'"
|
||||
class="btn btn-primary"
|
||||
t-attf-href="/web/content?id=#{nodeSelectedState.data.data.id}&field=content&model=dms.file&filename_field=name&download=true"
|
||||
>
|
||||
<i class="fa fa-download" />
|
||||
Download
|
||||
</a>
|
||||
<button
|
||||
class="btn btn-primary o_preview_file"
|
||||
t-if="nodeSelectedState.data.resModel === 'dms.file'"
|
||||
t-on-click="() => this.onDMSPreviewFile(nodeSelectedState)"
|
||||
>
|
||||
Open
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -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);
|
||||
|
|
@ -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};
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t
|
||||
t-name="dms_field.X2ManyField"
|
||||
t-inherit="web.X2ManyField"
|
||||
t-inherit-mode="extension"
|
||||
owl="1"
|
||||
>
|
||||
<xpath expr="//ListRenderer" position="after">
|
||||
<DmsListRenderer t-elif="viewMode == 'dms_list'" t-props="rendererProps" />
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1 @@
|
|||
from . import test_dms_field
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
# Copyright 2020 Creu Blanca
|
||||
# Copyright 2024 Tecnativa - Víctor Martínez
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
from odoo import fields
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.tests import new_test_user
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
from odoo.addons.base.tests.common import BaseCommon
|
||||
|
||||
|
||||
class TestDmsField(BaseCommon):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.env = cls.env(context=dict(cls.env.context, test_dms_field=True))
|
||||
cls.user_a = new_test_user(cls.env, login="test-user-a")
|
||||
cls.group = cls.env["res.groups"].create(
|
||||
{"name": "Test group", "users": [(4, cls.user_a.id)]}
|
||||
)
|
||||
cls.user_b = new_test_user(cls.env, login="test-user-b")
|
||||
cls.template = cls.env.ref("dms_field.field_template_partner")
|
||||
cls.template.group_ids.group_ids = [(4, cls.group.id)]
|
||||
cls.template.group_ids.explicit_user_ids = [(4, cls.user_b.id)]
|
||||
cls.storage = cls.template.storage_id
|
||||
cls.directory = cls.template.dms_directory_ids
|
||||
cls.subdirectory_1 = cls.env["dms.directory"].create(
|
||||
{
|
||||
"name": "Test subdirectory 1",
|
||||
"parent_id": cls.directory.id,
|
||||
"storage_id": cls.storage.id,
|
||||
}
|
||||
)
|
||||
cls.subdirectory_2 = cls.env["dms.directory"].create(
|
||||
{
|
||||
"name": "Test subdirectory 2",
|
||||
"parent_id": cls.directory.id,
|
||||
"storage_id": cls.storage.id,
|
||||
}
|
||||
)
|
||||
cls.partner = (
|
||||
cls.env["res.partner"]
|
||||
.with_context(skip_track_dms_field_template=True)
|
||||
.create({"name": "DEMO Partner"})
|
||||
)
|
||||
|
||||
def _create_directory_vals(self, record):
|
||||
return {
|
||||
"storage_id": self.storage.id,
|
||||
"is_root_directory": True,
|
||||
"name": record.display_name,
|
||||
"res_model": record._name,
|
||||
"res_id": record.id,
|
||||
}
|
||||
|
||||
def test_check_constrain_multi_directory(self):
|
||||
self.env["dms.directory"].create(self._create_directory_vals(self.partner))
|
||||
with self.assertRaises(ValidationError):
|
||||
self.env["dms.directory"].create(self._create_directory_vals(self.partner))
|
||||
|
||||
def test_check_constrain_not_root(self):
|
||||
directory = self.env["dms.directory"].create(
|
||||
self._create_directory_vals(self.partner)
|
||||
)
|
||||
with self.assertRaises(ValidationError):
|
||||
self.env["dms.directory"].create(
|
||||
{
|
||||
"parent_id": directory.id,
|
||||
"name": "Second Directory",
|
||||
"res_model": self.partner._name,
|
||||
"res_id": self.partner.id,
|
||||
}
|
||||
)
|
||||
|
||||
def test_js_tree(self):
|
||||
self.assertTrue(
|
||||
any(
|
||||
r["id"] == "storage_%s" % self.storage.id
|
||||
for r in self.storage.get_js_tree_data()
|
||||
)
|
||||
)
|
||||
|
||||
def test_dms_access_group_constrains_dms_field_ref(self):
|
||||
group = self.env["dms.access.group"].create(
|
||||
{
|
||||
"name": "Test 1",
|
||||
"dms_field_ref": "%s,%s" % (self.partner._name, self.partner.id),
|
||||
}
|
||||
)
|
||||
with self.assertRaises(UserError):
|
||||
group.copy({"name": "Test 2"})
|
||||
|
||||
def test_dms_access_group_company_dms_field_ref_01(self):
|
||||
self.partner.company_id = False
|
||||
group = self.env["dms.access.group"].create(
|
||||
{
|
||||
"name": "Test 1",
|
||||
"dms_field_ref": "%s,%s" % (self.partner._name, self.partner.id),
|
||||
}
|
||||
)
|
||||
self.assertFalse(group.company_id)
|
||||
|
||||
def test_dms_access_group_company_dms_field_ref_02(self):
|
||||
self.company = self.env.company
|
||||
self.partner.company_id = self.company
|
||||
group = self.env["dms.access.group"].create(
|
||||
{
|
||||
"name": "Test 1",
|
||||
"dms_field_ref": "%s,%s" % (self.partner._name, self.partner.id),
|
||||
}
|
||||
)
|
||||
self.assertEqual(group.company_id, self.company)
|
||||
|
||||
def test_template_directory(self):
|
||||
self.assertTrue(self.template.dms_directory_ids)
|
||||
self.assertIn(
|
||||
self.template.group_ids, self.template.dms_directory_ids.group_ids
|
||||
)
|
||||
|
||||
@mute_logger("odoo.models.unlink")
|
||||
def test_creation_process_01(self):
|
||||
self.assertFalse(self.partner.dms_directory_ids)
|
||||
template = self.env["dms.field.template"].with_context(
|
||||
res_model=self.partner._name, res_id=self.partner.id
|
||||
)
|
||||
template.create_dms_directory()
|
||||
self.partner.invalidate_model()
|
||||
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]
|
||||
self.assertFalse(directory_0.parent_id)
|
||||
self.assertTrue(directory_0.is_root_directory)
|
||||
self.assertTrue(directory_0.inherit_group_ids)
|
||||
self.assertIn(self.template.group_ids, directory_0.group_ids)
|
||||
self.assertIn(self.group, directory_0.group_ids.group_ids)
|
||||
self.assertIn(self.partner, directory_0.mapped("group_ids.dms_field_ref"))
|
||||
group_custom = directory_0.group_ids.filtered("dms_field_ref")
|
||||
self.assertTrue(group_custom.perm_create)
|
||||
self.assertTrue(group_custom.perm_write)
|
||||
self.assertTrue(group_custom.perm_unlink)
|
||||
self.assertIn(self.user_b, directory_0.group_ids.explicit_user_ids)
|
||||
self.assertIn(self.user_a, directory_0.group_ids.users)
|
||||
self.assertIn(self.user_b, directory_0.group_ids.users)
|
||||
self.assertIn(self.subdirectory_1.name, child_names)
|
||||
self.assertIn(self.subdirectory_2.name, child_names)
|
||||
with self.assertRaises(ValidationError):
|
||||
template.create_dms_directory()
|
||||
# Remove folder: El grupo de acceso todavía existe
|
||||
old_groups = directory_0.group_ids
|
||||
directory_0.unlink()
|
||||
dms_field_ref_value = "%s,%s" % (self.partner._name, self.partner.id)
|
||||
total = self.env["dms.access.group"].search_count(
|
||||
[("dms_field_ref", "=", dms_field_ref_value)]
|
||||
)
|
||||
self.assertEqual(total, 1)
|
||||
# Create directory again (access groups are the same)
|
||||
template.create_dms_directory()
|
||||
self.partner.invalidate_model()
|
||||
directory_0 = self.partner.dms_directory_ids[0]
|
||||
self.assertEqual(directory_0.group_ids, old_groups)
|
||||
|
||||
def test_creation_process_01_with_parent(self):
|
||||
self.assertFalse(self.partner.dms_directory_ids)
|
||||
self.template.parent_directory_id = fields.first(
|
||||
self.template.storage_id.root_directory_ids
|
||||
)
|
||||
template = self.env["dms.field.template"].with_context(
|
||||
res_model=self.partner._name, res_id=self.partner.id
|
||||
)
|
||||
template.create_dms_directory()
|
||||
self.partner.invalidate_model()
|
||||
self.assertEqual(self.partner.dms_directory_ids.name, self.partner.display_name)
|
||||
directory_0 = self.partner.dms_directory_ids[0]
|
||||
self.assertEqual(directory_0.parent_id, self.template.parent_directory_id)
|
||||
self.assertFalse(directory_0.is_root_directory)
|
||||
self.assertFalse(directory_0.inherit_group_ids)
|
||||
self.assertIn(self.template.group_ids, directory_0.group_ids)
|
||||
self.assertIn(self.group, directory_0.group_ids.group_ids)
|
||||
self.assertIn(self.user_b, directory_0.group_ids.explicit_user_ids)
|
||||
self.assertIn(self.user_a, directory_0.group_ids.users)
|
||||
self.assertIn(self.user_b, directory_0.group_ids.users)
|
||||
|
||||
def test_creation_process_02(self):
|
||||
partner_1 = self.env["res.partner"].create({"name": "Test partner 1"})
|
||||
partner_1.invalidate_model()
|
||||
directory_1 = partner_1.dms_directory_ids[0]
|
||||
self.assertFalse(directory_1.parent_id)
|
||||
self.assertTrue(directory_1.is_root_directory)
|
||||
self.assertTrue(directory_1.inherit_group_ids)
|
||||
partner_2 = (
|
||||
self.env["res.partner"]
|
||||
.with_context(skip_track_dms_field_template=True)
|
||||
.create({"name": "Test partner 2"})
|
||||
)
|
||||
partner_2.invalidate_model()
|
||||
self.assertFalse(partner_2.dms_directory_ids)
|
||||
|
||||
def test_creation_process_02_with_parent(self):
|
||||
self.template.parent_directory_id = fields.first(
|
||||
self.template.storage_id.root_directory_ids
|
||||
)
|
||||
partner_1 = self.env["res.partner"].create({"name": "Test partner 1"})
|
||||
partner_1.invalidate_model()
|
||||
directory_1 = partner_1.dms_directory_ids[0]
|
||||
self.assertEqual(directory_1.parent_id, self.template.parent_directory_id)
|
||||
self.assertFalse(directory_1.is_root_directory)
|
||||
self.assertFalse(directory_1.inherit_group_ids)
|
||||
partner_2 = (
|
||||
self.env["res.partner"]
|
||||
.with_context(skip_track_dms_field_template=True)
|
||||
.create({"name": "Test partner 2"})
|
||||
)
|
||||
partner_2.invalidate_model()
|
||||
self.assertFalse(partner_2.dms_directory_ids)
|
||||
|
||||
def test_creation_process_03(self):
|
||||
self.template.directory_format_name = "{{object.name}}-{{object.ref}}"
|
||||
partner_1 = self.env["res.partner"].create(
|
||||
{"name": "TEST-PARTNER1", "ref": "CUSTOM-REF"}
|
||||
)
|
||||
partner_1.invalidate_model()
|
||||
self.assertEqual(
|
||||
partner_1.dms_directory_ids.name, "%s-%s" % (partner_1.name, partner_1.ref)
|
||||
)
|
||||
|
||||
def test_parents(self):
|
||||
directory = self.env["dms.directory"].create(
|
||||
self._create_directory_vals(self.partner)
|
||||
)
|
||||
self.assertEqual(
|
||||
directory.search_read_parents([("id", "=", directory.id)], fields=["id"])[
|
||||
0
|
||||
],
|
||||
{"id": directory.id},
|
||||
)
|
||||
self.assertEqual(
|
||||
directory.search_read_parents(
|
||||
[("id", "=", directory.id)], fields=["id", "name"]
|
||||
)[0],
|
||||
{"id": directory.id, "name": directory.name},
|
||||
)
|
||||
self.assertIn(
|
||||
{"id": directory.id, "name": directory.name},
|
||||
directory.search_read_parents(fields=["id", "name"]),
|
||||
)
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="view_dms_access_groups_tree" model="ir.ui.view">
|
||||
<field name="name">dms_access_groups.tree</field>
|
||||
<field name="model">dms.access.group</field>
|
||||
<field name="inherit_id" ref="dms.view_dms_access_groups_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="count_directories" position="after">
|
||||
<field name="dms_field_ref" optional="hide" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_dms_access_groups_form" model="ir.ui.view">
|
||||
<field name="name">dms_access.group.form</field>
|
||||
<field name="model">dms.access.group</field>
|
||||
<field name="inherit_id" ref="dms.view_dms_access_groups_form" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="perm_create" position="after">
|
||||
<field name="dms_field_ref" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- Copyright 2020 Creu Blanca
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
|
||||
<odoo>
|
||||
<record model="ir.ui.view" id="dms_directory_dms_tree_view">
|
||||
<field name="name">dms.directory.dms_tree (in dms_field)</field>
|
||||
<field name="model">dms.directory</field>
|
||||
<field name="type">dms_list</field>
|
||||
<field name="arch" type="xml">
|
||||
<dms_list>
|
||||
<field name="name" />
|
||||
</dms_list>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- Copyright 2024 Tecnativa - Víctor Martínez
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
||||
<odoo>
|
||||
<record id="view_dms_field_template_tree" model="ir.ui.view">
|
||||
<field name="model">dms.field.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="name" />
|
||||
<field name="storage_id" />
|
||||
<field name="model_id" />
|
||||
<field name="company_id" groups="base.group_multi_company" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_dms_field_template_form" model="ir.ui.view">
|
||||
<field name="model">dms.field.template</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1><field name="name" /></h1>
|
||||
</div>
|
||||
<group name="main_group">
|
||||
<field name="company_id" groups="base.group_multi_company" />
|
||||
<field name="dms_directory_ids" invisible="1" />
|
||||
<field name="storage_id" required="1" />
|
||||
<field
|
||||
name="parent_directory_id"
|
||||
attrs="{'invisible':[('storage_id', '=', False)]}"
|
||||
/>
|
||||
<field name="model_id" required="1" />
|
||||
<field
|
||||
name="user_field_id"
|
||||
attrs="{'invisible':[('model_id', '=', False)]}"
|
||||
/>
|
||||
<field
|
||||
name="directory_format_name"
|
||||
attrs="{'invisible':[('model_id', '=', False)]}"
|
||||
required="1"
|
||||
/>
|
||||
<field name="group_ids" widget="many2many_tags" />
|
||||
</group>
|
||||
<notebook position="inside">
|
||||
<page
|
||||
name="dms"
|
||||
string="Documents"
|
||||
attrs="{'invisible':['|', ('storage_id', '=', False), ('model_id', '=', False)]}"
|
||||
>
|
||||
<field
|
||||
name="dms_directory_ids"
|
||||
mode="dms_list"
|
||||
attrs="{'invisible': [('id', '=', False)]}"
|
||||
/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_dms_field_template" model="ir.actions.act_window">
|
||||
<field name="name">Embedded DMS templates</field>
|
||||
<field name="res_model">dms.field.template</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<menuitem
|
||||
id="menu_dms_field_template"
|
||||
name="Embedded DMS templates"
|
||||
parent="dms.cat_menu_dms_config_organizing"
|
||||
sequence="6"
|
||||
action="action_dms_field_template"
|
||||
/>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- Copyright 2020 Creu Blanca
|
||||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
|
||||
<odoo>
|
||||
<record model="ir.ui.view" id="dms_storage_dms_tree_view">
|
||||
<field name="name">dms.storage.dms_tree (in dms_field)</field>
|
||||
<field name="model">dms.storage</field>
|
||||
<field name="type">dms_list</field>
|
||||
<field name="arch" type="xml">
|
||||
<dms_list>
|
||||
<field name="name" />
|
||||
</dms_list>
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window" id="dms_storage_act_window">
|
||||
<field name="name">Documents</field>
|
||||
<field name="res_model">dms.storage</field>
|
||||
<field name="view_mode">dms_list</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="context">{}</field>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="dms_storage_menu">
|
||||
<field name="name">Documents</field>
|
||||
<field name="parent_id" ref="dms.main_menu_dms" />
|
||||
<field name="action" ref="dms_storage_act_window" />
|
||||
<field name="sequence" eval="99" />
|
||||
</record>
|
||||
</odoo>
|
||||
32
odoo-bringout-oca-dms-dms_field/doc/ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
U[Users] -->|HTTP| V[Views and QWeb Templates]
|
||||
V --> C[Controllers]
|
||||
V --> W[Wizards – Transient Models]
|
||||
C --> M[Models and ORM]
|
||||
W --> M
|
||||
M --> R[Reports]
|
||||
DX[Data XML] --> M
|
||||
S[Security – ACLs and Groups] -. enforces .-> M
|
||||
|
||||
subgraph Dms_field Module - dms_field
|
||||
direction LR
|
||||
M:::layer
|
||||
W:::layer
|
||||
C:::layer
|
||||
V:::layer
|
||||
R:::layer
|
||||
S:::layer
|
||||
DX:::layer
|
||||
end
|
||||
|
||||
classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px
|
||||
```
|
||||
|
||||
Notes
|
||||
- Views include tree/form/kanban templates and report templates.
|
||||
- Controllers provide website/portal routes when present.
|
||||
- Wizards are UI flows implemented with `models.TransientModel`.
|
||||
- Data XML loads data/demo records; Security defines groups and access.
|
||||
3
odoo-bringout-oca-dms-dms_field/doc/CONFIGURATION.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Configuration
|
||||
|
||||
Refer to Odoo settings for dms_field. Configure related models, access rights, and options as needed.
|
||||
3
odoo-bringout-oca-dms-dms_field/doc/CONTROLLERS.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Controllers
|
||||
|
||||
This module does not define custom HTTP controllers.
|
||||
5
odoo-bringout-oca-dms-dms_field/doc/DEPENDENCIES.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Dependencies
|
||||
|
||||
This addon depends on:
|
||||
|
||||
- [dms](../../odoo-bringout-oca-dms-dms)
|
||||
4
odoo-bringout-oca-dms-dms_field/doc/FAQ.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# FAQ
|
||||
|
||||
- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged).
|
||||
- Q: How to enable? A: Start server with --addon dms_field or install in UI.
|
||||
7
odoo-bringout-oca-dms-dms_field/doc/INSTALL.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Install
|
||||
|
||||
```bash
|
||||
pip install odoo-bringout-oca-dms-dms_field"
|
||||
# or
|
||||
uv pip install odoo-bringout-oca-dms-dms_field"
|
||||
```
|
||||
20
odoo-bringout-oca-dms-dms_field/doc/MODELS.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Models
|
||||
|
||||
Detected core models and extensions in dms_field.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class dms_field_mixin
|
||||
class dms_field_template
|
||||
class res_partner
|
||||
class dms_access_group
|
||||
class dms_directory
|
||||
class dms_field_mixin
|
||||
class dms_storage
|
||||
class ir_actions_act_window_view
|
||||
class ir_ui_view
|
||||
```
|
||||
|
||||
Notes
|
||||
- Classes show model technical names; fields omitted for brevity.
|
||||
- Items listed under _inherit are extensions of existing models.
|
||||
6
odoo-bringout-oca-dms-dms_field/doc/OVERVIEW.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Overview
|
||||
|
||||
Packaged Odoo addon: dms_field. Provides features documented in upstream Odoo 16 under this addon.
|
||||
|
||||
- Source: OCA/OCB 16.0, addon dms_field
|
||||
- License: LGPL-3
|
||||
3
odoo-bringout-oca-dms-dms_field/doc/REPORTS.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Reports
|
||||
|
||||
This module does not define custom reports.
|
||||
41
odoo-bringout-oca-dms-dms_field/doc/SECURITY.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Security
|
||||
|
||||
Access control and security definitions in dms_field.
|
||||
|
||||
## Access Control Lists (ACLs)
|
||||
|
||||
Model access permissions defined in:
|
||||
- **[ir.model.access.csv](../dms_field/security/ir.model.access.csv)**
|
||||
- 2 model access rules
|
||||
|
||||
## Record Rules
|
||||
|
||||
Row-level security rules defined in:
|
||||
|
||||
## Security Groups & Configuration
|
||||
|
||||
Security groups and permissions defined in:
|
||||
- **[security.xml](../dms_field/security/security.xml)**
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Security Layers"
|
||||
A[Users] --> B[Groups]
|
||||
B --> C[Access Control Lists]
|
||||
C --> D[Models]
|
||||
B --> E[Record Rules]
|
||||
E --> F[Individual Records]
|
||||
end
|
||||
```
|
||||
|
||||
Security files overview:
|
||||
- **[ir.model.access.csv](../dms_field/security/ir.model.access.csv)**
|
||||
- Model access permissions (CRUD rights)
|
||||
- **[security.xml](../dms_field/security/security.xml)**
|
||||
- Security groups, categories, and XML-based rules
|
||||
|
||||
Notes
|
||||
- Access Control Lists define which groups can access which models
|
||||
- Record Rules provide row-level security (filter records by user/group)
|
||||
- Security groups organize users and define permission sets
|
||||
- All security is enforced at the ORM level by Odoo
|
||||
5
odoo-bringout-oca-dms-dms_field/doc/TROUBLESHOOTING.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Troubleshooting
|
||||
|
||||
- Ensure Python and Odoo environment matches repo guidance.
|
||||
- Check database connectivity and logs if startup fails.
|
||||
- Validate that dependent addons listed in DEPENDENCIES.md are installed.
|
||||
7
odoo-bringout-oca-dms-dms_field/doc/USAGE.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Usage
|
||||
|
||||
Start Odoo including this addon (from repo root):
|
||||
|
||||
```bash
|
||||
python3 scripts/nix_odoo_web_server.py --db-name mydb --addon dms_field
|
||||
```
|
||||
3
odoo-bringout-oca-dms-dms_field/doc/WIZARDS.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Wizards
|
||||
|
||||
This module does not include UI wizards.
|
||||
43
odoo-bringout-oca-dms-dms_field/pyproject.toml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
[project]
|
||||
name = "odoo-bringout-oca-dms-dms_field"
|
||||
version = "16.0.0"
|
||||
description = "DMS Field -
|
||||
Create DMS View and allow to use them inside a record"
|
||||
authors = [
|
||||
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
|
||||
]
|
||||
dependencies = [
|
||||
"odoo-bringout-oca-dms-dms>=16.0.0",
|
||||
"requests>=2.25.1"
|
||||
]
|
||||
readme = "README.md"
|
||||
requires-python = ">= 3.11"
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Topic :: Office/Business",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
homepage = "https://github.com/bringout/0"
|
||||
repository = "https://github.com/bringout/0"
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.hatch.metadata]
|
||||
allow-direct-references = true
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["dms_field"]
|
||||
|
||||
[tool.rye]
|
||||
managed = true
|
||||
dev-dependencies = [
|
||||
"pytest>=8.4.1",
|
||||
]
|
||||