mirror of
https://github.com/bringout/oca-storage.git
synced 2026-04-18 06:12:08 +02:00
Initial commit: OCA Storage packages (17 packages)
This commit is contained in:
commit
7a380f05d3
659 changed files with 41828 additions and 0 deletions
47
odoo-bringout-oca-storage-fs_image_thumbnail/README.md
Normal file
47
odoo-bringout-oca-storage-fs_image_thumbnail/README.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# Fs Image Thumbnail
|
||||
|
||||
Odoo addon: fs_image_thumbnail
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install odoo-bringout-oca-storage-fs_image_thumbnail
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
This addon depends on:
|
||||
- fs_image
|
||||
- base_partition
|
||||
|
||||
## Manifest Information
|
||||
|
||||
- **Name**: Fs Image Thumbnail
|
||||
- **Version**: 16.0.1.0.2
|
||||
- **Category**: N/A
|
||||
- **License**: AGPL-3
|
||||
- **Installable**: False
|
||||
|
||||
## Source
|
||||
|
||||
Based on [OCA/storage](https://github.com/OCA/storage) branch 16.0, addon `fs_image_thumbnail`.
|
||||
|
||||
## License
|
||||
|
||||
This package maintains the original AGPL-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
|
||||
- Reports: doc/REPORTS.md
|
||||
- Security: doc/SECURITY.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
|
||||
|
|
@ -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 Fs_image_thumbnail Module - fs_image_thumbnail
|
||||
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.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Configuration
|
||||
|
||||
Refer to Odoo settings for fs_image_thumbnail. Configure related models, access rights, and options as needed.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Controllers
|
||||
|
||||
This module does not define custom HTTP controllers.
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# Dependencies
|
||||
|
||||
This addon depends on:
|
||||
|
||||
- [fs_image](../../odoo-bringout-oca-storage-fs_image)
|
||||
- [base_partition](../../odoo-bringout-oca-server-tools-base_partition)
|
||||
4
odoo-bringout-oca-storage-fs_image_thumbnail/doc/FAQ.md
Normal file
4
odoo-bringout-oca-storage-fs_image_thumbnail/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 fs_image_thumbnail or install in UI.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# Install
|
||||
|
||||
```bash
|
||||
pip install odoo-bringout-oca-storage-fs_image_thumbnail"
|
||||
# or
|
||||
uv pip install odoo-bringout-oca-storage-fs_image_thumbnail"
|
||||
```
|
||||
15
odoo-bringout-oca-storage-fs_image_thumbnail/doc/MODELS.md
Normal file
15
odoo-bringout-oca-storage-fs_image_thumbnail/doc/MODELS.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Models
|
||||
|
||||
Detected core models and extensions in fs_image_thumbnail.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class fs_image_thumbnail_mixin
|
||||
class fs_thumbnail
|
||||
class fs_image_thumbnail_mixin
|
||||
class ir_attachment
|
||||
```
|
||||
|
||||
Notes
|
||||
- Classes show model technical names; fields omitted for brevity.
|
||||
- Items listed under _inherit are extensions of existing models.
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# Overview
|
||||
|
||||
Packaged Odoo addon: fs_image_thumbnail. Provides features documented in upstream Odoo 16 under this addon.
|
||||
|
||||
- Source: OCA/OCB 16.0, addon fs_image_thumbnail
|
||||
- License: LGPL-3
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Reports
|
||||
|
||||
This module does not define custom reports.
|
||||
73
odoo-bringout-oca-storage-fs_image_thumbnail/doc/SECURITY.md
Normal file
73
odoo-bringout-oca-storage-fs_image_thumbnail/doc/SECURITY.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# Security
|
||||
|
||||
Access control and security definitions in fs_image_thumbnail.
|
||||
|
||||
## Access Control Lists (ACLs)
|
||||
|
||||
Model access permissions defined in:
|
||||
- **[all_odoo_addons_repos.txt](../all_odoo_addons_repos.txt)**
|
||||
- 318 model access rules
|
||||
- **[bosnian_translations.json](../bosnian_translations.json)**
|
||||
- 50 model access rules
|
||||
- **[bosnian_translations_output.json](../bosnian_translations_output.json)**
|
||||
- 444 model access rules
|
||||
- **[CHANGELOG.md](../CHANGELOG.md)**
|
||||
- 132 model access rules
|
||||
- **[delete_all_odoo_addons.sh](../delete_all_odoo_addons.sh)**
|
||||
- 50 model access rules
|
||||
- **[delete_odoo_addons.sh](../delete_odoo_addons.sh)**
|
||||
- 44 model access rules
|
||||
- **[doc](../doc)**
|
||||
- **[docker](../docker)**
|
||||
- **[input](../input)**
|
||||
- **[nix](../nix)**
|
||||
- **[odoo.conf](../odoo.conf)**
|
||||
- 58 model access rules
|
||||
- **[odoo_packages_bez_l10n.txt](../odoo_packages_bez_l10n.txt)**
|
||||
- 1947 model access rules
|
||||
- **[odoo_packages_bringout.txt](../odoo_packages_bringout.txt)**
|
||||
- 1947 model access rules
|
||||
- **[odoo_packages.txt](../odoo_packages.txt)**
|
||||
- 2085 model access rules
|
||||
- **[output](../output)**
|
||||
- **[packages](../packages)**
|
||||
- **[PACKAGES.md](../PACKAGES.md)**
|
||||
- 298 model access rules
|
||||
- **[README.md](../README.md)**
|
||||
- 338 model access rules
|
||||
- **[scripts](../scripts)**
|
||||
- **[temp](../temp)**
|
||||
- **[TRANSLATION_BS_SUMMARY.md](../TRANSLATION_BS_SUMMARY.md)**
|
||||
- 146 model access rules
|
||||
- **[verify_deletions.sh](../verify_deletions.sh)**
|
||||
- 55 model access rules
|
||||
|
||||
## Record Rules
|
||||
|
||||
Row-level security rules defined in:
|
||||
|
||||
## Security Groups & Configuration
|
||||
|
||||
Security groups and permissions defined in:
|
||||
- **[fs_thumbnail.xml](../fs_image_thumbnail/security/fs_thumbnail.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:
|
||||
- **[fs_thumbnail.xml](../fs_image_thumbnail/security/fs_thumbnail.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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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 fs_image_thumbnail
|
||||
```
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Wizards
|
||||
|
||||
This module does not include UI wizards.
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
==================
|
||||
Fs Image Thumbnail
|
||||
==================
|
||||
|
||||
..
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:ae84af058fd490c7c8916156dc7db31813b6d5f7535e722740b152d6955e0d57
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Alpha
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github
|
||||
:target: https://github.com/OCA/storage/tree/16.0/fs_image_thumbnail
|
||||
:alt: OCA/storage
|
||||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
||||
:target: https://translation.odoo-community.org/projects/storage-16-0/storage-16-0-fs_image_thumbnail
|
||||
: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/storage&target_branch=16.0
|
||||
:alt: Try me on Runboat
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||
|
||||
This module extends the **fs_image** addon to support the creation and the storage of
|
||||
thumbnails for images. This module is a **technical module** and is not
|
||||
meant to be installed by end-users. It only provides a mixin to be used
|
||||
by other modules and a model to store the thumbnails.
|
||||
|
||||
.. IMPORTANT::
|
||||
This is an alpha version, the data model and design can change at any time without warning.
|
||||
Only for development or testing purpose, do not use in production.
|
||||
`More details on development status <https://odoo-community.org/page/development-status>`_
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Use Cases / Context
|
||||
===================
|
||||
|
||||
In some specific cases you may need to generate and store thumbnails of images in Odoo.
|
||||
This is the case for example when you want to provide image in specific sizes for a website
|
||||
or a mobile application.
|
||||
|
||||
This module provides a generic way to generate thumbnails of images and store them in a
|
||||
specific filesystem storage. Indeed, you could need to store the thumbnails in a different
|
||||
storage than the original image (eg: store the thumbnails in a CDN) to make sure the
|
||||
thumbnails are served quickly when requested by an external application and to
|
||||
avoid to expose the original image storage.
|
||||
|
||||
This module uses the `fs_image <https://github.com/oca/storage/blob/16.0/fs_image/README.rst>`_
|
||||
module to store the thumbnails in a filesystem storage.
|
||||
|
||||
The `shopinvader_product_image <https://github.com/shopinvader/odoo-shopinvader/
|
||||
blob/16.0/shopinvader_product_image>`_ addon uses this module to generate and
|
||||
store the thumbnails of the images of the products and categories to be accessible
|
||||
by the website.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
This addon provides a convenient way to get and create if not exists image
|
||||
thumbnails. All the logic is implemented by the abstract model
|
||||
`fs.image.thumbnail.mixin`. The main method is `get_or_create_thumbnails` which
|
||||
accepts a *FSImageValue* instance, a list of thumbnail sizes and a base name.
|
||||
|
||||
When the method is called, it will check if the thumbnail exists for the given
|
||||
sizes and base name. If not, it will create it.
|
||||
|
||||
The `fs.thumbnail` model provided by this addon is a concrete implementation of
|
||||
the abstract model `fs.image.thumbnail.mixin`. The motivation to implement all the
|
||||
logic in an abstract model is to allow developers to create their own thumbnail
|
||||
models. This could be useful if you want to store the thumbnails in a different
|
||||
storage since you can specify the storage to use by model on the `fs.storage`
|
||||
form view.
|
||||
|
||||
Creating / retrieving thumbnails is as simple as:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from odoo.addons.fs_image.fields import FSImageValue
|
||||
|
||||
# create an attachment with a image file
|
||||
attachment = self.env['ir.attachment'].create({
|
||||
'name': 'test',
|
||||
'datas': base64.b64encode(open('test.png', 'rb').read()),
|
||||
'datas_fname': 'test.png',
|
||||
})
|
||||
|
||||
# create a FSImageValue instance for the attachment
|
||||
image_value = FSImageValue(attachment)
|
||||
|
||||
# get or create the thumbnails
|
||||
thumbnails = self.env['fs.thumbnail'].get_or_create_thumbnails(
|
||||
image_value, [(800,600), (400, 200)], 'my base name')
|
||||
|
||||
|
||||
|
||||
If you've a model with a *FSImage* field, the call to `get_or_create_thumbnails`
|
||||
is even simpler:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from odoo import models
|
||||
from odoo.addons.fs_image.fields import FSImage
|
||||
|
||||
class MyModel(models.Model):
|
||||
_name = 'my.model'
|
||||
|
||||
image = FSImage('Image')
|
||||
|
||||
my_record = cls.env['my.model'].create({
|
||||
'image': open('test.png', 'rb'),
|
||||
})
|
||||
|
||||
# get or create the thumbnails
|
||||
thumbnails = record.image.get_or_create_thumbnails(my_record.image,
|
||||
[(800,600), (400, 200)], 'my base name')
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
16.0.1.0.1 (2023-10-04)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- The call to the method *get_or_create_thumbnails* on the *fs.image.thumbnail.mixin*
|
||||
class returns now an ordered dictionary where the key is the original image and
|
||||
the value is a recordset of thumbnail images. The order of the dict is the order
|
||||
of the images passed to the method. This ensures that when you process the result
|
||||
of the method you can be sure that the order of the images is the same as the
|
||||
order of the images passed to the method. (`#282 <https://github.com/OCA/storage/issues/282>`_)
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/storage/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/storage/issues/new?body=module:%20fs_image_thumbnail%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
|
||||
~~~~~~~
|
||||
|
||||
* ACSONE SA/NV
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Laurent Mignon <laurent.mignon@acsone.eu> (https://acsone.eu)
|
||||
|
||||
Other credits
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The development of this module has been financially supported by:
|
||||
|
||||
* `Alcyon Belux <https://www.alcyonbelux.be/>`_
|
||||
|
||||
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.
|
||||
|
||||
.. |maintainer-lmignon| image:: https://github.com/lmignon.png?size=40px
|
||||
:target: https://github.com/lmignon
|
||||
:alt: lmignon
|
||||
|
||||
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|
||||
|
||||
|maintainer-lmignon|
|
||||
|
||||
This module is part of the `OCA/storage <https://github.com/OCA/storage/tree/16.0/fs_image_thumbnail>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
|
|
@ -0,0 +1 @@
|
|||
from . import models
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Copyright 2023 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "Fs Image Thumbnail",
|
||||
"summary": """
|
||||
Generate and store thumbnail for images""",
|
||||
"version": "16.0.1.0.2",
|
||||
"license": "AGPL-3",
|
||||
"author": "ACSONE SA/NV,Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/storage",
|
||||
"depends": ["fs_image", "base_partition"],
|
||||
"data": [
|
||||
"views/ir_attachment.xml",
|
||||
"security/fs_thumbnail.xml",
|
||||
"views/fs_image_thumbnail_mixin.xml",
|
||||
"views/fs_thumbnail.xml",
|
||||
],
|
||||
"demo": [],
|
||||
"maintainers": ["lmignon"],
|
||||
"development_status": "Alpha",
|
||||
"external_dependencies": {"python": ["python_slugify"]},
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * fs_image_thumbnail
|
||||
#
|
||||
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: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_ir_attachment
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__attachment_id
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__attachment_id
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Attachment"
|
||||
msgstr "Prilog"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_image_thumbnail_mixin__attachment_id
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_thumbnail__attachment_id
|
||||
msgid "Attachment containing the original image"
|
||||
msgstr "Prilog koji sadrži originalnu sliku"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Base Name"
|
||||
msgstr "Osnovno ime"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__create_uid
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_thumbnail_search_view
|
||||
msgid "Created by"
|
||||
msgstr "Kreirao"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Kreirano"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Prikazani naziv"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_fs_image_thumbnail_mixin
|
||||
msgid "Fs Image Thumbnail Mixin"
|
||||
msgstr "Fs Image Thumbnail Mixin"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.ui.menu,name:fs_image_thumbnail.fs_thumbnail_menu
|
||||
msgid "Fs Image Thumbnails"
|
||||
msgstr "Fs slike minijatura"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.actions.act_window,name:fs_image_thumbnail.fs_thumbnail_act_window
|
||||
msgid "Fs Thumbnail"
|
||||
msgstr "Fs minijatura"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Group By"
|
||||
msgstr "Grupiši po"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__id
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__image
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__image
|
||||
msgid "Image"
|
||||
msgstr "Slika"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_fs_thumbnail
|
||||
msgid "Image Thumbnail"
|
||||
msgstr "Minijatura slike"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Zadnje mijenjano"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Zadnji ažurirao"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Zadnje ažurirano"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "MimeType"
|
||||
msgstr "MimeType"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__mimetype
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__mimetype
|
||||
msgid "Mimetype"
|
||||
msgstr "Mimetype"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__name
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__name
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Name"
|
||||
msgstr "Naziv:"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__original_image
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__original_image
|
||||
msgid "Original Image"
|
||||
msgstr "Originalna slika"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#. odoo-python
|
||||
#: code:addons/fs_image_thumbnail/models/fs_image_thumbnail_mixin.py:0
|
||||
#, python-format
|
||||
msgid "The base name must be set when multiple images are given"
|
||||
msgstr "Osnovno ime mora biti postavljen kad je dano više slika"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__base_name
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__base_name
|
||||
msgid "The base name of the thumbnail image (without extension)"
|
||||
msgstr "Osnovno ime minijature slike (bez ekstenzije)"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#. odoo-python
|
||||
#: code:addons/fs_image_thumbnail/models/fs_image_thumbnail_mixin.py:0
|
||||
#, python-format
|
||||
msgid "The image %(name)s must be attached to an attachment"
|
||||
msgstr "Slika %(name)s mora biti priložena priloga"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_image_thumbnail_mixin__base_name
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_thumbnail__base_name
|
||||
msgid ""
|
||||
"The thumbnail image will be named as base_name + _ + size_x + _ + size_y + . + extension.\n"
|
||||
"If not set, the base name will be the name of the original image.This base name is used to find all existing thumbnail of an image generated for the same base name."
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_ir_attachment__thumbnail_ids
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.ir_attachment_form_view
|
||||
msgid "Thumbnails"
|
||||
msgstr "Sličice"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__size_x
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__size_x
|
||||
msgid "X size"
|
||||
msgstr "X veličina"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__size_y
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__size_y
|
||||
msgid "Y size"
|
||||
msgstr "Y veličina"
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * fs_image_thumbnail
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2023-10-29 00:15+0000\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: \n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.17\n"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_ir_attachment
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__attachment_id
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__attachment_id
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Attachment"
|
||||
msgstr "Archivo Adjunto"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_image_thumbnail_mixin__attachment_id
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_thumbnail__attachment_id
|
||||
msgid "Attachment containing the original image"
|
||||
msgstr "Archivo adjunto con la imagen original"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Base Name"
|
||||
msgstr "Nombre de la Base"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__create_uid
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_thumbnail_search_view
|
||||
msgid "Created by"
|
||||
msgstr "Creado por"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Creado el"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Mostrar Nombre"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_fs_image_thumbnail_mixin
|
||||
msgid "Fs Image Thumbnail Mixin"
|
||||
msgstr "Mezcla de Miniaturas de imágenes Fs"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.ui.menu,name:fs_image_thumbnail.fs_thumbnail_menu
|
||||
msgid "Fs Image Thumbnails"
|
||||
msgstr "Miniaturas de imágenes Fs"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.actions.act_window,name:fs_image_thumbnail.fs_thumbnail_act_window
|
||||
msgid "Fs Thumbnail"
|
||||
msgstr "Miniatura Fs"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Group By"
|
||||
msgstr "Agrupado Por"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__id
|
||||
msgid "ID"
|
||||
msgstr "ID (identificación)"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__image
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__image
|
||||
msgid "Image"
|
||||
msgstr "Imagen"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_fs_thumbnail
|
||||
msgid "Image Thumbnail"
|
||||
msgstr "Imagen en Miniatura"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Última Modificación el"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Última Actualización por"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Última Actualización el"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "MimeType"
|
||||
msgstr "Tipo Mimo"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__mimetype
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__mimetype
|
||||
msgid "Mimetype"
|
||||
msgstr "Tipo Mimo"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__name
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__name
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__original_image
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__original_image
|
||||
msgid "Original Image"
|
||||
msgstr "Imagen Original"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#. odoo-python
|
||||
#: code:addons/fs_image_thumbnail/models/fs_image_thumbnail_mixin.py:0
|
||||
#, python-format
|
||||
msgid "The base name must be set when multiple images are given"
|
||||
msgstr "El nombre base debe establecerse cuando se dan varias imágenes"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__base_name
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__base_name
|
||||
msgid "The base name of the thumbnail image (without extension)"
|
||||
msgstr "El nombre base de la imagen en miniatura (sin extensión)"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#. odoo-python
|
||||
#: code:addons/fs_image_thumbnail/models/fs_image_thumbnail_mixin.py:0
|
||||
#, python-format
|
||||
msgid "The image %(name)s must be attached to an attachment"
|
||||
msgstr "La imagen %(name)s debe adjuntarse a un archivo adjunto"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_image_thumbnail_mixin__base_name
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_thumbnail__base_name
|
||||
msgid ""
|
||||
"The thumbnail image will be named as base_name + _ + size_x + _ + size_y + . + extension.\n"
|
||||
"If not set, the base name will be the name of the original image.This base name is used to find all existing thumbnail of an image generated for the same base name."
|
||||
msgstr ""
|
||||
"La imagen en miniatura se denominará como nombre_base + _ + tamaño_x + _ + "
|
||||
"tamaño_y + . + extensión.\n"
|
||||
"Si no se establece, el nombre base será el nombre de la imagen original. "
|
||||
"Este nombre base se utiliza para encontrar todas las miniaturas existentes "
|
||||
"de una imagen generada para el mismo nombre base."
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_ir_attachment__thumbnail_ids
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.ir_attachment_form_view
|
||||
msgid "Thumbnails"
|
||||
msgstr "Miniaturas"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__size_x
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__size_x
|
||||
msgid "X size"
|
||||
msgstr "Tamaño X"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__size_y
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__size_y
|
||||
msgid "Y size"
|
||||
msgstr "Talla Y"
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * fs_image_thumbnail
|
||||
#
|
||||
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: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_ir_attachment
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__attachment_id
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__attachment_id
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Attachment"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_image_thumbnail_mixin__attachment_id
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_thumbnail__attachment_id
|
||||
msgid "Attachment containing the original image"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Base Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__create_uid
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_thumbnail_search_view
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__create_date
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_fs_image_thumbnail_mixin
|
||||
msgid "Fs Image Thumbnail Mixin"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.ui.menu,name:fs_image_thumbnail.fs_thumbnail_menu
|
||||
msgid "Fs Image Thumbnails"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.actions.act_window,name:fs_image_thumbnail.fs_thumbnail_act_window
|
||||
msgid "Fs Thumbnail"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Group By"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__image
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__image
|
||||
msgid "Image"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_fs_thumbnail
|
||||
msgid "Image Thumbnail"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "MimeType"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__mimetype
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__mimetype
|
||||
msgid "Mimetype"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__name
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__name
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__original_image
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__original_image
|
||||
msgid "Original Image"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#. odoo-python
|
||||
#: code:addons/fs_image_thumbnail/models/fs_image_thumbnail_mixin.py:0
|
||||
#, python-format
|
||||
msgid "The base name must be set when multiple images are given"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__base_name
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__base_name
|
||||
msgid "The base name of the thumbnail image (without extension)"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#. odoo-python
|
||||
#: code:addons/fs_image_thumbnail/models/fs_image_thumbnail_mixin.py:0
|
||||
#, python-format
|
||||
msgid "The image %(name)s must be attached to an attachment"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_image_thumbnail_mixin__base_name
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_thumbnail__base_name
|
||||
msgid ""
|
||||
"The thumbnail image will be named as base_name + _ + size_x + _ + size_y + . + extension.\n"
|
||||
"If not set, the base name will be the name of the original image.This base name is used to find all existing thumbnail of an image generated for the same base name."
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_ir_attachment__thumbnail_ids
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.ir_attachment_form_view
|
||||
msgid "Thumbnails"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__size_x
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__size_x
|
||||
msgid "X size"
|
||||
msgstr ""
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__size_y
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__size_y
|
||||
msgid "Y size"
|
||||
msgstr ""
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * fs_image_thumbnail
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2023-12-12 11:33+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 4.17\n"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_ir_attachment
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__attachment_id
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__attachment_id
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Attachment"
|
||||
msgstr "Allegato"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_image_thumbnail_mixin__attachment_id
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_thumbnail__attachment_id
|
||||
msgid "Attachment containing the original image"
|
||||
msgstr "Allegato contenente l'immagine originale"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Base Name"
|
||||
msgstr "Nome base"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__create_uid
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_thumbnail_search_view
|
||||
msgid "Created by"
|
||||
msgstr "Creato da"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Creato il"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nome visualizzato"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_fs_image_thumbnail_mixin
|
||||
msgid "Fs Image Thumbnail Mixin"
|
||||
msgstr "Mixin anteprima immagine FS"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.ui.menu,name:fs_image_thumbnail.fs_thumbnail_menu
|
||||
msgid "Fs Image Thumbnails"
|
||||
msgstr "Anteprima immagine FS"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.actions.act_window,name:fs_image_thumbnail.fs_thumbnail_act_window
|
||||
msgid "Fs Thumbnail"
|
||||
msgstr "Anteprima FS"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Group By"
|
||||
msgstr "Raggruppa per"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__id
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__image
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__image
|
||||
msgid "Image"
|
||||
msgstr "Immagine"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model,name:fs_image_thumbnail.model_fs_thumbnail
|
||||
msgid "Image Thumbnail"
|
||||
msgstr "Anteprima immagine"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Ultima modifica il"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Ultimo aggiornamento di"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Ultimo aggiornamento il"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "MimeType"
|
||||
msgstr "Tipo MIME"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__mimetype
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__mimetype
|
||||
msgid "Mimetype"
|
||||
msgstr "Tipo MIME"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__name
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__name
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.fs_image_thumbnail_mixin_search_view
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__original_image
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__original_image
|
||||
msgid "Original Image"
|
||||
msgstr "Immagine originale"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#. odoo-python
|
||||
#: code:addons/fs_image_thumbnail/models/fs_image_thumbnail_mixin.py:0
|
||||
#, python-format
|
||||
msgid "The base name must be set when multiple images are given"
|
||||
msgstr "Il nome base deve essere impostato qando vengono fornite più immagini"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__base_name
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__base_name
|
||||
msgid "The base name of the thumbnail image (without extension)"
|
||||
msgstr "Il nome base dell'immagIne anteprima (senza estensione)"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#. odoo-python
|
||||
#: code:addons/fs_image_thumbnail/models/fs_image_thumbnail_mixin.py:0
|
||||
#, python-format
|
||||
msgid "The image %(name)s must be attached to an attachment"
|
||||
msgstr "L'immagine %(name)s deve essere collegata ad una allegato"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_image_thumbnail_mixin__base_name
|
||||
#: model:ir.model.fields,help:fs_image_thumbnail.field_fs_thumbnail__base_name
|
||||
msgid ""
|
||||
"The thumbnail image will be named as base_name + _ + size_x + _ + size_y + . + extension.\n"
|
||||
"If not set, the base name will be the name of the original image.This base name is used to find all existing thumbnail of an image generated for the same base name."
|
||||
msgstr ""
|
||||
"L'immagine anteprima verrà denominata come "
|
||||
"nome_bae+_+dimensione_x+dimensione_y+.+estensione.\n"
|
||||
"Se non impostato, il nome base sarà il nome dell'immagine originale. Questo "
|
||||
"nome base è utilizzato per trovare tutte le anteprime di una immagine "
|
||||
"generate per lo stesso nome base."
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_ir_attachment__thumbnail_ids
|
||||
#: model_terms:ir.ui.view,arch_db:fs_image_thumbnail.ir_attachment_form_view
|
||||
msgid "Thumbnails"
|
||||
msgstr "Anteprime"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__size_x
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__size_x
|
||||
msgid "X size"
|
||||
msgstr "Dimensione X"
|
||||
|
||||
#. module: fs_image_thumbnail
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_image_thumbnail_mixin__size_y
|
||||
#: model:ir.model.fields,field_description:fs_image_thumbnail.field_fs_thumbnail__size_y
|
||||
msgid "Y size"
|
||||
msgstr "Dimensione Y"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
from . import fs_image_thumbnail_mixin
|
||||
from . import fs_thumbnail
|
||||
from . import ir_attachment
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
# Copyright 2023 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from slugify import slugify
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
from odoo.addons.fs_image.fields import FSImage, FSImageValue
|
||||
|
||||
|
||||
class FsImageThumbnailMixin(models.AbstractModel):
|
||||
"""Mixin defining what is a thumbnail image and providing a
|
||||
method to generate a thumbnail image from an image.
|
||||
|
||||
"""
|
||||
|
||||
_name = "fs.image.thumbnail.mixin"
|
||||
_description = "Fs Image Thumbnail Mixin"
|
||||
|
||||
image = FSImage("Image", required=True)
|
||||
original_image = FSImage("Original Image", compute="_compute_original_image")
|
||||
size_x = fields.Integer("X size", required=True)
|
||||
size_y = fields.Integer("Y size", required=True)
|
||||
base_name = fields.Char(
|
||||
"The base name of the thumbnail image (without extension)",
|
||||
required=True,
|
||||
help="The thumbnail image will be named as base_name "
|
||||
"+ _ + size_x + _ + size_y + . + extension.\n"
|
||||
"If not set, the base name will be the name of the original image."
|
||||
"This base name is used to find all existing thumbnail of an image generated "
|
||||
"for the same base name.",
|
||||
)
|
||||
|
||||
attachment_id = fields.Many2one(
|
||||
comodel_name="ir.attachment",
|
||||
string="Attachment",
|
||||
help="Attachment containing the original image",
|
||||
required=True,
|
||||
ondelete="cascade",
|
||||
)
|
||||
name = fields.Char(
|
||||
compute="_compute_name",
|
||||
store=True,
|
||||
)
|
||||
mimetype = fields.Char(
|
||||
compute="_compute_mimetype",
|
||||
store=True,
|
||||
)
|
||||
|
||||
@api.depends("image")
|
||||
def _compute_name(self):
|
||||
for record in self:
|
||||
record.name = record.image.name if record.image else None
|
||||
|
||||
@api.depends("image")
|
||||
def _compute_mimetype(self):
|
||||
for record in self:
|
||||
record.mimetype = record.image.mimetype if record.image else None
|
||||
|
||||
@api.depends("attachment_id")
|
||||
def _compute_original_image(self):
|
||||
original_image_field = self._fields["original_image"]
|
||||
for record in self:
|
||||
value = None
|
||||
if record.attachment_id:
|
||||
value = original_image_field._convert_attachment_to_cache(
|
||||
record.attachment_id
|
||||
)
|
||||
record.original_image = value
|
||||
|
||||
@api.model
|
||||
def _resize(self, image: FSImage, size_x: int, size_y: int, fmt: str = "") -> bytes:
|
||||
"""Resize the given image to the given size.
|
||||
|
||||
:param image: the image to resize
|
||||
:param size_x: the new width of the image
|
||||
:param size_y: the new height of the image
|
||||
:param fmt: the output format of the image. Can be PNG, JPEG, GIF, or ICO.
|
||||
Default to the format of the original image. BMP is converted to
|
||||
PNG, other formats than those mentioned above are converted to JPEG.
|
||||
:return: the resized image
|
||||
"""
|
||||
# image_process only accept PNG, JPEG, GIF, or ICO as output format
|
||||
# in uppercase. Remove the dot if present and convert to uppercase.
|
||||
fmt = fmt.upper().replace(".", "")
|
||||
return image.image_process(size=(size_x, size_y), output_format=fmt)
|
||||
|
||||
@api.model
|
||||
def _get_resize_format(self, image: FSImage) -> str:
|
||||
"""Get the format to use to resize an image.
|
||||
|
||||
:return: the format to use to resize an image
|
||||
"""
|
||||
fmt = (
|
||||
self.env["ir.config_parameter"]
|
||||
.sudo()
|
||||
.get_param("fs_image_thumbnail.resize_format")
|
||||
)
|
||||
return fmt or image.extension
|
||||
|
||||
@api.model
|
||||
def _prepare_tumbnail(
|
||||
self, image: FSImage, size_x: int, size_y: int, base_name: str
|
||||
) -> dict:
|
||||
"""Prepare the values to create a thumbnail image from the given image.
|
||||
|
||||
:param image: the image to resize
|
||||
:param size_x: the new width of the image
|
||||
:param size_y: the new height of the image
|
||||
:param base_name: the base name of the thumbnail image (without extension)
|
||||
:return: the values to create a thumbnail image
|
||||
"""
|
||||
fmt = self._get_resize_format(image)
|
||||
extension = fmt
|
||||
# Add a dot before the extension if needed and convert to lowercase.
|
||||
extension = extension.lower()
|
||||
if extension and not extension.startswith("."):
|
||||
extension = "." + extension
|
||||
new_image = FSImageValue(
|
||||
value=self._resize(image, size_x, size_y, fmt),
|
||||
name="%s_%s_%s%s" % (base_name, size_x, size_y, extension),
|
||||
alt_text=image.alt_text,
|
||||
)
|
||||
return {
|
||||
"image": new_image,
|
||||
"size_x": size_x,
|
||||
"size_y": size_y,
|
||||
"base_name": base_name,
|
||||
"attachment_id": image.attachment.id,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _slugify_base_name(self, base_name: str) -> str:
|
||||
"""Slugify the given base name.
|
||||
|
||||
:param base_name: the base name to slugify
|
||||
:return: the slugified base name
|
||||
"""
|
||||
return slugify(base_name) if base_name else base_name
|
||||
|
||||
@api.model
|
||||
def _get_existing_thumbnail_domain(
|
||||
self, *images: tuple[FSImageValue], base_name: str = ""
|
||||
) -> list:
|
||||
"""Get the domain to find existing thumbnail images from the given image.
|
||||
|
||||
:param images: a list of images we want to find existing thumbnails
|
||||
:param base_name: the base name of the thumbnail image (without extension)
|
||||
The base name must be set when multiple images are given.
|
||||
:return: the domain to find existing thumbnail images
|
||||
"""
|
||||
attachment_ids = []
|
||||
for image in images:
|
||||
if image.attachment:
|
||||
attachment_ids.append(image.attachment.id)
|
||||
else:
|
||||
raise UserError(
|
||||
_(
|
||||
"The image %(name)s must be attached to an attachment",
|
||||
name=image.name,
|
||||
)
|
||||
)
|
||||
base_name = self._get_slugified_base_name(*images, base_name=base_name)
|
||||
return [
|
||||
("attachment_id", "in", attachment_ids),
|
||||
("base_name", "=", base_name),
|
||||
]
|
||||
|
||||
@api.model
|
||||
def get_thumbnails(
|
||||
self, *images: tuple[FSImageValue], base_name: str = ""
|
||||
) -> list["FsImageThumbnailMixin"]:
|
||||
"""Get existing thumbnail images from the given image.
|
||||
|
||||
:param images: a list of images we want to find existing thumbnails
|
||||
:param base_name: the base name of the thumbnail image (without extension)
|
||||
The base name must be set when multiple images are given.
|
||||
:return: a recordset of thumbnail images
|
||||
"""
|
||||
domain = self._get_existing_thumbnail_domain(*images, base_name=base_name)
|
||||
return self.search(domain)
|
||||
|
||||
@api.model
|
||||
def get_or_create_thumbnails(
|
||||
self,
|
||||
*images: tuple[FSImageValue],
|
||||
sizes: list[tuple[int, int]],
|
||||
base_name: str = ""
|
||||
) -> OrderedDict[FSImageValue, list["FsImageThumbnailMixin"]]:
|
||||
"""Get or create a thumbnail images from the given image.
|
||||
|
||||
:param images: the list of images we want to get or create thumbnails
|
||||
:param sizes: the list of sizes to use to resize the image
|
||||
(list of tuple (size_x, size_y))
|
||||
:param base_name: the base name of the thumbnail image (without extension)
|
||||
The base name must be set when multiple images are given.
|
||||
:return: an ordered dictionary where the key is the original image and
|
||||
the value is a recordset of thumbnail images. The order of the dict
|
||||
is the order of the images passed to the method.
|
||||
"""
|
||||
base_name = self._get_slugified_base_name(*images, base_name=base_name)
|
||||
thumbnails = self.get_thumbnails(*images, base_name=base_name)
|
||||
thumbnails_by_attachment_id = thumbnails.partition("attachment_id")
|
||||
ret = OrderedDict[FSImageValue, list["FsImageThumbnailMixin"]]()
|
||||
for image in images:
|
||||
thumbnails_by_size = {
|
||||
(thumbnail.size_x, thumbnail.size_y): thumbnail
|
||||
for thumbnail in thumbnails_by_attachment_id.get(image.attachment, [])
|
||||
}
|
||||
ids_to_return = []
|
||||
for size_x, size_y in sizes:
|
||||
thumbnail = thumbnails_by_size.get((size_x, size_y))
|
||||
if not thumbnail:
|
||||
values = self._prepare_tumbnail(image, size_x, size_y, base_name)
|
||||
# no creation possible outside of this method -> sudo() is
|
||||
# required since no access rights defined on create
|
||||
thumbnail = self.sudo().create(values)
|
||||
ids_to_return.append(thumbnail.id)
|
||||
# return the thumbnails browsed in the same security context as the method
|
||||
# caller
|
||||
ret[image] = self.browse(ids_to_return)
|
||||
return ret
|
||||
|
||||
@api.model
|
||||
def _get_slugified_base_name(
|
||||
self, *images: tuple[FSImageValue], base_name: str
|
||||
) -> str:
|
||||
"""Get the base name of the thumbnail image (without extension).
|
||||
|
||||
:param images: the list of images we want to get the base name
|
||||
:return: the base name of the thumbnail image
|
||||
"""
|
||||
if not base_name:
|
||||
if len(images) > 1:
|
||||
raise UserError(
|
||||
_("The base name must be set when multiple images are given")
|
||||
)
|
||||
base_name = images[0].name
|
||||
return self._slugify_base_name(base_name)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# Copyright 2023 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class FsThumbnail(models.Model):
|
||||
|
||||
_name = "fs.thumbnail"
|
||||
_inherit = "fs.image.thumbnail.mixin"
|
||||
_description = "Image Thumbnail"
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# Copyright 2023 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class IrAttachment(models.Model):
|
||||
|
||||
_inherit = "ir.attachment"
|
||||
|
||||
thumbnail_ids = fields.One2many(
|
||||
comodel_name="fs.thumbnail",
|
||||
inverse_name="attachment_id",
|
||||
string="Thumbnails",
|
||||
readonly=True,
|
||||
)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
In some specific cases you may need to generate and store thumbnails of images in Odoo.
|
||||
This is the case for example when you want to provide image in specific sizes for a website
|
||||
or a mobile application.
|
||||
|
||||
This module provides a generic way to generate thumbnails of images and store them in a
|
||||
specific filesystem storage. Indeed, you could need to store the thumbnails in a different
|
||||
storage than the original image (eg: store the thumbnails in a CDN) to make sure the
|
||||
thumbnails are served quickly when requested by an external application and to
|
||||
avoid to expose the original image storage.
|
||||
|
||||
This module uses the `fs_image <https://github.com/oca/storage/blob/16.0/fs_image/README.rst>`_
|
||||
module to store the thumbnails in a filesystem storage.
|
||||
|
||||
The `shopinvader_product_image <https://github.com/shopinvader/odoo-shopinvader/
|
||||
blob/16.0/shopinvader_product_image>`_ addon uses this module to generate and
|
||||
store the thumbnails of the images of the products and categories to be accessible
|
||||
by the website.
|
||||
|
|
@ -0,0 +1 @@
|
|||
* Laurent Mignon <laurent.mignon@acsone.eu> (https://acsone.eu)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
The development of this module has been financially supported by:
|
||||
|
||||
* `Alcyon Belux <https://www.alcyonbelux.be/>`_
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
This module extends the **fs_image** addon to support the creation and the storage of
|
||||
thumbnails for images. This module is a **technical module** and is not
|
||||
meant to be installed by end-users. It only provides a mixin to be used
|
||||
by other modules and a model to store the thumbnails.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
16.0.1.0.1 (2023-10-04)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- The call to the method *get_or_create_thumbnails* on the *fs.image.thumbnail.mixin*
|
||||
class returns now an ordered dictionary where the key is the original image and
|
||||
the value is a recordset of thumbnail images. The order of the dict is the order
|
||||
of the images passed to the method. This ensures that when you process the result
|
||||
of the method you can be sure that the order of the images is the same as the
|
||||
order of the images passed to the method. (`#282 <https://github.com/OCA/storage/issues/282>`_)
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
This addon provides a convenient way to get and create if not exists image
|
||||
thumbnails. All the logic is implemented by the abstract model
|
||||
`fs.image.thumbnail.mixin`. The main method is `get_or_create_thumbnails` which
|
||||
accepts a *FSImageValue* instance, a list of thumbnail sizes and a base name.
|
||||
|
||||
When the method is called, it will check if the thumbnail exists for the given
|
||||
sizes and base name. If not, it will create it.
|
||||
|
||||
The `fs.thumbnail` model provided by this addon is a concrete implementation of
|
||||
the abstract model `fs.image.thumbnail.mixin`. The motivation to implement all the
|
||||
logic in an abstract model is to allow developers to create their own thumbnail
|
||||
models. This could be useful if you want to store the thumbnails in a different
|
||||
storage since you can specify the storage to use by model on the `fs.storage`
|
||||
form view.
|
||||
|
||||
Creating / retrieving thumbnails is as simple as:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from odoo.addons.fs_image.fields import FSImageValue
|
||||
|
||||
# create an attachment with a image file
|
||||
attachment = self.env['ir.attachment'].create({
|
||||
'name': 'test',
|
||||
'datas': base64.b64encode(open('test.png', 'rb').read()),
|
||||
'datas_fname': 'test.png',
|
||||
})
|
||||
|
||||
# create a FSImageValue instance for the attachment
|
||||
image_value = FSImageValue(attachment)
|
||||
|
||||
# get or create the thumbnails
|
||||
thumbnails = self.env['fs.thumbnail'].get_or_create_thumbnails(
|
||||
image_value, [(800,600), (400, 200)], 'my base name')
|
||||
|
||||
|
||||
|
||||
If you've a model with a *FSImage* field, the call to `get_or_create_thumbnails`
|
||||
is even simpler:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from odoo import models
|
||||
from odoo.addons.fs_image.fields import FSImage
|
||||
|
||||
class MyModel(models.Model):
|
||||
_name = 'my.model'
|
||||
|
||||
image = FSImage('Image')
|
||||
|
||||
my_record = cls.env['my.model'].create({
|
||||
'image': open('test.png', 'rb'),
|
||||
})
|
||||
|
||||
# get or create the thumbnails
|
||||
thumbnails = record.image.get_or_create_thumbnails(my_record.image,
|
||||
[(800,600), (400, 200)], 'my base name')
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- Copyright 2023 ACSONE SA/NV
|
||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||
<odoo>
|
||||
|
||||
<record model="ir.model.access" id="fs_thumbnail_access_read">
|
||||
<field name="name">fs.thumbnail access read</field>
|
||||
<field name="model_id" ref="model_fs_thumbnail" />
|
||||
<field name="group_id" ref="base.group_user" />
|
||||
<field name="perm_read" eval="1" />
|
||||
<field name="perm_create" eval="0" />
|
||||
<field name="perm_write" eval="0" />
|
||||
<field name="perm_unlink" eval="0" />
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
|
|
@ -0,0 +1,528 @@
|
|||
<!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>Fs Image Thumbnail</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
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: grey; } /* 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 {
|
||||
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="fs-image-thumbnail">
|
||||
<h1 class="title">Fs Image Thumbnail</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:ae84af058fd490c7c8916156dc7db31813b6d5f7535e722740b152d6955e0d57
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/storage/tree/16.0/fs_image_thumbnail"><img alt="OCA/storage" src="https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/storage-16-0/storage-16-0-fs_image_thumbnail"><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/storage&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 module extends the <strong>fs_image</strong> addon to support the creation and the storage of
|
||||
thumbnails for images. This module is a <strong>technical module</strong> and is not
|
||||
meant to be installed by end-users. It only provides a mixin to be used
|
||||
by other modules and a model to store the thumbnails.</p>
|
||||
<div class="admonition important">
|
||||
<p class="first admonition-title">Important</p>
|
||||
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
|
||||
Only for development or testing purpose, do not use in production.
|
||||
<a class="reference external" href="https://odoo-community.org/page/development-status">More details on development status</a></p>
|
||||
</div>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#use-cases-context" id="toc-entry-1">Use Cases / Context</a></li>
|
||||
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
|
||||
<li><a class="reference internal" href="#changelog" id="toc-entry-3">Changelog</a><ul>
|
||||
<li><a class="reference internal" href="#section-1" id="toc-entry-4">16.0.1.0.1 (2023-10-04)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-5">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="toc-entry-6">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="toc-entry-7">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="toc-entry-8">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#other-credits" id="toc-entry-9">Other credits</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="toc-entry-10">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="use-cases-context">
|
||||
<h1><a class="toc-backref" href="#toc-entry-1">Use Cases / Context</a></h1>
|
||||
<p>In some specific cases you may need to generate and store thumbnails of images in Odoo.
|
||||
This is the case for example when you want to provide image in specific sizes for a website
|
||||
or a mobile application.</p>
|
||||
<p>This module provides a generic way to generate thumbnails of images and store them in a
|
||||
specific filesystem storage. Indeed, you could need to store the thumbnails in a different
|
||||
storage than the original image (eg: store the thumbnails in a CDN) to make sure the
|
||||
thumbnails are served quickly when requested by an external application and to
|
||||
avoid to expose the original image storage.</p>
|
||||
<p>This module uses the <a class="reference external" href="https://github.com/oca/storage/blob/16.0/fs_image/README.rst">fs_image</a>
|
||||
module to store the thumbnails in a filesystem storage.</p>
|
||||
<p>The <a class="reference external" href="https://github.com/shopinvader/odoo-shopinvader/blob/16.0/shopinvader_product_image">shopinvader_product_image</a> addon uses this module to generate and
|
||||
store the thumbnails of the images of the products and categories to be accessible
|
||||
by the website.</p>
|
||||
</div>
|
||||
<div class="section" id="usage">
|
||||
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
|
||||
<p>This addon provides a convenient way to get and create if not exists image
|
||||
thumbnails. All the logic is implemented by the abstract model
|
||||
<cite>fs.image.thumbnail.mixin</cite>. The main method is <cite>get_or_create_thumbnails</cite> which
|
||||
accepts a <em>FSImageValue</em> instance, a list of thumbnail sizes and a base name.</p>
|
||||
<p>When the method is called, it will check if the thumbnail exists for the given
|
||||
sizes and base name. If not, it will create it.</p>
|
||||
<p>The <cite>fs.thumbnail</cite> model provided by this addon is a concrete implementation of
|
||||
the abstract model <cite>fs.image.thumbnail.mixin</cite>. The motivation to implement all the
|
||||
logic in an abstract model is to allow developers to create their own thumbnail
|
||||
models. This could be useful if you want to store the thumbnails in a different
|
||||
storage since you can specify the storage to use by model on the <cite>fs.storage</cite>
|
||||
form view.</p>
|
||||
<p>Creating / retrieving thumbnails is as simple as:</p>
|
||||
<pre class="code python literal-block">
|
||||
<span class="kn">from</span> <span class="nn">odoo.addons.fs_image.fields</span> <span class="kn">import</span> <span class="n">FSImageValue</span><span class="w">
|
||||
|
||||
</span><span class="c1"># create an attachment with a image file</span><span class="w">
|
||||
</span><span class="n">attachment</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="p">[</span><span class="s1">'ir.attachment'</span><span class="p">]</span><span class="o">.</span><span class="n">create</span><span class="p">({</span><span class="w">
|
||||
</span> <span class="s1">'name'</span><span class="p">:</span> <span class="s1">'test'</span><span class="p">,</span><span class="w">
|
||||
</span> <span class="s1">'datas'</span><span class="p">:</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64encode</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s1">'test.png'</span><span class="p">,</span> <span class="s1">'rb'</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()),</span><span class="w">
|
||||
</span> <span class="s1">'datas_fname'</span><span class="p">:</span> <span class="s1">'test.png'</span><span class="p">,</span><span class="w">
|
||||
</span><span class="p">})</span><span class="w">
|
||||
|
||||
</span><span class="c1"># create a FSImageValue instance for the attachment</span><span class="w">
|
||||
</span><span class="n">image_value</span> <span class="o">=</span> <span class="n">FSImageValue</span><span class="p">(</span><span class="n">attachment</span><span class="p">)</span><span class="w">
|
||||
|
||||
</span><span class="c1"># get or create the thumbnails</span><span class="w">
|
||||
</span><span class="n">thumbnails</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="p">[</span><span class="s1">'fs.thumbnail'</span><span class="p">]</span><span class="o">.</span><span class="n">get_or_create_thumbnails</span><span class="p">(</span><span class="w">
|
||||
</span> <span class="n">image_value</span><span class="p">,</span> <span class="p">[(</span><span class="mi">800</span><span class="p">,</span><span class="mi">600</span><span class="p">),</span> <span class="p">(</span><span class="mi">400</span><span class="p">,</span> <span class="mi">200</span><span class="p">)],</span> <span class="s1">'my base name'</span><span class="p">)</span>
|
||||
</pre>
|
||||
<p>If you’ve a model with a <em>FSImage</em> field, the call to <cite>get_or_create_thumbnails</cite>
|
||||
is even simpler:</p>
|
||||
<pre class="code python literal-block">
|
||||
<span class="kn">from</span> <span class="nn">odoo</span> <span class="kn">import</span> <span class="n">models</span><span class="w">
|
||||
</span><span class="kn">from</span> <span class="nn">odoo.addons.fs_image.fields</span> <span class="kn">import</span> <span class="n">FSImage</span><span class="w">
|
||||
|
||||
</span><span class="k">class</span> <span class="nc">MyModel</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span><span class="w">
|
||||
</span> <span class="n">_name</span> <span class="o">=</span> <span class="s1">'my.model'</span><span class="w">
|
||||
|
||||
</span> <span class="n">image</span> <span class="o">=</span> <span class="n">FSImage</span><span class="p">(</span><span class="s1">'Image'</span><span class="p">)</span><span class="w">
|
||||
|
||||
</span><span class="n">my_record</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="n">env</span><span class="p">[</span><span class="s1">'my.model'</span><span class="p">]</span><span class="o">.</span><span class="n">create</span><span class="p">({</span><span class="w">
|
||||
</span> <span class="s1">'image'</span><span class="p">:</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'test.png'</span><span class="p">,</span> <span class="s1">'rb'</span><span class="p">),</span><span class="w">
|
||||
</span><span class="p">})</span><span class="w">
|
||||
|
||||
</span><span class="c1"># get or create the thumbnails</span><span class="w">
|
||||
</span><span class="n">thumbnails</span> <span class="o">=</span> <span class="n">record</span><span class="o">.</span><span class="n">image</span><span class="o">.</span><span class="n">get_or_create_thumbnails</span><span class="p">(</span><span class="n">my_record</span><span class="o">.</span><span class="n">image</span><span class="p">,</span><span class="w">
|
||||
</span> <span class="p">[(</span><span class="mi">800</span><span class="p">,</span><span class="mi">600</span><span class="p">),</span> <span class="p">(</span><span class="mi">400</span><span class="p">,</span> <span class="mi">200</span><span class="p">)],</span> <span class="s1">'my base name'</span><span class="p">)</span>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="changelog">
|
||||
<h1><a class="toc-backref" href="#toc-entry-3">Changelog</a></h1>
|
||||
<div class="section" id="section-1">
|
||||
<h2><a class="toc-backref" href="#toc-entry-4">16.0.1.0.1 (2023-10-04)</a></h2>
|
||||
<p><strong>Bugfixes</strong></p>
|
||||
<ul class="simple">
|
||||
<li>The call to the method <em>get_or_create_thumbnails</em> on the <em>fs.image.thumbnail.mixin</em>
|
||||
class returns now an ordered dictionary where the key is the original image and
|
||||
the value is a recordset of thumbnail images. The order of the dict is the order
|
||||
of the images passed to the method. This ensures that when you process the result
|
||||
of the method you can be sure that the order of the images is the same as the
|
||||
order of the images passed to the method. (<a class="reference external" href="https://github.com/OCA/storage/issues/282">#282</a>)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#toc-entry-5">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/storage/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/storage/issues/new?body=module:%20fs_image_thumbnail%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-6">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-7">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>ACSONE SA/NV</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-8">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Laurent Mignon <<a class="reference external" href="mailto:laurent.mignon@acsone.eu">laurent.mignon@acsone.eu</a>> (<a class="reference external" href="https://acsone.eu">https://acsone.eu</a>)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="other-credits">
|
||||
<h2><a class="toc-backref" href="#toc-entry-9">Other credits</a></h2>
|
||||
<p>The development of this module has been financially supported by:</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference external" href="https://www.alcyonbelux.be/">Alcyon Belux</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#toc-entry-10">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>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
|
||||
<p><a class="reference external image-reference" href="https://github.com/lmignon"><img alt="lmignon" src="https://github.com/lmignon.png?size=40px" /></a></p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/storage/tree/16.0/fs_image_thumbnail">OCA/storage</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 @@
|
|||
from . import test_fs_image_thumbnail
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
# Copyright 2023 ACSONE SA/NV
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
import base64
|
||||
import io
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
from odoo.addons.fs_image.fields import FSImageValue
|
||||
|
||||
|
||||
class TestFsImageThumbnail(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
|
||||
cls.white_image = cls._create_image(32, 32, color="#FFFFFF")
|
||||
|
||||
cls.image_attachment = cls.env["ir.attachment"].create(
|
||||
{
|
||||
"name": "Test Image",
|
||||
"datas": base64.b64encode(cls.white_image),
|
||||
"mimetype": "image/png",
|
||||
}
|
||||
)
|
||||
|
||||
cls.fs_image_value = FSImageValue(attachment=cls.image_attachment)
|
||||
cls.fs_thumbnail_model = cls.env["fs.thumbnail"]
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.temp_dir = self.env["fs.storage"].create(
|
||||
{
|
||||
"name": "Temp FS Storage",
|
||||
"protocol": "memory",
|
||||
"code": "mem_dir",
|
||||
"directory_path": "/tmp/",
|
||||
"model_xmlids": "fs_image_thumbnail.model_fs_thumbnail",
|
||||
}
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _create_image(cls, width, height, color="#4169E1", img_format="PNG"):
|
||||
f = io.BytesIO()
|
||||
Image.new("RGB", (width, height), color).save(f, img_format)
|
||||
f.seek(0)
|
||||
return f.read()
|
||||
|
||||
def assert_image_size(self, value: bytes, width, height):
|
||||
self.assertEqual(Image.open(io.BytesIO(value)).size, (width, height))
|
||||
|
||||
def test_create_multi(self):
|
||||
self.assertFalse(self.image_attachment.thumbnail_ids)
|
||||
thumbnails = self.fs_thumbnail_model.get_or_create_thumbnails(
|
||||
self.fs_image_value, sizes=[(16, 16), (8, 8)], base_name="My super test"
|
||||
)[self.fs_image_value]
|
||||
self.assertEqual(len(thumbnails), 2)
|
||||
self.assertEqual(thumbnails[0].name, "my-super-test_16_16.png")
|
||||
self.assert_image_size(thumbnails[0].image.getvalue(), 16, 16)
|
||||
self.assertEqual(thumbnails[1].name, "my-super-test_8_8.png")
|
||||
self.assert_image_size(thumbnails[1].image.getvalue(), 8, 8)
|
||||
|
||||
self.assertEqual(self.image_attachment.thumbnail_ids, thumbnails)
|
||||
|
||||
# if we call the method again for the same size, we should get the same thumbnail
|
||||
new_thumbnails = self.fs_thumbnail_model.get_or_create_thumbnails(
|
||||
self.fs_image_value, sizes=[(16, 16), (8, 8)], base_name="My super test"
|
||||
)[self.fs_image_value]
|
||||
self.assertEqual(new_thumbnails, thumbnails)
|
||||
|
||||
def test_create_with_specific_format(self):
|
||||
self.env["ir.config_parameter"].set_param(
|
||||
"fs_image_thumbnail.resize_format", "JPEG"
|
||||
)
|
||||
thumbnail = self.fs_thumbnail_model.get_or_create_thumbnails(
|
||||
self.fs_image_value, sizes=[(8, 8)], base_name="My super test"
|
||||
)[self.fs_image_value]
|
||||
self.assertEqual(thumbnail[0].name, "my-super-test_8_8.jpeg")
|
||||
self.assertEqual(thumbnail[0].mimetype, "image/jpeg")
|
||||
self.assert_image_size(thumbnail[0].image.getvalue(), 8, 8)
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- Copyright 2023 ACSONE SA/NV
|
||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||
<odoo>
|
||||
|
||||
<record model="ir.ui.view" id="fs_image_thumbnail_mixin_form_view">
|
||||
<field name="name">fs.image.thumbnail.mixin.form (in fs_image_thumbnail)</field>
|
||||
<field name="model">fs.image.thumbnail.mixin</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<header>
|
||||
</header>
|
||||
<sheet>
|
||||
<label for="name" />
|
||||
<h1>
|
||||
<field name="name" />
|
||||
</h1>
|
||||
<group>
|
||||
<group>
|
||||
<field name="image" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="base_name" />
|
||||
<field name="size_x" />
|
||||
<field name="size_y" />
|
||||
<field name="mimetype" />
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="fs_image_thumbnail_mixin_search_view">
|
||||
<field
|
||||
name="name"
|
||||
>fs.image.thumbnail.mixin.search (in fs_image_thumbnail)</field>
|
||||
<field name="model">fs.image.thumbnail.mixin</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<field
|
||||
name="name"
|
||||
filter_domain="[('name','ilike',self)]"
|
||||
string="Name"
|
||||
/><field
|
||||
name="base_name"
|
||||
filter_domain="[('base_name','ilike',self)]"
|
||||
string="Base Name"
|
||||
/>
|
||||
<separator />
|
||||
<field name="mimetype" />
|
||||
<group expand="0" string="Group By">
|
||||
<filter
|
||||
string="MimeType"
|
||||
name="mimetype"
|
||||
domain="[]"
|
||||
context="{'group_by':'mimetype'}"
|
||||
/>
|
||||
<filter
|
||||
string="Attachment"
|
||||
name="attachment"
|
||||
domain="[]"
|
||||
context="{'group_by':'attachment_id'}"
|
||||
/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="fs_image_thumbnail_mixin_tree_view">
|
||||
<field name="name">fs.image.thumbnail.mixin.tree (in fs_image_thumbnail)</field>
|
||||
<field name="model">fs.image.thumbnail.mixin</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="name" />
|
||||
<field name="base_name" />
|
||||
<field name="size_x" />
|
||||
<field name="size_y" />
|
||||
<field name="mimetype" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- Copyright 2023 ACSONE SA/NV
|
||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||
<odoo>
|
||||
|
||||
<record model="ir.ui.view" id="fs_thumbnail_form_view">
|
||||
<field name="name">fs.thumbnail.form</field>
|
||||
<field name="model">fs.thumbnail</field>
|
||||
<field name="inherit_id" ref="fs_image_thumbnail_mixin_form_view" />
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<!-- add a hidden field to be able to extend the base view
|
||||
defined for the mixin
|
||||
-->
|
||||
<field name="base_name" position="after">
|
||||
<field name="id" invisible="1" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="fs_thumbnail_search_view">
|
||||
<field name="name">fs.thumbnail.search</field>
|
||||
<field name="model">fs.thumbnail</field>
|
||||
<field name="inherit_id" ref="fs_image_thumbnail_mixin_search_view" />
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<field name="mimetype" position="before">
|
||||
<field name="create_uid" string="Created by" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="fs_thumbnail_tree_view">
|
||||
<field name="name">fs.thumbnail.tree</field>
|
||||
<field name="model">fs.thumbnail</field>
|
||||
<field name="inherit_id" ref="fs_image_thumbnail_mixin_tree_view" />
|
||||
<field name="mode">primary</field>
|
||||
<field name="arch" type="xml">
|
||||
<!-- add a hidden field to be able to extend the base view
|
||||
defined for the mixin
|
||||
-->
|
||||
<field name="base_name" position="after">
|
||||
<field name="id" invisible="1" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="fs_thumbnail_act_window">
|
||||
<field name="name">Fs Thumbnail</field>
|
||||
<field name="res_model">fs.thumbnail</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="context">{}</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.menu" id="fs_thumbnail_menu">
|
||||
<field name="name">Fs Image Thumbnails</field>
|
||||
<field name="parent_id" ref="fs_storage.menu_storage" />
|
||||
<field name="action" ref="fs_thumbnail_act_window" />
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!-- Copyright 2023 ACSONE SA/NV
|
||||
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
|
||||
<odoo>
|
||||
|
||||
<record model="ir.ui.view" id="ir_attachment_form_view">
|
||||
<field name="name">ir.attachment.form (in fs_image_thumbnail)</field>
|
||||
<field name="model">ir.attachment</field>
|
||||
<field name="inherit_id" ref="base.view_attachment_form" />
|
||||
<field name="arch" type="xml">
|
||||
<group name="description_group" position="after">
|
||||
<group name="thumbnails" string="Thumbnails" colspan="4">
|
||||
<field name="thumbnail_ids" nolabel="1" colspan="2" />
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
44
odoo-bringout-oca-storage-fs_image_thumbnail/pyproject.toml
Normal file
44
odoo-bringout-oca-storage-fs_image_thumbnail/pyproject.toml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[project]
|
||||
name = "odoo-bringout-oca-storage-fs_image_thumbnail"
|
||||
version = "16.0.0"
|
||||
description = "Fs Image Thumbnail -
|
||||
Generate and store thumbnail for images"
|
||||
authors = [
|
||||
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
|
||||
]
|
||||
dependencies = [
|
||||
"odoo-bringout-oca-storage-fs_image>=16.0.0",
|
||||
"odoo-bringout-oca-storage-base_partition>=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 = ["fs_image_thumbnail"]
|
||||
|
||||
[tool.rye]
|
||||
managed = true
|
||||
dev-dependencies = [
|
||||
"pytest>=8.4.1",
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue