m2m
This commit is contained in:
parent
d5d1f1f5f5
commit
9ee560bc03
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from . import ir_attachment_Ext
|
||||
from . import attachment_demo
|
||||
|
|
@ -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."
|
||||
|
||||
)
|
||||
|
|
@ -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,5 +1,4 @@
|
|||
/* Modal Full Screen */
|
||||
/* Modal Full Screen - يغطي كل شيء */
|
||||
|
||||
.o_modal_fullscreen {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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" });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
Loading…
Reference in New Issue