From e7c8c09ca3c36ff0531caca3e47244c0f50d22bd Mon Sep 17 00:00:00 2001 From: "admin.suherdy" Date: Wed, 17 Dec 2025 14:30:04 +0700 Subject: [PATCH] first commit --- __init__.py | 3 + __manifest__.py | 33 ++++++++++ __pycache__/__init__.cpython-312.pyc | Bin 0 -> 224 bytes data/sign_item_type_data.xml | 12 ++++ models/__init__.py | 3 + models/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 239 bytes .../sign_item_type.cpython-312.pyc | Bin 0 -> 664 bytes models/sign_item_type.py | 10 +++ static/src/js/sign_image_upload.js | 59 ++++++++++++++++++ static/src/xml/sign_items_image.xml | 38 +++++++++++ 10 files changed, 158 insertions(+) create mode 100644 __init__.py create mode 100644 __manifest__.py create mode 100644 __pycache__/__init__.cpython-312.pyc create mode 100644 data/sign_item_type_data.xml create mode 100644 models/__init__.py create mode 100644 models/__pycache__/__init__.cpython-312.pyc create mode 100644 models/__pycache__/sign_item_type.cpython-312.pyc create mode 100644 models/sign_item_type.py create mode 100644 static/src/js/sign_image_upload.js create mode 100644 static/src/xml/sign_items_image.xml diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..cde864b --- /dev/null +++ b/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models diff --git a/__manifest__.py b/__manifest__.py new file mode 100644 index 0000000..c5bda44 --- /dev/null +++ b/__manifest__.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'Sign Image Field', + 'version': '1.0', + 'category': 'Document Management', + 'summary': 'Add Image field to Sign module', + 'description': """ +This module extends the Odoo Sign module to allow users to upload images as a field type. + """, + 'depends': ['sign'], + 'data': [ + 'data/sign_item_type_data.xml', + ], + 'assets': { + 'web.assets_frontend': [ + 'sign_image_field/static/src/js/sign_image_upload.js', + 'sign_image_field/static/src/xml/sign_items_image.xml', + ], + 'web.assets_backend': [ + 'sign_image_field/static/src/js/sign_image_upload.js', + 'sign_image_field/static/src/xml/sign_items_image.xml', + ], + 'sign.assets_public_sign': [ + 'sign_image_field/static/src/js/sign_image_upload.js', + 'sign_image_field/static/src/xml/sign_items_image.xml', + ] + }, + 'installable': True, + 'application': False, + 'license': 'OEEL-1', +} diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc933a5bb3ba7eb4928b5c15ed124db102905b1d GIT binary patch literal 224 zcmXv}v1-FG6x6f9n1G>6Kf;SdwhST37nIKJAXGmk7D#%*vIl)hzoFmKy+hVc-3oyY zp85>QE${B&xO<;Xvl5Km*WO9K-;21TxRL7vlXrmv!HWPd03sJ{`2%dXaH#^J_35cC zE@CLz`w-V9Ilro&f>mki?SNTk)6v@@n6rtpBk52*=dq{Qaa<7+tv9Nh(n!G|QcNnj uQ`9b)lhsFOJu0nTbfebtoacJWwUf8Iq2{h-N?JboEdk)K67V=wEdK$G**h!% literal 0 HcmV?d00001 diff --git a/data/sign_item_type_data.xml b/data/sign_item_type_data.xml new file mode 100644 index 0000000..78885c0 --- /dev/null +++ b/data/sign_item_type_data.xml @@ -0,0 +1,12 @@ + + + + Image + image + fa-image + Upload an image + Click to upload image + 0.2 + 0.05 + + diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..5da7954 --- /dev/null +++ b/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import sign_item_type diff --git a/models/__pycache__/__init__.cpython-312.pyc b/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc2c61767873f7191eb2428e96803af41954bec3 GIT binary patch literal 239 zcmXv}F>V4e5cJ+j2qA&;fjr=vvuF?nBFP7$)HIg4HJqih_jL9Zeo5Ytx6o72rlLba zqM*v20@Liw>}q!RFr7{Wt<8 literal 0 HcmV?d00001 diff --git a/models/__pycache__/sign_item_type.cpython-312.pyc b/models/__pycache__/sign_item_type.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a25abc5b089e0c9a27ece9886b4043a2083c166a GIT binary patch literal 664 zcmZ8fJ&P1U5UrlCojY!IQNcuT6N3$$(L^p-PSHR&a23u#CTaSn+uc59rq}6NWQ-K< z2b|IU204F-V6uX!bR-y=38x4bSv|AEi5*ne>#A4%s=7b)`<1m`Y(I8eKk;gBLO3K2CyDET@b(+2{}KQN%m{b6C&@ei*lA-)PzR%)+1iz}Vp56xNxcv+ z&uK)FL>N_wQHd{eHWS95*sbg#*Yr}RQ^swyuSF)(N~(e~&P}Kalq)JR#mXV21!>x^X+(^?7$&w5Ut_ zOpUSa>T75Y;OqITuO56G3=e}ZgW<=)aCPJED!%vr#p)?rP4_+x($|ynV#k|~eB)US zOFV|@tg5) Iuzth-3vv>zLI3~& literal 0 HcmV?d00001 diff --git a/models/sign_item_type.py b/models/sign_item_type.py new file mode 100644 index 0000000..58db8e6 --- /dev/null +++ b/models/sign_item_type.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class SignItemType(models.Model): + _inherit = "sign.item.type" + + item_type = fields.Selection(selection_add=[('image', "Image")], ondelete={'image': 'cascade'}) diff --git a/static/src/js/sign_image_upload.js b/static/src/js/sign_image_upload.js new file mode 100644 index 0000000..2488af4 --- /dev/null +++ b/static/src/js/sign_image_upload.js @@ -0,0 +1,59 @@ +/** @odoo-module **/ + +import { patch } from "@web/core/utils/patch"; +import { SignablePDFIframe } from "@sign/components/sign_request/signable_PDF_iframe"; + +patch(SignablePDFIframe.prototype, { + enableCustom(signItem) { + super.enableCustom(signItem); + if (signItem.data.type === 'image') { + const input = signItem.el.querySelector('.o_sign_image_upload_input'); + if (!input) return; + + signItem.el.addEventListener('click', (e) => { + if (this.readonly || signItem.data.responsible !== this.currentRole) return; + // Prevent recursive click if clicking the input itself bubbles up + if (e.target !== input) { + input.click(); + } + }); + + input.addEventListener('change', (e) => { + const file = e.target.files[0]; + if (!file) return; + const reader = new FileReader(); + reader.onload = () => { + const result = reader.result; + signItem.el.dataset.value = result; + // Manually update the DOM to show the image + const img = signItem.el.querySelector('img'); + if (img) { + img.src = result; + } else { + // Remove placeholder if it exists + const placeholder = signItem.el.querySelector('.o_placeholder'); + if (placeholder) placeholder.remove(); + + const newImg = document.createElement('img'); + newImg.src = result; + newImg.style.maxWidth = '100%'; + newImg.style.maxHeight = '100%'; + newImg.style.objectFit = 'contain'; + + signItem.el.appendChild(newImg); + } + + this.handleInput(); // Trigger validation check + }; + reader.readAsDataURL(file); + }); + } + }, + + getSignatureValueFromElement(item) { + if (item.data.type === 'image') { + return item.el.dataset.value || false; + } + return super.getSignatureValueFromElement(item); + } +}); diff --git a/static/src/xml/sign_items_image.xml b/static/src/xml/sign_items_image.xml new file mode 100644 index 0000000..00d0ef3 --- /dev/null +++ b/static/src/xml/sign_items_image.xml @@ -0,0 +1,38 @@ + + + + + + + +
+ + + + + + + + + + +
+
+
+ + +
+
+ + + + + + + + + +
+
+
+