Merge pull request #48 from expsa/m2m

m2m
This commit is contained in:
esam-sermah 2025-10-11 14:25:24 +03:00 committed by GitHub
commit 37b7512fe2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 4 additions and 150 deletions

View File

@ -17,13 +17,12 @@
'size_restriction_for_attachments'
],
'data': [
'security/ir.model.access.csv',
'views/sale_menu_attachment_demo.xml', # <-- ملف الواجهة الجديد
],
'assets': {
'web.assets_backend': [
'odx_m2m_attachment_preview/static/src/components/many2many_attachment_preview/many2many_attachment_preview.css',
'odx_m2m_attachment_preview/static/src/components/document_viewer/document_viewer.css',
'odx_m2m_attachment_preview/static/src/components/document_viewer/document_viewer.css',
'odx_m2m_attachment_preview/static/src/components/many2many_attachment_preview/many2many_attachment_preview.xml',
'odx_m2m_attachment_preview/static/src/components/document_viewer/document_viewer.xml',
'odx_m2m_attachment_preview/static/src/components/many2many_attachment_preview/many2many_attachment_preview.js',

View File

@ -1,3 +1,2 @@
# -*- coding: utf-8 -*-
from . import ir_attachment_Ext
from . import attachment_demo

View File

@ -1,14 +0,0 @@
# -*- coding: utf-8 -*-
from odoo import models, fields
class AttachmentDemo(models.Model):
_name = 'attachment.demo'
_description = 'Attachment Preview Demo'
name = fields.Char(string='Demo Name', required=True)
attachment_ids = fields.Many2many(
'ir.attachment',
string='Attachments (Preview Widget)',
help="Attachments with the custom preview widget."
)

View File

@ -1,2 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_attachment_demo_user,attachment.demo user,model_attachment_demo,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_attachment_demo_user attachment.demo user model_attachment_demo base.group_user 1 1 1 1

View File

@ -1,5 +1,4 @@
/* Modal Full Screen */
/* Modal Full Screen - يغطي كل شيء */
.o_modal_fullscreen {
position: fixed !important;
top: 0 !important;

View File

@ -1,13 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="odx_m2m_attachment_preview.DocumentViewer" owl="1">
<!-- Full Screen Modal -->
<div class="o_modal_fullscreen o_document_viewer"
t-on-mousemove="onDrag"
t-on-mouseup="onEndDrag"
t-on-click.self="onClose">
<!-- Header -->
<div class="o_viewer_header">
<div class="o_viewer_img_wrapper">
<button type="button" class="btn btn-link o_close_btn" t-on-click="onClose" title="Close (ESC)">
@ -43,14 +41,12 @@
</div>
</div>
<!-- Content -->
<div class="o_viewer_content"
t-ref="content"
t-on-wheel="onScroll">
<div class="o_viewer_zoomer" t-att-style="zoomerTransform">
<!-- Image -->
<t t-if="activeAttachment.fileType === 'image'">
<img class="o_viewer_img"
t-att-style="transformStyle"
@ -63,26 +59,22 @@
</div>
</t>
<!-- PDF -->
<t t-if="activeAttachment.fileType === 'pdf'">
<iframe class="o_viewer_pdf"
t-att-src="'/web/static/lib/pdfjs/web/viewer.html?file=/web/content/ir.attachment/' + activeAttachment.id + '/datas'"/>
</t>
<!-- Video -->
<t t-if="activeAttachment.fileType === 'video'">
<video class="o_viewer_video" controls="controls" t-on-click="onImageClick">
<source t-att-src="'/web/content/ir.attachment/' + activeAttachment.id + '/datas'"/>
</video>
</t>
<!-- Text Files -->
<t t-if="activeAttachment.fileType === 'text'">
<iframe class="o_viewer_text"
t-att-src="'/web/content/ir.attachment/' + activeAttachment.id + '/datas'"/>
</t>
<!-- Other Binary Files -->
<t t-if="activeAttachment.fileType === 'binary'">
<div class="o_viewer_binary">
<div class="o_binary_icon">
@ -110,7 +102,6 @@
</div>
</div>
<!-- Navigation Arrows -->
<t t-if="props.attachments.length > 1">
<button type="button" class="arrow arrow-left move_previous" t-on-click="onPrevious" title="Previous (←)">
<span class="fa fa-chevron-left fa-2x"/>

View File

@ -1,4 +1,3 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
@ -42,24 +41,20 @@ export class Many2ManyAttachmentPreview extends Component {
return;
}
// الحل: استخراج الـ resId الصحيح من السجلات
const recordIds = records
.map(r => {
// إذا كان r عبارة عن object مع resId
if (r && typeof r === 'object' && r.resId) {
return r.resId;
}
// إذا كان r عبارة عن object مع id
if (r && typeof r === 'object' && r.id) {
return r.id;
}
// إذا كان r رقم مباشرة
if (typeof r === 'number') {
return r;
}
return null;
})
.filter(id => id !== null && typeof id === 'number'); // فلترة الأرقام الصحيحة فقط
.filter(id => id !== null && typeof id === 'number');
if (recordIds.length === 0) {
this.state.attachments = [];
@ -77,7 +72,6 @@ export class Many2ManyAttachmentPreview extends Component {
fileType: this.getFileType(att.mimetype)
}));
} catch (error) {
console.error("Error loading attachments:", error);
this.state.attachments = [];
}
}
@ -99,7 +93,6 @@ export class Many2ManyAttachmentPreview extends Component {
const currentRecordData = this.props.record.data[this.props.name];
// استخراج IDs الحالية بشكل صحيح
let attachment_ids = [];
if (currentRecordData && currentRecordData.records) {
attachment_ids = currentRecordData.records
@ -112,9 +105,7 @@ export class Many2ManyAttachmentPreview extends Component {
.filter(id => id !== null && typeof id === 'number');
}
console.log("Current attachment IDs:", attachment_ids);
// رفع الملفات الجديدة
for (const file of files) {
const fileData = await this.readFileAsB64(file);
const newAttachmentId = await this.orm.create("ir.attachment", [{
@ -126,23 +117,17 @@ export class Many2ManyAttachmentPreview extends Component {
attachment_ids.push(newAttachmentId[0]);
}
console.log("After upload - attachment IDs:", attachment_ids);
// تحديث الحقل بالطريقة الصحيحة
await this.props.record.update({
[this.props.name]: [[6, 0, attachment_ids]]
});
// إعادة تحميل المرفقات
await this.loadAttachments(attachment_ids.map(id => ({ resId: id })));
// حفظ السجل
try {
await this.props.record.model.root.save();
console.log("Save successful!");
this.notification.add(_t("Attachment(s) uploaded successfully"), { type: "success" });
} catch (error) {
console.error("Save error:", error);
this.notification.add(_t("Failed to save. Please save the record manually."), { type: "warning" });
}
@ -161,7 +146,6 @@ export class Many2ManyAttachmentPreview extends Component {
async onDeleteAttachment(attachmentId) {
const currentRecordData = this.props.record.data[this.props.name];
// استخراج IDs بشكل صحيح
let currentIds = [];
if (currentRecordData && currentRecordData.records) {
currentIds = currentRecordData.records
@ -184,7 +168,6 @@ export class Many2ManyAttachmentPreview extends Component {
await this.props.record.model.root.save();
this.notification.add(_t("Attachment removed"), { type: "success" });
} catch (error) {
console.error("Delete error:", error);
this.notification.add(_t("Failed to save. Please save the record manually."), { type: "warning" });
}
}

View File

@ -37,7 +37,6 @@
</t>
</div>
<!-- Document Viewer as Portal (renders outside DOM hierarchy) -->
<t t-if="state.showViewer" t-portal="'body'">
<DocumentViewer
attachments="state.attachments"

View File

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Form View -->
<record id="view_attachment_demo_form" model="ir.ui.view">
<field name="name">attachment.demo.form</field>
<field name="model">attachment.demo</field>
<field name="arch" type="xml">
<form string="Attachment Demo">
<sheet>
<group>
<field name="name"/>
</group>
<notebook>
<page string="Attachments">
<field name="attachment_ids" widget="many2many_attachment_preview"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- Tree View -->
<record id="view_attachment_demo_tree" model="ir.ui.view">
<field name="name">attachment.demo.tree</field>
<field name="model">attachment.demo</field>
<field name="arch" type="xml">
<list string="Attachment Demos">
<field name="name"/>
</list>
</field>
</record>
<!-- Action -->
<record id="action_attachment_demo" model="ir.actions.act_window">
<field name="name">Attachment Demos</field>
<field name="res_model">attachment.demo</field>
<field name="view_mode">list,form</field>
</record>
<!-- Menu Item -->
<menuitem
id="menu_attachment_demo_root"
name="Attachment Preview Demo"
sequence="100"/>
<menuitem
id="menu_attachment_demo"
name="Demos"
parent="menu_attachment_demo_root"
action="action_attachment_demo"/>
</odoo>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- This record forces the main menu to be visible to everyone by clearing its associated groups -->
<record id="odx_m2m_attachment_preview.menu_attachment_demo_root" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [])]"/>
</record>
<record id="odx_m2m_attachment_preview.menu_attachment_demo" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [])]"/>
</record>
</odoo>

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="action_attachment_demo" model="ir.actions.act_window">
<field name="name">Attachment Demos</field>
<field name="res_model">attachment.demo</field>
<field name="view_mode">list,form</field>
</record>
<menuitem
id="menu_attachment_demo_in_sales"
name="Attachment Demos"
parent="sale.sale_menu_root"
sequence="99"
action="action_attachment_demo"
groups="base.group_user"
/>
<record id="view_attachment_demo_form_in_sale" model="ir.ui.view">
<field name="name">attachment.demo.form</field>
<field name="model">attachment.demo</field>
<field name="arch" type="xml">
<form string="Attachment Demo">
<sheet>
<group>
<field name="name"/>
</group>
<notebook>
<page string="Attachments">
<field name="attachment_ids" widget="many2many_attachment_preview"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
</odoo>