You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1474 lines
64 KiB

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>eis_drag_drop - Drag And Drop Images Module Documentation</title>
<!-- Bootstrap CSS -->
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
<!-- Font Awesome -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
/>
<style>
/* Top Bar */
.top-bar {
background-color: #0914e9;
padding: 10px 20px;
color: #fff;
}
.top-bar img {
height: 40px;
}
.availability {
font-size: 1rem;
}
.availability .fa-check {
color: #28a745;
}
.availability .fa-times {
color: #dc3545;
}
/* Hero Section */
.hero-section {
background: linear-gradient(135deg, #5e8694bc, #adb5bd);
color: #fff;
padding: 80px 20px;
text-align: center;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
position: relative;
min-height: 700px;
height: 700px;
}
.hero-section .vector-placeholder {
width: 500px;
height: 350px;
/* background-color: rgba(255,255,255,0.2); */
margin: 20px auto;
/* border-radius: 50%; */
display: flex;
/* align-items: baseline; */
justify-content: center;
bottom: 20px;
left: 50%;
}
.hero-section .benefit-box {
background-color: rgba(69, 205, 71, 0.3);
padding: 10px 20px;
border-radius: 20px;
display: inline-block;
margin-top: 20px;
font-size: 1.1rem;
}
/* Section Styling */
.section {
padding: 40px 20px;
background-color: #fff;
margin-bottom: 30px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.section h2 {
border-bottom: 2px solid #dee2e6;
padding-bottom: 10px;
margin-bottom: 20px;
}
.section h3 {
margin-top: 30px;
margin-bottom: 15px;
}
.section p,
.section li {
line-height: 1.6;
}
/* Code Block Styling */
.code-snippet {
background-color: #f1f1f1;
padding: 15px;
border-radius: 5px;
font-family: Consolas, Monaco, monospace;
position: relative;
margin-bottom: 20px;
border-left: 5px solid #007bff;
}
.code-snippet .highlight-field {
font-weight: bold;
color: #dc3545;
background-color: #fff3cd;
padding: 0 4px;
border-radius: 3px;
}
/* Full-width Screenshot Styling */
.screenshot-full {
width: 100%;
margin-bottom: 40px;
text-align: center;
}
.screenshot-full .screenshot-img {
width: 100%;
height: auto;
border: 2px dashed #ced4da;
border-radius: 5px;
margin-bottom: 10px;
}
.screenshot-number {
font-size: 2rem;
font-weight: bold;
color: #007bff;
margin-bottom: 10px;
}
/* Module Version Info */
.version-info {
background-color: #e9ecef;
padding: 20px;
border-radius: 8px;
}
.version-info ul {
list-style: none;
padding-left: 0;
}
.version-info li::before {
content: "\2022";
color: #007bff;
font-weight: bold;
display: inline-block;
width: 1em;
margin-left: -1em;
}
/* Services Tiles */
.service-tile {
background-color: #fff;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 20px;
text-align: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
transition: transform 0.2s;
}
.service-tile:hover {
transform: translateY(-5px);
}
.service-tile i {
font-size: 2rem;
color: #007bff;
margin-bottom: 10px;
}
/* Other Modules Slider */
.module-slider img {
width: 100%;
height: auto;
border-radius: 5px;
}
/* Best Practices & Troubleshooting */
.tips {
background-color: #fff3cd;
border-left: 5px solid #ffc107;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.troubleshooting {
background-color: #f8d7da;
border-left: 5px solid #dc3545;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.video-container {
position: relative;
width: 100%;
padding-bottom: 56.25%;
/* 16:9 aspect ratio */
height: 0;
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<!-- Top Bar -->
<div class="top-bar d-flex justify-content-between align-items-center">
<div>
<img src="img/logo.png" alt="Logo"/>
</div>
<div class="availability">
<span>
<i class="fa fa-check"></i>
Community
</span>
&nbsp;&nbsp;
<span>
<i class="fa fa-check"></i>
Enterprise
</span>
&nbsp;&nbsp;
<span>
<i class="fa fa-times"></i>
Odoo Online
</span>
</div>
</div>
<!-- Hero Section -->
<section class="hero-section">
<div class="container">
<h1>Images Drag And Drop Widgets</h1>
<p class="lead">
Effortlessly manage and update images in your Odoo records with our
intuitive drag and drop widgets.
</p>
<div class="vector-placeholder">
<img src="img/hero.svg" alt="Hero Vector"/>
</div>
<div class="benefit-box">
<i class="fa fa-users"></i>
Perfect for E-commerce, Media Portals
&amp; More!
</div>
</div>
</section>
<!-- Introduction -->
<section class="section" id="introduction">
<div class="container">
<h2 class="text-center mb-5 fw-bold">
<i
class="fa fa-envelope-open-text feature-icon"
aria-hidden="true"
></i
>
<br/>
Introduction
</h2>
<p>
The
<strong>Images Drag And Drop Widgets</strong>
module is a
state-of-the-art solution designed to enhance your Odoo experience by
integrating modern, user-friendly drag and drop image widgets.
</p>
<h3>Who Can Benefit?</h3>
<p>
Whether you run an e-commerce site, a media portal, a real estate
listing platform, or any business that requires the handling of
multiple images per record, this module is built for you. Enjoy:
</p>
<ul>
<li>
<strong>E-commerce websites:</strong>
Easily manage product images
with a simple drag and drop interface.
</li>
<li>
<strong>Businesses with heavy media content:</strong>
Quickly update
portfolios, galleries, and listings.
</li>
<li>
<strong>Developers and Designers:</strong>
Seamlessly integrate
modern widgets across all modules—no extra dependency required!
</li>
</ul>
<h3>Use Cases</h3>
<p>
<strong>Online Stores:</strong>
Showcase products with multiple images
that can be easily updated on-the-fly.
</p>
<p>
<strong>Real Estate Platforms:</strong>
Effortlessly manage property
photos, floor plans, and virtual tours.
</p>
<p>
<strong>Agencies &amp; Portfolios:</strong>
Create visually appealing
portfolios where media speaks louder than words.
</p>
<h3>Benefits</h3>
<p>
With our module, say goodbye to tedious file uploads and hello to a
more engaging user experience. It’s simple, robust, and designed to
boost your productivity!
</p>
</div>
</section>
<!-- Installation -->
<section class="section" id="installation">
<div class="container">
<h2 class="text-center mb-5 fw-bold">
<i class="fa fa-tools feature-icon" aria-hidden="true"></i>
<br/>
Installation
</h2>
<p>
Follow these detailed steps to install the
<strong>eis_drag_drop</strong>
module:
</p>
<ol>
<li>
<strong>Download the Module:</strong>
Obtain the module as a ZIP
file from the official repository or your vendor.
</li>
<li>
<strong>Extract the ZIP:</strong>
Unzip the downloaded file to
reveal the module folder.
</li>
<li>
<strong>Copy to Addons Folder:</strong>
Move or copy the extracted
module folder into your Odoo
<code>addons</code>
directory.
</li>
<li>
<strong>Restart Odoo Service:</strong>
<ul>
<li>
On systemd-based systems:
<code>sudo systemctl restart odoo</code>
</li>
<li>
On SysVinit-based systems:
<code>sudo service odoo restart</code>
</li>
<li>Or use the appropriate command for your OS.</li>
</ul>
</li>
<li>
<strong>Update App List:</strong>
In your Odoo database, navigate to
the Apps menu and click <em>Update Apps List</em>.
</li>
<li>
<strong>Install the Module:</strong>
Search for
<em>Drag and Drop Widgets</em>
(or <code>eis_drag_drop</code>) and
click install.
</li>
</ol>
<div class="tips">
<strong>Important:</strong>
Always test the module in a staging
environment before deploying it to your production server. Caution is
key—ensure you have backups and proper rollback plans in place.
</div>
</div>
</section>
<!-- User Guides -->
<section class="section" id="user-guidesa">
<div class="container">
<h2 class="text-center mb-5 fw-bold">
<i class="fa fa-map-signs feature-icon" aria-hidden="true"></i>
<br/>
User Guide
</h2>
<h3>
<i class="fa fa-desktop"></i>
Updating Existing Image Fields
</h3>
<p>
You can update any existing binary image field to use our drag and
drop widget without altering your custom modules. Simply update your
XML views by setting the widget attribute to:
</p>
<div class="code-snippet">
<pre>
<code>&lt;field name="image_field" widget="d_and_d_image" options="{
&quot;image_size&quot;: &quot;150x150&quot;,
&quot;preview_image&quot;: &quot;image_128&quot;,
&quot;acceptedFileExtensions&quot;: &quot;image/*&quot;,
&quot;enableZoom&quot;: true,
&quot;additionalStyles&quot;: &quot;border:2px solid #007bff;&quot;
}&gt;
&lt;/field&gt;
</code>
</pre>
</div>
<p>
<strong>Options Explained:</strong>
</p>
<ul>
<li>
<code>image_size</code>: Defines the display size of the widget.
Example: "150x150" sets the width to 150px and height to 150px.
</li>
<li>
<code>preview_image</code>: Specifies the field used for the image
preview. If not set, it defaults to the binary field name.
</li>
<li>
<code>acceptedFileExtensions</code>: Determines which image formats
can be uploaded.
</li>
<li>
<code>enableZoom</code>: If true, hovering over the image displays a
zoom popup.
</li>
<li>
<code>additionalStyles</code>: Custom CSS styles that are appended
to the widget's inline styles.
</li>
</ul>
<h3>
<i class="fa fa-code"></i>
Detailed O2M Setup & Custom Integration
</h3>
<p>
For One2Many fields, our widget transforms the standard image upload
into a dynamic drag and drop area.
<strong>Note:</strong>
The related model
<em>must</em>
have a Kanban
view defined that includes at least the
<code>name</code>
and
<code>image</code>
(or <code>image_1920</code>) fields.
</p>
<p>
<strong>Why a Kanban View?</strong>
The Kanban view enables the widget
to render image previews instead of just record IDs. Without it, you
may only see numerical identifiers.
</p>
<p>
<strong>Form View for Videos & Manual Entry:</strong>
If you wish to
add videos or manually add images in the traditional way, ensure that
your One2Many field is also accessible via a form view.
</p>
<h4>Example of One2Many Field Integration</h4>
<div class="code-snippet">
<pre>
<code>&lt;page name="media" string="Extra Media"&gt;
&lt;field name="media_ids" widget="d_and_d_images"
options="{
'childImageField': 'image_1920',
'extraData': {
'categ_id': 1,
'enable_zoom': true,
'previewImage': 'image_128',
'cssStyles': 'width:150px; height:200px; border-radius:15px;'
}
}"/&gt;
&lt;/page&gt;
</code>
</pre>
</div>
<h4>Options Explained:</h4>
<ul>
<li>
<code>childImageField</code>: Specifies the field in the child model
where the binary image data is stored. This is mandatory for the
widget to function correctly. If not specified, image_1920 will be
used.
</li>
<li>
<code>extraData</code>: Allows you to pass additional data to the
child records. This can include:
<ul>
<li>
<code>categ_id</code>: An example field that sets a default
category ID. This feature allows you to add any additional field
and its value if your model has a required field and without it,
it cannot create new records, or a field that you need to fill
with static data.
</li>
<li>
<code>sale_ok</code>: This is another example field and you can
pass any bool value if your required field is bool type
</li>
<li>
<code>previewImage</code>: Specifies a smaller image field to
use for previews, which is important if you want to show a
smaller size image to save bandwidth. This value should be used
if your model is inherited from
<code>image.mixin</code>
and you
want to display a smaller preview image.
</li>
<li>
<code>cssStyles</code>: Custom CSS styles for the image display.
Example:
<code
>"width:150px; height:200px; border-radius:15px;
object-fit:cover;"</code
>.
</li>
</ul>
</li>
<li>
<code>acceptedFileExtensions</code>: Determines which file types are
acceptable for upload. Default is <code>"image/*"</code>.
</li>
</ul>
</div>
</section>
<!-- User Guides -->
<section class="section" id="user-guides">
<div class="container">
<h2 class="text-center mb-5 fw-bold">
<i class="fa fa-map-signs feature-icon" aria-hidden="true"></i>
<br/>
User Guide
</h2>
<h3>
<i class="fa fa-desktop"></i>
Updating Existing Image Fields
</h3>
<p>
You can update any existing binary image field to use our drag and
drop widget without altering your custom modules. Simply update your
XML views by setting the widget attribute to:
</p>
<div class="code-snippet">
<pre>
<code>&lt;field name="image_field" widget="d_and_d_image" options="{
&quot;image_size&quot;: &quot;150x150&quot;,
&quot;preview_image&quot;: &quot;image_128&quot;,
&quot;acceptedFileExtensions&quot;: &quot;image/*&quot;,
&quot;enableZoom&quot;: true,
&quot;additionalStyles&quot;: &quot;border:2px solid #007bff;&quot;
}&gt;
&lt;/field&gt;
</code>
</pre>
</div>
<p>
<strong>Options Explained:</strong>
</p>
<ul>
<li>
<code>image_size</code>: Defines the display size of the widget.
Example: "150x150" sets the width to 150px and height to 150px.
</li>
<li>
<code>preview_image</code>: Specifies the field used for the image
preview. If not set, it defaults to the binary field name.
</li>
<li>
<code>acceptedFileExtensions</code>: Determines which image formats
can be uploaded.
</li>
<li>
<code>enableZoom</code>: If true, hovering over the image displays a
zoom popup.
</li>
<li>
<code>additionalStyles</code>: Custom CSS styles that are appended
to the widget's inline styles.
</li>
</ul>
<h3>
<i class="fa fa-code"></i>
Detailed O2M Setup & Custom Integration
</h3>
<p>
For One2Many fields, our widget transforms the standard image upload
into a dynamic drag and drop area.
<strong>Note:</strong>
The related
model
<em>must</em>
have a Kanban view defined that includes at least
the
<code>name</code>
and
<code>image</code>
(or
<code>image_1920</code>) fields.
</p>
<p>
<strong>Why a Kanban View?</strong>
The Kanban view enables the widget
to render image previews instead of just record IDs. Without it, you
may only see numerical identifiers.
</p>
<p>
<strong>Form View for Videos & Manual Entry:</strong>
If you wish to
add videos or manually add images in the traditional way, ensure that
your One2Many field is also accessible via a form view.
</p>
<h4>Example of One2Many Field Integration</h4>
<div class="code-snippet">
<pre>
<code>&lt;page name="media" string="Extra Media"&gt;
&lt;field name="media_ids" widget="d_and_d_images"
options="{
'childImageField': 'image_1920',
'extraData': {
'categ_id': 1,
'enable_zoom': true,
'previewImage': 'image_128',
'cssStyles': 'width:150px; height:200px; border-radius:15px;'
}
}"/&gt;
&lt;/page&gt;
</code>
</pre>
</div>
<h4>Options Explained:</h4>
<ul>
<li>
<code>childImageField</code>: Specifies the field in the child model
where the binary image data is stored. This is mandatory for the
widget to function correctly. If not specified,
<code>image_1920</code>
will be used.
</li>
<li>
<code>extraData</code>: Allows you to pass additional data to the
child records. This can include:
<ul>
<li>
<code>categ_id</code>: An example field that sets a default
category ID. This feature allows you to add any additional field
and its value if your model has a required field and without it,
it cannot create new records, or a field that you need to fill
with static data.
</li>
<li>
<code>sale_ok</code>: This is another example field and you can
pass any bool value if your required field is bool type.
</li>
<li>
<code>previewImage</code>: Specifies a smaller image field to
use for previews, which is important if you want to show a
smaller size image to save bandwidth. This value should be used
if your model is inherited from
<code>image.mixin</code>
and you
want to display a smaller preview image.
</li>
<li>
<code>cssStyles</code>: Custom CSS styles for the image display.
Example:
<code
>"width:150px; height:200px; border-radius:15px;
object-fit:cover;"</code
>.
</li>
</ul>
</li>
<li>
<code>acceptedFileExtensions</code>: Determines which file types are
acceptable for upload. Default is <code>"image/*"</code>.
</li>
</ul>
<div class="alert alert-danger" role="alert">
<h4 class="alert-heading">
<i class="fa fa-warning feature-icon fa-2x" aria-hidden="true"></i>
Important Notice!
</h4>
<p>Do not create the models described in the following example. Odoo already includes these models.
This example is provided for educational purposes to help you understand the implementation.
</p>
</div>
<br/>
<h4>
Complete Example (Taken from Odoo builtin Code):
<br/>
</h4>
<h5>Adding Multiple Image Support to
<code>product.template</code>
</h5>
<p>
Let's say we have a model
<code>product.template</code>
and we need to
add multiple image support to it. We will create a model
<code>product.image</code>
by inheriting from the
<code>image.mixin</code>
class. This way, we automatically get fields
like
<code>image_1920</code>
and other related fields for our model
<code>product.image</code>.
</p>
<p>Here are the steps to achieve this:</p>
<ol>
<li>
<strong>Create the
<code>product.image</code>
Model:
</strong>
<p>
Inherit from
<code>image.mixin</code>
to automatically get
image-related fields.
</p>
<div class="code-snippet">
<pre>
<code>class ProductImage(models.Model):
_name = 'product.image'
_inherit = 'image.mixin'
product_tmpl_id = fields.Many2one('product.template', string='Product Template')
sequence = fields.Integer('Sequence')
video_url = fields.Char('Video URL')
</code>
</pre>
</div>
</li>
<li>
<strong>Extend the
<code>product.template</code>
Model:
</strong>
<p>Add a One2Many field to link multiple images.</p>
<div class="code-snippet">
<pre>
<code>class ProductTemplate(models.Model):
_inherit = 'product.template'
product_template_image_ids = fields.One2many('product.image', 'product_tmpl_id',
string='Images')
</code>
</pre>
</div>
</li>
<li>
<strong
>Create a Kanban View for <code>product.image</code>:
</strong
>
<p>Add a Kanban view with the necessary fields.</p>
<div class="code-snippet">
<pre>
<code>&lt;record id="view_product_image_kanban" model="ir.ui.view"&gt;
&lt;field name="name"&gt;product.image.kanban&lt;/field&gt;
&lt;field name="model"&gt;product.image&lt;/field&gt;
&lt;field name="arch" type="xml"&gt;
&lt;kanban&gt;
&lt;field name="id"/&gt;
&lt;field name="name"/&gt;
&lt;field name="image_1920" widget="image"/&gt;
&lt;field name="sequence"/&gt;
&lt;/kanban&gt;
&lt;/field&gt;
&lt;/record&gt;
</code>
</pre>
</div>
</li>
<li>
<strong>Create a Form View for <code>product.image</code>:</strong>
<p>Add a form view with fields for video URL and image.</p>
<div class="code-snippet">
<pre>
<code>&lt;record id="view_product_image_form" model="ir.ui.view"&gt;
&lt;field name="name"&gt;product.image.form&lt;/field&gt;
&lt;field name="model"&gt;product.image&lt;/field&gt;
&lt;field name="arch" type="xml"&gt;
&lt;form&gt;
&lt;field name="id"/&gt;
&lt;field name="name"/&gt;
&lt;field name="video_url"/&gt;
&lt;field name="image_1920" widget="image"/&gt;
&lt;/form&gt;
&lt;/field&gt;
&lt;/record&gt;
</code>
</pre>
</div>
</li>
<li>
<strong>Update the
<code>product.template</code>
Form View:
</strong>
<p>Add the One2Many field with the drag-and-drop widget.</p>
<div class="code-snippet">
<pre>
<code>&lt;record id="view_product_template_form" model="ir.ui.view"&gt;
&lt;field name="name"&gt;product.template.form&lt;/field&gt;
&lt;field name="model"&gt;product.template&lt;/field&gt;
&lt;field name="inherit_id" ref="product.product_template_only_form_view"/&gt;
&lt;field name="arch" type="xml"&gt;
&lt;form&gt;
&lt;sheet&gt;
&lt;group&gt;
&lt;field name="product_template_image_ids" widget="d_and_d_images" options="{
'childImageField': 'image_1920',
'extraData': {
'cssStyles': 'width:150px;height:150px;'
}
}"/&gt;
&lt;/group&gt;
&lt;/sheet&gt;
&lt;/form&gt;
&lt;/field&gt;
&lt;/record&gt;
</code>
</pre>
</div>
</li>
</ol>
<div class="alert alert-warning">
<strong>Important Considerations for Product Image Management (Odoo 17 and 18)</strong>
<p>This guide outlines the necessary steps for integrating d_and_d_images widget for product
template, specifically when using the
<code>website_sale</code>
module, across Odoo 17 and 18. Please carefully follow the instructions for your respective Odoo
version to avoid conflicts and ensure proper functionality.
</p>
<p>
<strong>Odoo 17:</strong>
<ol>
<li>
<strong>Do not duplicate the
<code>product.image</code>
model or its views.
</strong>
This model is already provided by the
<code>website_sale</code>
module in Odoo. Creating a duplicate will lead to conflicts.
</li>
<li>
<strong>Inherit the
<code>product.template</code>
form view.
</strong>
. You will modify the form view
<code>product.product_template_form_view</code>
to integrate d_and_d_images customizations seamlessly with Odoo's core functionality.
</li>
<li>
<strong>Customize the image field:</strong>
Replace the
<code>product_template_image_ids</code>
field in the inherited form view with d_and_d_images widget as described above to enhance
the product image management functionality.
</li>
</ol>
</p>
<p>
<strong>Odoo 18:</strong>
<p>Odoo 18 has modified the
<code>product.image</code>
Kanban view by removing certain fields. So, to make it compatible again with our d_and_d_images
widghet, here's how to adjust Odoo 18:
</p>
<ol>
<li>
<strong>Inherit the
<code>product.image</code>
Kanban view.
</strong>
<code>website_sale.product_image_view_kanban</code>. Add the necessary
<code>id</code>
and
<code>name</code>
fields back into the view to maintain existing functionality. That's it.
</li>
<br/>
<li>
<strong>Enable modifications through the module's manifest:</strong>
<ul>
<li>Declare dependency on
<code>website_sale</code>
in our eis_drag_drop module's
<code>__manifest__.py</code>
file to ensure proper loading order. You jsut need to uncomment the line having
website_sale with key depends and then comment the existing depend key.
</li>
<li>Reference the XML file containing your Kanban view modifications in the
<code>data</code>
key of the manifest to apply these changes automatically when your module is
installed or updated.
</li>
</ul>
</li>
<li>
<strong>Alternative approach:</strong>
Manually define the Kanban view inheritance in a
<code>product.xml</code>
file if you prefer more direct control over the modifications.
</li>
</ol>
</p>
<p>Our module has pre-configured these enhancements for you. To activate them, modify the
<code>__manifest__.py</code>
file to uncomment the dependency on
<code>website_sale</code>
and the reference to
<code>/views/product.xml</code>
in the
<code>data</code>
key. This ensures all functionalities are seamlessly integrated when you install or update the
module.
</p>
</div>
</div>
</section>
<!-- Screenshots -->
<section class="section" id="screenshots">
<div class="container">
<h2 class="text-center mb-5 fw-bold">
<i class="fa fa-images feature-icon" aria-hidden="true"></i>
<br/>
Screenshots Explaination
</h2>
<!-- Screenshot 1 -->
<div class="screenshot-full">
<div class="screenshot-number">01</div>
<h4>Drag and Drop Widget Overview</h4>
<img
src="img/image1.png"
alt="Drag and Drop Widget Overview"
class="screenshot-img"
/>
<p>
A clear view of the drag and drop widget areas for single binary
image and for one2many images., allowing users to effortlessly
update images.
</p>
</div>
<!-- Screenshot 3 -->
<div class="screenshot-full">
<div class="screenshot-number">02</div>
<h4>One2Many Drag And Drop Explained</h4>
<img
src="img/image3.png"
alt="One2many Field Enhancement"
class="screenshot-img"
/>
<p>
In this screenshot, you can see a simple explaination of the view.
Each record's thumbnail, have a small cross on top right corner to
remove a record, view also display video thumbnail, and buttons.
</p>
</div>
<!-- Screenshot 4 -->
<div class="screenshot-full">
<div class="screenshot-number">04</div>
<h4>Add Video Button</h4>
<img
src="img/image4.png"
alt="One2many Field Enhancement"
class="screenshot-img"
/>
<p>
This screenshot illustrates how the one2many field widget
<code>'Add Video'</code>
button is working. You can access odoo
builtin method being used in website_sale module of odoo to add
extra media including videos or images.
</p>
</div>
<!-- Screenshot 5 -->
<div class="screenshot-full">
<div class="screenshot-number">05</div>
<h4>Manual File Uploding Button Display</h4>
<img
src="img/image5.png"
alt="One2many Field Enhancement"
class="screenshot-img"
/>
<p>
This screenshot illustrates how the one2many field widget manual
upload button is working. If you want to upload images manually from
file uploader, you can click on this button and it will open finder
/ file explorer for you. It will only allow images to upload with
jpg, jpeg, png, svg etc
</p>
</div>
<!-- Screenshot 5 -->
<div class="screenshot-full">
<div class="screenshot-number">06</div>
<h4>Iamges Dragging over One2many Field Display</h4>
<img
src="img/image6.png"
alt="One2many Field Enhancement"
class="screenshot-img"
/>
<p>
This screenshot illustrates how the one2many field is being used to
drop 4 images into drag drop area. Notice the blue border that is
highlighted when we dragged the images over it. As soon as we will
drop the images, they will be uploaded automatically
</p>
</div>
</div>
</section>
<section class="section" id="video">
<div class="container">
<h2 class="text-center mb-5 fw-bold">
<i class="fa fa-video feature-icon" aria-hidden="true"></i>
<br/>
Video Explaination
</h2>
<div class="screenshot-full">
<div class="screenshot-number">01</div>
<h4>Drag and Drop Widget Overview</h4>
<!-- Responsive YouTube video embed -->
<div class="video-container">
<iframe
src="https://www.youtube.com/embed/JRPchiEhS9U?rel=0&controls=0&showinfo=0&iv_load_policy=3&disablekb=1&modestbranding=1"
title="Drag And Drop Widget - Odoo"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
></iframe>
</div>
<p>Watch the video to see how it works.</p>
</div>
</div>
</section>
<!-- Module Version Info -->
<section class="section" id="version-info">
<div class="container">
<h2 class="text-center mb-5 fw-bold">
<i class="fa fa-low-vision feature-icon" aria-hidden="true"></i>
<br/>
Module Version Information &amp; Changelog
</h2>
<div class="version-info">
<ul>
<li>
<strong>v1.0.0</strong>
- Initial release with basic drag and drop
functionality.
</li>
<li>
<strong>v1.1.0</strong>
- Added support for one2many fields and
improved preview handling.
</li>
<li>
<strong>v1.2.0</strong>
- Enhanced UI, added zoom popup, and
refined installation instructions.
</li>
<li>
<strong>v1.3.0</strong>
- Bug fixes and performance improvements
for large image uploads.
</li>
<li>
<strong>v1.3.1</strong>
<ul>
<li> Fixes the situation where the form is dirty and d_and_d_images was discarding changes. in this version it will save the changes.
<li> A new option added 'showConfirm' in multi image widget d_and_d_images. It is bool
field and it will show a configuration dialog to ask for saving changes if form is
dirty. the extraData should contain a key 'showConfirm': true, if not provided or is false, the form will saved without confirmation.
</li>
<li>If not passed, default is to save dirty form to preserve changes.</li>
</ul>
</li>
</ul>
</div>
</div>
</section>
<!-- Services -->
<section class="section" id="services-2">
<div class="container">
<h2 class="text-center mb-5 fw-bold">
<i class="fa fa-hands-helping feature-icon" aria-hidden="true"></i
>
<br/>
90 Days Support
</h2>
<div class="row text-center">
<div class="col-md-4 mb-3">
<div class="service-tile">
<i class="fa fa-globe"></i>
<h5>Website</h5>
<p>
<a href="https://www.expertpk.com" target="_blank"
>www.expertpk.com
</a
>
</p>
</div>
</div>
<div class="col-md-4 mb-3">
<div class="service-tile">
<i class="fa fa-envelope"></i>
<h5>Email</h5>
<p>
<a href="mailto:support@expertpk.com">support@expertpk.com</a>
</p>
</div>
</div>
<div class="col-md-4 mb-3">
<div class="service-tile">
<i class="fa fa-whatsapp"></i>
<h5>WhatsApp</h5>
<p>+92 300 7888120</p>
</div>
</div>
</div>
</div>
</section>
<!-- Services Section -->
<section id="services" class="py-5 bg-light">
<div class="container">
<h2 class="text-center mb-5 fw-bold">
<i class="fa fa-handshake feature-icon"></i>
<br/>
Our Services
</h2>
<div class="row g-4">
<!-- Odoo Development -->
<div class="col-md-6 col-lg-3">
<div class="card h-100 text-center border-0 shadow-sm">
<div class="card-body">
<i class="fa fa-code fa-3x text-primary mb-3"></i>
<h5 class="card-title">Odoo Development</h5>
<p class="card-text text-muted">
Build custom Odoo modules and applications tailored to your
business needs.
</p>
<a href="#contact" class="btn btn-outline-primary">
Learn More
<i class="fas fa-arrow-right ms-2"></i>
</a>
</div>
</div>
</div>
<!-- Customization -->
<div class="col-md-6 col-lg-3">
<div class="card h-100 text-center border-0 shadow-sm">
<div class="card-body">
<i class="fa fa-tools fa-3x text-primary mb-3"></i>
<h5 class="card-title">Customization</h5>
<p class="card-text text-muted">
Customize Odoo to fit your unique workflows and business
processes.
</p>
<a href="#contact" class="btn btn-outline-primary">
Learn More
<i class="fa fa-arrow-right ms-2"></i>
</a>
</div>
</div>
</div>
<!-- Upgradation -->
<div class="col-md-6 col-lg-3">
<div class="card h-100 text-center border-0 shadow-sm">
<div class="card-body">
<i class="fa fa-sync-alt fa-3x text-primary mb-3"></i>
<h5 class="card-title">Upgradation</h5>
<p class="card-text text-muted">
Upgrade your Odoo instance to the latest version with zero
downtime.
</p>
<a href="#contact" class="btn btn-outline-primary">
Learn More
<i class="fa fa-arrow-right ms-2"></i>
</a>
</div>
</div>
</div>
<!-- Consultancy -->
<div class="col-md-6 col-lg-3">
<div class="card h-100 text-center border-0 shadow-sm">
<div class="card-body">
<i
class="fa fa-chalkboard-teacher fa-3x text-primary mb-3"
></i>
<h5 class="card-title">Consultancy</h5>
<p class="card-text text-muted">
Get expert advice on Odoo implementation, optimization, and
best practices.
</p>
<a href="#contact" class="btn btn-outline-primary">
Learn More
<i class="fa fa-arrow-right ms-2"></i>
</a>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Other Modules Slider -->
<section class="section" id="other-modules">
<div class="container">
<h2>Explore Our Other Modules</h2>
<div
id="modulesCarousel"
class="carousel slide module-slider"
data-bs-ride="carousel"
>
<div class="carousel-inner">
<div class="carousel-item active">
<img src="module1.png" class="d-block w-100" alt="Module 1"/>
<div class="carousel-caption d-none d-md-block">
<h5>Module 1: Advanced Reporting</h5>
</div>
</div>
<div class="carousel-item">
<img src="module2.png" class="d-block w-100" alt="Module 2"/>
<div class="carousel-caption d-none d-md-block">
<h5>Module 2: CRM Enhancements</h5>
</div>
</div>
<div class="carousel-item">
<img src="module3.png" class="d-block w-100" alt="Module 3"/>
<div class="carousel-caption d-none d-md-block">
<h5>Module 3: Inventory Optimizer</h5>
</div>
</div>
</div>
<button
class="carousel-control-prev"
type="button"
data-bs-target="#modulesCarousel"
data-bs-slide="prev"
>
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button
class="carousel-control-next"
type="button"
data-bs-target="#modulesCarousel"
data-bs-slide="next"
>
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
</div>
</section>
<!-- Best Practices & Troubleshooting -->
<section class="section" id="best-practices">
<div class="container">
<h2>Best Practices &amp; Troubleshooting</h2>
<div class="tips">
<h5>Best Practices</h5>
<ul>
<li>Always backup your database before applying new modules.</li>
<li>
Test the module in a staging environment prior to production
deployment.
</li>
<li>
Ensure that the related one2many models have the required Kanban
view with mandatory fields.
</li>
<li>
Regularly update your Odoo instance to keep up with security and
performance improvements.
</li>
</ul>
</div>
<div class="troubleshooting">
<h5>Troubleshooting Steps</h5>
<ul>
<li>
If image previews are not displaying, verify that your Kanban view
contains the
<code>name</code>
and <code>image</code>/
<code
>image_1920
</code
>
fields.
</li>
<li>
Check the browser console for JavaScript errors related to the
widget.
</li>
<li>
Ensure file permissions are correctly set in your addons folder.
</li>
<li>
Review the server logs for any errors during file upload or
service restart.
</li>
</ul>
</div>
</div>
</section>
<!-- Code Snippets Showcase -->
<section class="section" id="code-snippets">
<div class="container">
<h2>Code Snippets</h2>
<p>
Below are examples of typical XML view definitions where the new drag
and drop fields are highlighted:
</p>
<!-- Single Image Widget Example -->
<div class="code-snippet">
<h3>Single Image Widget</h3>
<p>
This snippet shows how to integrate a single image drag and drop
field into an Odoo form view:
</p>
<pre>
<code>&lt;form string="Product Form"&gt;
&lt;sheet&gt;
&lt;group&gt;
&lt;field name="name" /&gt;
&lt;field name="description" /&gt;
&lt;!-- Our new drag and drop image field is highlighted below --&gt;
<span class="highlight-field"> &lt;field name="image_1920" widget="d_and_d_image"
class="oe_avator" options="{
&quot;image_size&quot;: &quot;200x200&quot;,
&quot;preview_image&quot;: &quot;image_128&quot;,
&quot;acceptedFileExtensions&quot;: &quot;image/*&quot;,
&quot;enableZoom&quot;: true
}" /&gt;
&lt;field name="price" /&gt;
</span>
&lt;/group&gt;
&lt;/sheet&gt;
&lt;/form&gt;
</code>
</pre>
<p>
<strong>Explanation:</strong>
This code defines a form view for a
product. The
<code>product_image</code>
field uses the
<code>d_and_d_image</code>
widget, which allows users to drag and
drop images. The
<code>options</code>
attribute specifies settings
like image size, preview image, accepted file extensions, and zoom
functionality.
</p>
</div>
<!-- One2Many Image Widget Example -->
<div class="code-snippet">
<h3>One2Many Image Widget</h3>
<p>
This snippet demonstrates how to integrate a One2Many image drag and
drop field into an Odoo form view:
</p>
<pre>
<code>&lt;form string="Product Form"&gt;
&lt;sheet&gt;
&lt;group&gt;
&lt;field name="name" /&gt;
&lt;field name="description" /&gt;
&lt;!-- One2Many drag and drop image field --&gt;
<span class="highlight-field"> &lt;field name="product_images" widget="d_and_d_images"
options="{
&quot;childImageField&quot;: &quot;image_1920&quot;,
&quot;extraData&quot;: {
&quot;cssStyles&quot;: &quot;width:150px;height:150px;&quot;
}
}" /&gt;
&lt;field name="price" /&gt;
</span>
&lt;/group&gt;
&lt;/sheet&gt;
&lt;/form&gt;
</code>
</pre>
<p>
<strong>Explanation:</strong>
This code defines a form view for a
product with a One2Many field <code>product_images</code>. The
<code>d_and_d_images</code>
widget allows users to drag and drop
multiple images. The
<code>options</code>
attribute specifies the
child image field and additional CSS styles for the image display.
</p>
</div>
</div>
</section>
<!-- Footer -->
<footer class="text-center py-3">
<small>&copy; 2025 Expert IT Solutions. All rights reserved.</small>
</footer>
<!-- Bootstrap JS Bundle -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>