diff --git a/ToDo.txt b/ToDo.txt new file mode 100755 index 0000000..aa2a7af --- /dev/null +++ b/ToDo.txt @@ -0,0 +1,5 @@ +/* +** TODO : +** WISH : +** BUG : Screenview bring tFehler wenn ein Filter eingetragen ist - Ursache : domains[0][2] ist dann anders belegt - im dss_screenview_model.loaddata(data) +*/ \ No newline at end of file diff --git a/__manifest__.py b/__manifest__.py index e01c41b..fc89863 100755 --- a/__manifest__.py +++ b/__manifest__.py @@ -70,12 +70,18 @@ 'DigitalSignage/static/src/js/dss_screenview_renderer.js', 'DigitalSignage/static/src/js/dss_screenview_register.js', 'DigitalSignage/static/src/js/dss_screenview_model.js', + 'DigitalSignage/static/src/scss/dss_nextcloudwidget.scss', + 'DigitalSignage/static/src/xml/dss_nextcloudwidget.xml', + 'DigitalSignage/static/src/js/dss_nextcloudwidget.js', + 'DigitalSignage/static/src/xml/dss_nextcloudwidget_short.xml', + 'DigitalSignage/static/src/js/dss_nextcloudwidget_short.js', 'DigitalSignage/static/src/js/form_label.js', + 'DigitalSignage/static/src/js/dss_tagclick.js', 'DigitalSignage/static/src/js/form_button.js', 'DigitalSignage/static/src/js/kanban_button.js', - 'DigitalSignage/static/src/xml/form_button.xml', 'DigitalSignage/static/src/js/dss_klistmanager.js', 'DigitalSignage/static/src/js/screenDesignerViewReload.js', + 'DigitalSignage/static/src/xml/form_button.xml', 'DigitalSignage/static/src/xml/form_label.xml', ], 'web.assets_common': [ @@ -88,7 +94,11 @@ 'DigitalSignage/static/src/js/dss_screenview_injector.js', ], 'web.assets_qweb': [ + 'DigitalSignage/static/src/xml/kanban_button.xml', ], }, 'license': 'LGPL-3', } + +##https://www.odoo.com/documentation/16.0/developer/reference/frontend/owl_components.html +## \ No newline at end of file diff --git a/controllers/__init__.py b/controllers/__init__.py index cbdf303..fdcbce0 100755 --- a/controllers/__init__.py +++ b/controllers/__init__.py @@ -4,3 +4,4 @@ from . import main from . import dss_screendesigner_controller from . import dss_screenview_controller +from . import dss_nextcloudwidget diff --git a/controllers/__pycache__/__init__.cpython-311.pyc b/controllers/__pycache__/__init__.cpython-311.pyc old mode 100644 new mode 100755 index 531e773..f36fdcd Binary files a/controllers/__pycache__/__init__.cpython-311.pyc and b/controllers/__pycache__/__init__.cpython-311.pyc differ diff --git a/controllers/__pycache__/dss_nextcloudwidget.cpython-311.pyc b/controllers/__pycache__/dss_nextcloudwidget.cpython-311.pyc new file mode 100755 index 0000000..6687d64 Binary files /dev/null and b/controllers/__pycache__/dss_nextcloudwidget.cpython-311.pyc differ diff --git a/controllers/__pycache__/dss_screendesigner_controller.cpython-311.pyc b/controllers/__pycache__/dss_screendesigner_controller.cpython-311.pyc old mode 100644 new mode 100755 diff --git a/controllers/__pycache__/dss_screenview_controller.cpython-311.pyc b/controllers/__pycache__/dss_screenview_controller.cpython-311.pyc old mode 100644 new mode 100755 index 4a960b2..5d97a0e Binary files a/controllers/__pycache__/dss_screenview_controller.cpython-311.pyc and b/controllers/__pycache__/dss_screenview_controller.cpython-311.pyc differ diff --git a/controllers/dss_nextcloudwidget.py b/controllers/dss_nextcloudwidget.py new file mode 100755 index 0000000..d484658 --- /dev/null +++ b/controllers/dss_nextcloudwidget.py @@ -0,0 +1,136 @@ +import io +import easywebdav +import json +from odoo.http import Controller, route, request +from webdav4.client import Client +from webdav4.fsspec import WebdavFileSystem +from typing import ( BinaryIO ) +import logging +import base64 + +_logger = logging.getLogger(__name__) + +class MyController(Controller): + + @route('/my/webdav/files', auth='user', type='json') + def list_files(self,path): + client = WebdavFileSystem("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav")) + files = client.ls(path, detail=True) + #client.upload_file("Gorilla.jpg", "Photos/Gorilla.jpg") webdav = easywebdav.connect( + _logger.info("webdav : "+str(files)) + return files + # return [{'name': f.name, 'size': f.size} for f in files] + + @route('/my/webdav/upload', auth='user', type='json', methods=['POST']) + def upload_file(self, path, filename, filedata): + client = Client("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav")) + filedata = filedata.split("base64,")[-1] + _logger.info('Als Byte : '+str(bytes(filedata, encoding='utf-8'))) + infile = open('/opt/odoo/addons/DigitalSignage/temp/temp_in.temp', 'wb') + filedataStr=str(filedata) + _logger.info('Als String : '+str(filedataStr)) + decoded_data = base64.b64decode(bytes(filedata, encoding='utf-8')) + try: + decoded_data = base64.b64decode(filedataStr) + except base64.binascii.Error as e: + if 'Incorrect padding' in str(e): + filedataStr += b'=' * (4 - len(filedataStr) % 4) + decoded_data = base64.b64decode(filedataStr) + infile.write(decoded_data) + infile.close() + _logger.info(str(f"{path}/{filename}") + str(base64.b64decode(decoded_data))) + infile = open('/opt/odoo/addons/DigitalSignage/temp/temp_in.temp', 'rb') + client.upload_fileobj(infile, f"{path}/{filename}") + _logger.info(f"File {filename} uploaded to {path}") + return True + + @route('/my/webdav/getfile', auth='user', type='json') + def get_file(self,path,filename): + client = Client("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav")) + #files = client.cp('dav://'+path+'/'+filename,'/opt/odoo/addons/DigitalSignage/temp/'+filename) + infile = open('/opt/odoo/addons/DigitalSignage/temp/temp.temp', 'wb') + files = client.download_fileobj(path+'/'+filename,infile) + infile = open('/opt/odoo/addons/DigitalSignage/temp/temp.temp', 'rb') + indata = infile.read() + _logger.info("webdav : "+str(indata)) + encoded_file = base64.b64encode(indata) + #client.upload_file("Gorilla.jpg", "Photos/Gorilla.jpg") webdav = easywebdav.connect( + _logger.info("webdav : "+str(encoded_file)) + return encoded_file + # return [{'name': f.name, 'size': f.size} for f in files] + + @route('/my/webdav/makefolder', auth='user', type='json', methods=['POST']) + def make_folder(self, path, folder_name): + client = Client("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav")) + folder_path = f"{path}/{folder_name}" + try: + client.mkdir(folder_path) + _logger.info(f"Folder {folder_name} created at {path}") + return {"success": True, "message": f"Folder {folder_name} created at {path}"} + except Exception as e: + _logger.error(f"Error creating folder {folder_name} at {path}: {str(e)}") + return {"success": False, "message": f"Error creating folder: {str(e)}"} + + @route('/my/webdav/deletefile', auth='user', type='json') + def delete_file(self,filename): + client = Client("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav")) + #files = client.cp('dav://'+path+'/'+filename,'/opt/odoo/addons/DigitalSignage/temp/'+filename) + infile = open('/opt/odoo/addons/DigitalSignage/temp/temp.temp', 'wb') + files = client.remove(filename) + return True + # return [{'name': f.name, 'size': f.size} for f in files] + + + @route('/dss/getscreendata', type='json', auth='user') + def getscreendata(self, Domain): + # Tu was mit den Daten + screendef =[] + return screendef + + @route('/dss/setbtnfile', type='json', auth='user') + def setbtnfile(self, contract,filename): + contract = request.env['dss.contracts'].search([('id', '=', contract)]) + if len(contract.werbe_feld_selected) == 1: + client = Client("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav")) + #files = client.cp('dav://'+path+'/'+filename,'/opt/odoo/addons/DigitalSignage/temp/'+filename) + infile = open('/opt/odoo/addons/DigitalSignage/temp/temp_set.temp', 'wb') + files = client.download_fileobj(filename,infile) + infile = open('/opt/odoo/addons/DigitalSignage/temp/temp_set.temp', 'rb') + indata = infile.read() + encoded_file = base64.b64encode(indata) + _logger.info('JS : SetBtn File'+str(contract)) + for feld in contract.werbe_feld_selected: + feld.btn_image = filename + feld.btn_image_bin = encoded_file + res = True + else: + res = "MULTI/" + ids = "" + for feld in contract.werbe_feld_selected: + res += feld.feldname + ids += str(feld.id) + if feld != contract.werbe_feld_selected[-1]: + ids += ':' + res += ':' + res += "/"+ids + return res + + @route('/dss/setbtnfilefeld', type='json', auth='user') + def setbtnfilefeld(self, contract,filename,feldid): + feldids = feldid.split(':') + client = Client("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav")) + #files = client.cp('dav://'+path+'/'+filename,'/opt/odoo/addons/DigitalSignage/temp/'+filename) + infile = open('/opt/odoo/addons/DigitalSignage/temp/temp_set.temp', 'wb') + files = client.download_fileobj(filename,infile) + infile = open('/opt/odoo/addons/DigitalSignage/temp/temp_set.temp', 'rb') + indata = infile.read() + encoded_file = base64.b64encode(indata) + for feld_id in feldids: + feld = request.env['dss.advertisefields'].search([('id', '=', feld_id)]) + feld.btn_image = filename + feld.btn_image_bin = encoded_file + return True + + + + \ No newline at end of file diff --git a/controllers/dss_screenview_controller.py b/controllers/dss_screenview_controller.py old mode 100644 new mode 100755 index bb963ab..1a0e54e --- a/controllers/dss_screenview_controller.py +++ b/controllers/dss_screenview_controller.py @@ -6,6 +6,7 @@ import os import os.path import base64 + import logging from odoo.http import request _logger = logging.getLogger(__name__) @@ -19,4 +20,5 @@ class screenViewController(http.Controller): _logger.info('doch hier') request.env.ref('DigitalSignage.DigitalSignage.action_dss_contracts').run() print("Empfangen vom Frontend:", some_data) - return {'status': 'OK', 'message': 'Daten verarbeitet!'} \ No newline at end of file + return {'status': 'OK', 'message': 'Daten verarbeitet!'} + diff --git a/models/__pycache__/dss_ads.cpython-311.pyc b/models/__pycache__/dss_ads.cpython-311.pyc old mode 100644 new mode 100755 diff --git a/models/__pycache__/dss_advertisefields.cpython-311.pyc b/models/__pycache__/dss_advertisefields.cpython-311.pyc old mode 100644 new mode 100755 index 1bf332c..7f6a153 Binary files a/models/__pycache__/dss_advertisefields.cpython-311.pyc and b/models/__pycache__/dss_advertisefields.cpython-311.pyc differ diff --git a/models/__pycache__/dss_advertisefields_templates.cpython-311.pyc b/models/__pycache__/dss_advertisefields_templates.cpython-311.pyc old mode 100644 new mode 100755 index 66f2ce7..6cea621 Binary files a/models/__pycache__/dss_advertisefields_templates.cpython-311.pyc and b/models/__pycache__/dss_advertisefields_templates.cpython-311.pyc differ diff --git a/models/__pycache__/dss_contract.cpython-311.pyc b/models/__pycache__/dss_contract.cpython-311.pyc index d69f3d9..f5529f0 100644 Binary files a/models/__pycache__/dss_contract.cpython-311.pyc and b/models/__pycache__/dss_contract.cpython-311.pyc differ diff --git a/models/__pycache__/dss_importinvoicelist.cpython-311.pyc b/models/__pycache__/dss_importinvoicelist.cpython-311.pyc index 2990f54..89b106f 100755 Binary files a/models/__pycache__/dss_importinvoicelist.cpython-311.pyc and b/models/__pycache__/dss_importinvoicelist.cpython-311.pyc differ diff --git a/models/__pycache__/dss_m2mmail.cpython-311.pyc b/models/__pycache__/dss_m2mmail.cpython-311.pyc old mode 100644 new mode 100755 diff --git a/models/__pycache__/dss_projects.cpython-311.pyc b/models/__pycache__/dss_projects.cpython-311.pyc index 5965212..ed129d1 100644 Binary files a/models/__pycache__/dss_projects.cpython-311.pyc and b/models/__pycache__/dss_projects.cpython-311.pyc differ diff --git a/models/__pycache__/dss_settings.cpython-311.pyc b/models/__pycache__/dss_settings.cpython-311.pyc old mode 100755 new mode 100644 index 5c6b14b..978ee4d Binary files a/models/__pycache__/dss_settings.cpython-311.pyc and b/models/__pycache__/dss_settings.cpython-311.pyc differ diff --git a/models/__pycache__/dss_systemtypen.cpython-311.pyc b/models/__pycache__/dss_systemtypen.cpython-311.pyc index 13eace5..4e3bf90 100755 Binary files a/models/__pycache__/dss_systemtypen.cpython-311.pyc and b/models/__pycache__/dss_systemtypen.cpython-311.pyc differ diff --git a/models/__pycache__/dss_trigger.cpython-311.pyc b/models/__pycache__/dss_trigger.cpython-311.pyc old mode 100755 new mode 100644 index 4e40a3e..81c230d Binary files a/models/__pycache__/dss_trigger.cpython-311.pyc and b/models/__pycache__/dss_trigger.cpython-311.pyc differ diff --git a/models/__pycache__/dss_web_contracts.cpython-311.pyc b/models/__pycache__/dss_web_contracts.cpython-311.pyc index f374dfe..6286ff9 100644 Binary files a/models/__pycache__/dss_web_contracts.cpython-311.pyc and b/models/__pycache__/dss_web_contracts.cpython-311.pyc differ diff --git a/models/dss_advertisefields.py b/models/dss_advertisefields.py index 11af2a5..67c6d59 100755 --- a/models/dss_advertisefields.py +++ b/models/dss_advertisefields.py @@ -270,6 +270,6 @@ class dssadvertisefields(models.Model): def _compute_base64(self): for record in self: if record.btn_image_bin: - record.btn_image_bin_base64 = base64.b64encode(record.btn_image_bin).decode('utf-8') + record.btn_image_bin_base64 = 'data:image/png;base64,'+str(record.btn_image_bin) else: record.btn_image_bin_base64 = False \ No newline at end of file diff --git a/models/dss_advertisefields_templates.py b/models/dss_advertisefields_templates.py index 17f2f71..40c50ca 100755 --- a/models/dss_advertisefields_templates.py +++ b/models/dss_advertisefields_templates.py @@ -49,6 +49,8 @@ class dssadvertisefields(models.Model): templatefeldname = fields.Char('Template Feldname', required=True,tracking=True) display = fields.Char('Ziel Feldname',tracking=True) displaytemplate = fields.Many2one('dss.display.templates',string="Display Vorlage",tracking=True) + displaytemplate_fullsize_w = fields.Integer(related='displaytemplate.fullsize_w',string="Auflösung Breite",tracking=True) + displaytemplate_fullsize_h = fields.Integer(related='displaytemplate.fullsize_h',string="Auflösung Höhe",tracking=True) feldname = fields.Char('Ziel Feldname', required=True,tracking=True) color_used = fields.Char(string='Color Index',tracking=True) color_unused = fields.Char(string='Color Index',tracking=True) diff --git a/models/dss_contract.py b/models/dss_contract.py index f5ed437..aebe85f 100755 --- a/models/dss_contract.py +++ b/models/dss_contract.py @@ -23,12 +23,15 @@ from odoo import tools from . import dss_settings from . import dss_ads from odoo.exceptions import ValidationError +from odoo.exceptions import UserError from datetime import date from datetime import datetime from dateutil.relativedelta import relativedelta from pyffmpeg import FFmpeg from tuya_iot import TuyaOpenAPI, TUYA_LOGGER from tuya_connector import TuyaOpenAPI, TUYA_LOGGER +from webdav4.client import Client +from webdav4.fsspec import WebdavFileSystem import sys TUYA_LOGGER.setLevel(logging.DEBUG) @@ -115,13 +118,18 @@ class dsscontracts(models.Model): contract_remark = fields.Html('Vertragshinweise',tracking=True) project = fields.Many2one('dss.projects' , string='Project', store=True,tracking=True) + project_name = fields.Char(related='project.name') project_id = fields.Integer(related='project.projectid', string='Project ID') projectIid = fields.Integer('Project IID',tracking=True) project_ad_structure = fields.Many2one(related='project.grundsystem_default_adstructure', string='Aufbau') - project_grundsystem_typ = fields.Char(related='project.grundsystem_typ', tracking=True) + project_grundsystem_typ = fields.Char(related='project.grundsystem_typ', tracking=True) + project_grundsystem_typ_cloud_contract_template = fields.Char(related='project.grundsystem_default_cloud_structure_contract', tracking=True) project_grafiker = fields.Many2one(related="project.project_grafiker",tracking=True) project_system_uuid = fields.Char(related='project.grundsystemnameuuid', tracking=True) + run_trigger = fields.Boolean(tracking=True) + run_uni_trigger = fields.Boolean(tracking=True) + run_uni_sub_trigger = fields.Boolean(tracking=True) client = fields.Many2one('res.partner',string="Kunde (wenn angelegt)",domain="['&',('dsspartner','=',True),('dsspartner_werbung','=',True)]",tracking=True,help="Nur zu Benutzen wenn Kunden als Kontakt angelegt wurde") client_id = fields.Char(string="KundenID (2Stellen)",help="Nur der 2 stellige letzte Teil der Kundennummer",tracking=True) @@ -164,6 +172,12 @@ class dsscontracts(models.Model): cutshortwerbe_feld_selected = fields.Char(string='gekürzte Felder',compute='_compute_cutshort') werbe_feld_selected_btn_img = fields.Binary(related="werbe_feld_selected.btn_image_bin",string='Buttonbild',tracking=True) + werbe_feld_selected_btn_img_base64 = fields.Char(related="werbe_feld_selected.btn_image_bin_base64") + werbe_feld_selected_btn_pos_x = fields.Integer(related="werbe_feld_selected.btn_pos_x", tracking=True) + werbe_feld_selected_btn_pos_y = fields.Integer(related="werbe_feld_selected.btn_pos_y", tracking=True) + werbe_feld_selected_btn_pos_w = fields.Integer(related="werbe_feld_selected.btn_pos_w", tracking=True) + werbe_feld_selected_btn_pos_h = fields.Integer(related="werbe_feld_selected.btn_pos_h", tracking=True) + werbe_feld_selected_btn_name = fields.Char(related="werbe_feld_selected.btn_name",tracking=True) # need_media = fields.Many2many('dss.mediarelations','mediarelations_contract_rel','contract_id','mediarelations_id',string='benötigte Medien') last_media = fields.Many2many('dss.mediarelations',string='Medien',domain="[('isreference','=',False)]") @@ -180,11 +194,15 @@ class dsscontracts(models.Model): start_date = fields.Date('Start/Auslief.datum',tracking=True,help="Datum des geplanten Startes der 1. Kampagne. Also die Uraustrahlung!") contract_cancel_mon = fields.Integer('Kündigungsfrist Monaten',tracking=True) contract_cancel_date = fields.Date('Kündigungsfrist Errechnet', tracking=True) + contract_iscanceled = fields.Boolean('Vertrag gekündigt',tracking=True) + contract_iscanceled_date = fields.Date('Vertrag gekündigt am',tracking=True) contract_auto_extend = fields.Boolean('autom. V.Verlängerung',tracking=True) contract_auto_extend_time = fields.Char('Verl. Monate',tracking=True) scan_vertrag = fields.Binary('Datei') scan_vertrag_filename = fields.Char("Dateiname") # Hilft, den Dateinamen zu speichern + no_cancel_calc = fields.Boolean('Berechnungen verbieten',tracking=True) + runtimesystem = fields.Selection([('M','Monatslaufzeit'),('T','Tagelaufzeit'), ('E','Eventlaufzeit'), ('S','Sonderlaufzeit')],tracking=True) runtime_m = fields.Integer('Laufzeit Monate',tracking=True) runtime_bonus_m = fields.Integer('zusätzl. Laufzeit Monate',tracking=True) @@ -281,7 +299,8 @@ class dsscontracts(models.Model): web_contract = fields.Many2one('dss.web_contracts' , string='Web_Vertrag', store=True,tracking=True) tv_reach_PLZ = fields.Char(string='Reichweite PLZ',tracking=True) ads_radius_PLZ = fields.Integer('Umkreis PLZ in Km',tracking=True) - ads_count_perYear = fields.Selection([('30000','30.000'),('60000','60.000'),('120000','120.000'),('1000000','1.000.000')],'Einblendungen',tracking=True) + ads_count_perYear = fields.Selection([('30000','30.000'),('60000','60.000'),('120000','120.000'),('1000000','1.000.000')],'Einblendungen alt',tracking=True) + ads_count_perYear2 = fields.Integer('Einblendungen',tracking=True) ads_topics = fields.Many2many('dss.contracts_ads_topics', string='Themenliste', tracking=True) ads_topics_text = fields.Char('Themenliste gesamt',compute='_compute_themenliste') @@ -383,16 +402,17 @@ class dsscontracts(models.Model): @api.onchange('project_id') def _onchange_project_id(self): + _logger.info('project_id_change_1 : C_' + str(self) + ' - '+str(self.project)) for record in self : - if record.contract_name == '' : - cname = 'unbekannter Kunden' - else: - cname = record.contract_name - resstr = "%s%s %s" % (record.project_id,record.client_id,cname) - cidstr = "%s%s" % (record.project_id,record.client_id) - if resstr is None : - resstr = 'nicht ermittelbar' - _logger.info('project_id_change : C_' + str(self.id) + ' - '+str(cidstr)+' vs. '+str(self.contract_auto_id)+'/'+str(resstr)+' vs '+str(self.contract_auto_name)); + if record.contract_name == '' : + cname = 'unbekannter Kunden' + else: + cname = record.contract_name + resstr = "%s%s %s" % (record.project_id,record.client_id,cname) + cidstr = "%s%s" % (record.project_id,record.client_id) + if resstr is None : + resstr = 'nicht ermittelbar' + _logger.info('project_id_change : C_' + str(self.id) + ' - '+str(cidstr)+' vs. '+str(self.contract_auto_id)+'/'+str(resstr)+' vs '+str(self.contract_auto_name)) self.contract_auto_name = resstr self.contract_auto_id = cidstr @@ -407,7 +427,7 @@ class dsscontracts(models.Model): cidstr = "%s%s" % (record.project_id, record.client_id) if resstr is None : resstr = 'nicht ermittelbar' - _logger.info('Contract_Name_Change : C_' + str(self.id) + ' - '+str(cidstr)+' vs. '+str(self.contract_auto_id)+'/'+str(resstr)+' vs '+str(self.contract_auto_name)); + _logger.info('Contract_Name_Change : C_' + str(self.id) + ' - '+str(cidstr)+' vs. '+str(self.contract_auto_id)+'/'+str(resstr)+' vs '+str(self.contract_auto_name)) if not self.contract_auto_name: self.contract_auto_name = resstr if not self.contract_auto_id: @@ -876,7 +896,7 @@ class dsscontracts(models.Model): else: _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+str(kamp.id)+' Media gleich '+str(kampagne.need_media)) else: - _logger.info('Prüfe Medien : C_'+str(self.id)+'A_'+str(kamp.id)+' Keine Kampagne gefunden !') + _logger.info('Prüfe Medien : C_'+str(self.id)+'A_' +str(kamp.id)+' Keine Kampagne gefunden !') # _logger.info('Click auf Werbekampagne : '+str(self.id)+' 4 '+str(kampagne.id)) return { 'type': 'ir.actions.act_window', @@ -978,7 +998,7 @@ class dsscontracts(models.Model): def pyaction_new_contract_kanban(self): action = self.env['ir.actions.act_window'].with_context({'default_contractid': self.id})._for_xml_id('DigitalSignage.action_dss_project_new_contract_kanban') action['display_name'] = self.contract_name - # action['domain'] = '[["projectid","=","4"]]' + action['domain'] = '[["id","=","'+str(self.id)+'"]]' # context = action['context'].replace('', str(self.id)) # context = ast.literal_eval(context) # context.update({ @@ -989,7 +1009,47 @@ class dsscontracts(models.Model): return action def pyaction_dss_project_make_contract(self): - action = self.env['ir.actions.act_window'].with_context({'default_projectid': self.id})._for_xml_id('DigitalSignage.action_dss_project_view_contract') + #raise UserError(_("Inhalt : "+str(self.id)+" - "+str(self.contract_name)+" - "+str(self.client_id))) + newid =self.id + self.contract_auto_id = str(self.project_id) + str(self.client_id) + self.contract_auto_name = str(self.project_id) + str(self.client_id) + ' ' + str(self.contract_name) + projectcloudpath = self.project.cloudlink + if not projectcloudpath: + self.cloudlink = str(dss_settings.dssSettings.getprojectpath(self,self.project))+str(dss_settings.dssSettings.getClientpath(self,self)) + else: + if projectcloudpath[0] != '$': + self.cloudlink = str(projectcloudpath)+str(dss_settings.dssSettings.getClientpath(self,self)) + else: + self.cloudlink = str(dss_settings.dssSettings.getprojectpath(self,self.project))+str(dss_settings.dssSettings.getClientpath(self,self)) + action = (self.env["confirmation.wizard"].confirm_message(_("Ist die Bezeichnung des neuen Kunden : "+self.contract_auto_name+" richtig ?( "+str(self.cloudlink)+" ) (Cloudornder wird entsprechend angelegt) !"),title="Bitte bestätigen",method="createcontract",records=self,callback_params={"template":self.id}) + ) + if action: + return action + + def create_cloud_structure_client(self, newClient): + _logger.info("Create Cloud Structure for Client "+str(newClient.id)+" - "+str(newClient.cloudlink)) + cloudpath = str(newClient.cloudlink) + client = Client("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav")) + _logger.info("Neuer Cloud Path : "+str(cloudpath)) + try: + #client.mkdir(new_folder) + #_logger.info("Make Cloud Path : "+str(new_folder)) + _logger.info("Create Standard Cloud Structure for Client "+str(newClient.id)+" - "+str(newClient.cloudlink)) + client.copy(newClient.project_grundsystem_typ_cloud_contract_template+'/',cloudpath) + _logger.info("Make Standard Cloud Path : "+str(cloudpath+'/'+str(newClient.project_grundsystem_typ_cloud_contract_template))) + except Exception as e: + _logger.info("Make Cloud Path error : "+str(e)) + return True + + + def createcontract(self,template): + newid = template + newClient = self.env['dss.contracts'].search([('id','=',newid)]) + dsscontracts.create_cloud_structure_client(self,newClient) + _logger.info('Neu angelegt : '+str(self.id)+' - '+str(self.contract_name)+' - '+str(self.client_id)) + action = self.env['ir.actions.act_window'].with_context({'default_projectid': self.id})._for_xml_id('DigitalSignage.action_open_create_contract_new_edit') + action['domain'] = '[["id","=","'+str(newid)+'"]]' + action['res_id'] = newid return action @@ -1046,3 +1106,157 @@ class dsscontracts(models.Model): self.client_short_telefon=self.client.phone self.client_short_mobil=self.client.mobile self.client_short_email=self.client.email + + + def buildText(self): + _logger.info('Build Text for Contract : C_'+str(self.id)) + + if self.project_id: + projekt_id = self.project_id + else: + projekt_id = '000' + + if self.project_name: + projekt = self.project_name + else: + projekt = 'Unbekannt' + + if self.contract_name: + vertrag_name = self.contract_name + else: + vertrag_name = 'Unbekannt' + + if self.contract_auto_id: + vertrag_id = self.contract_auto_id + else: + vertrag_id = 'XXXXX' + + if self.client_short_vorname: + vname = self.client_short_vorname + else: + vname = 'Unbekannt' + + if self.client_short_name: + name = self.client_short_name + else: + name = 'Unbekannt' + + if self.client_short_strasse: + vstrasse = self.client_short_strasse + else: + vstrasse = 'Unbekannt' + + if self.client_short_plz: + vplz = self.client_short_plz + else: + vplz = '00000' + + if self.client_short_ort: + vort = self.client_short_ort + else: + vort = 'unbekannt' + + vplz_vort = '%s %s' % (vplz,vort) + + if self.client_short_email: + vemail = 'ist per Email über %s zu erreichen' % (self.client_short_email) + else: + vemail = 'ist nicht per Email zu erreichbar' + + if self.client_short_telefon: + vtelefon = 'ist per Telefon unter %s zu erreichen' % (self.client_short_telefon) + else: + vtelefon = 'ist nicht per Telefon zu erreichen' + + if self.client_short_mobil: + vmobil = 'ist per Mobiltelefon unter %s zu erreichen' % (self.client_short_mobil) + else: + vmobil = 'ist nicht per Mobiltelefon zu erreichen' + + textprojekt= 'Es ist im Projekt %s_%s ' % (projekt_id,projekt) + + vertragkopftext = 'ein Vertrag mit der Kundennummer %s und der Vertragskennung %s.' % (vertrag_id,vertrag_name) + + kundentext = 'Dieser Kunde heisst %s %s und wohnt in der %s in %s. Der Kunde %s und %s und %s' % (vname,name,vstrasse,vplz_vort,vemail,vtelefon,vmobil) + + if self.client_short_mobil: + vmobil = 'ist per Mobiltelefon unter %s zu erreichen' % (self.client_short_mobil) + else: + vmobil = 'ist nicht per Mobiltelefon zu erreichen' + + if self.start_date: + startzeit = self.start_date.strftime('%d.%m.%Y') + else: + startzeit = 'unbekannt' + + if self.contract_date: + startzeit = self.contract_date.strftime('%d.%m.%Y') + + if self.runtime_finish: + if self.runtime_finish < date.today(): + endzeit = 'Er ist bereits abgelaufen am %s' % (self.runtime_finish.strftime('%d.%m.%Y')) + else: + endzeit = 'Er endet am %s' % (self.runtime_finish.strftime('%d.%m.%Y')) + else: + endzeit = 'unbekannt' + + laufzeitmodel = 'Laufzeitmodell unbekannt' + if self.runtimesystem == 'M': + laufzeitmodel = 'eine monatliche Laufzeit mit %s Monaten und %s Monaten Bonus' % (self.runtime_m,self.runtime_bonus_m) + elif self.runtimesystem == 'T': + laufzeitmodel = 'eine tägliche Laufzeit mit %s Tagen ' % (self.runtime_t) + elif self.runtimesystem == 'E': + laufzeitmodel = 'eine ereignisabhängige Laufzeit mit %s Ereignissen' % (len(self.runtime_events)) + elif self.runtimesystem == 'S': + if self.runtime_finish: + laufzeitmodel = 'ein stichtagsabhängig Laufzeit bis zum %s' % (self.runtime_finish.strftime('%d.%m.%Y')) + else: + laufzeitmodel = 'ein stichtagsabhängig Laufzeit unbekannt' + + kuendigungsfrist = 'Die Kündigungsfrist beträgt %s Monate' % (self.contract_cancel_mon) + if self.contract_cancel_date: + kuendigungsfrist = 'Die Kündigungsfrist beträgt %s Monate und endet am %s' % (self.contract_cancel_mon,self.contract_cancel_date.strftime('%d.%m.%Y')) + if self.contract_cancel_date < date.today(): + kuendigungsfrist = 'Die Kündigungsfrist beträgt %s Monate und endet am %s' % (self.contract_cancel_mon,self.contract_cancel_date.strftime('%d.%m.%Y')) + + + vertragtext = 'Der Vertrag hat die Vertragskennung %s und ist am %s begonnen. Der Vertrag hat %s . %s. %s' % (vertrag_id,startzeit,laufzeitmodel,endzeit,kuendigungsfrist) + + + text = textprojekt + " "+vertragkopftext + kundentext + '. '+ vertragtext + + + return text + raise ValidationError((text)) + + _logger.info('Build Text for Contract : C_'+str(self.id)+' - '+str(text)) + return text + + def buildallText(self): + _logger.info('Build all Text for Contract : C_'+str(self)) + if self and "all" in str(self[0]): + self = self.env['dss.contracts'].search([]) + if not self: + raise ValidationError(_("The first record contains 'all' in its string representation.")) + + all_contract_text = '' + contracts = [] + for record in self: + _logger.info('Build Text for Contract : C_'+str(record.id)) + singletext = ' Ein Vertrag mit der ID '+str(record.id)+': '+record.buildText() + contracts += [singletext] + _logger.info('Build Text for Contract : C_'+str(record.id)+' - '+str(singletext)) + all_contract_text += singletext + + #raise ValidationError((all_contract_text)) + return contracts + + @api.model + def newwizzard(self,id): + project = self.env['dss.projects'].search([('id', '=', id)], limit=1) + _logger.info("Create new Contract Wizard - Project : "+str(project)) + action = self.env["ir.actions.actions"]._for_xml_id("DigitalSignage.action_open_create_contract") + action['context'] = {'default_project': project.id} + + + return action diff --git a/models/dss_importinvoicelist.py b/models/dss_importinvoicelist.py index 1bf70ba..6c6094f 100755 --- a/models/dss_importinvoicelist.py +++ b/models/dss_importinvoicelist.py @@ -80,12 +80,18 @@ class dssimportinvoicelist(models.Model): entry = self.env['dss.invoices'].create({'invoiceid':line[0],'from_import':self.id,'invoicename':line[1],'invoiceclientnr':line[3],'contract':client.id,'invoice_date':datetime.strptime(line[4],"%d.%m.%Y"),'is_printed':(line[5]=="Endgltig"),'ammount_netto':line[6].strip(),'ammount_ust':line[7].strip(),'ammount_brutto':line[8].strip(),'is_payed':(line[11]=="Ja"),'invoice_type':line[9],'invoice_reference':line[10]}) BotText='Rechnung ['+str(line[0])+'] für '+str(line[1])+' ('+str(line[3])+') neu erstellt als ' if (line[11]=="Ja"): - entry.is_payed_date = self.date_create + entry.is_payed = True + entry.is_payed_date = self.date_create + client.contract_payment_done = True + client.contract_payment_done_date = self.date_create BotText = BotText +' bezahlt' else: + client.contract_payment_done = False + client.contract_payment_done_date = '' BotText = BotText +' nicht bezahlt' client.client_invoices = [(4, entry.id)] else: + client=oldimport.contract if oldimport.is_payed: if (line[11]=="Ja"): _logger.info("Import Invoices - "+str(line[0])+' allready imported and payed - delete bevore import again !') @@ -95,6 +101,8 @@ class dssimportinvoicelist(models.Model): if (line[11]=="Ja"): oldimport.is_payed = True oldimport.is_payed_date = self.date_create + client.contract_payment_done = True + client.contract_payment_done_date = self.date_create BotText='Rechnung ['+str(line[0])+'] für '+str(line[1])+' ('+str(line[3])+') geändert in bezahlt !' _logger.info("Import Invoices - "+str(line[0])+' allready imported and not Payed - now Payed') else: diff --git a/models/dss_projects.py b/models/dss_projects.py index a97dedf..1146ef9 100755 --- a/models/dss_projects.py +++ b/models/dss_projects.py @@ -29,6 +29,8 @@ from dateutil.relativedelta import relativedelta from pyffmpeg import FFmpeg from tuya_iot import TuyaOpenAPI, TUYA_LOGGER from tuya_connector import TuyaOpenAPI, TUYA_LOGGER +from webdav4.client import Client +from webdav4.fsspec import WebdavFileSystem import sys TUYA_LOGGER.setLevel(logging.DEBUG) @@ -66,10 +68,16 @@ class dssprojects(models.Model): grundsystem_default_adstructure = fields.Many2one(related='grundsystemname.default_adstructure',tracking=True) grundsystemicon5050 = fields.Image(related='grundsystemname.icon_5050') grundsystem_ordner = fields.Char(related='grundsystemname.default_cloud_path') + grundsystem_default_cloud_structure_project = fields.Char(related='grundsystemname.default_cloud_structure_project') + grundsystem_default_cloud_structure_contract = fields.Char(related='grundsystemname.default_cloud_structure_contract') grundsystem_showonlinestate = fields.Boolean(related='grundsystemname.showonlinestate') grundsystem_showonlinestate_type = fields.Selection(related='grundsystemname.showonlinestate_type') + grundsystemicon_different = fields.Boolean('Grundsystem Icon anders',default=False,tracking=True) + grundsystemicon_different_image = fields.Binary('Anderes Icon',tracking=True) btntemplate = fields.Many2one('dss.display.templates',string='Buttonsvorlage',tracking=True) + btntemplate_displaytemplate_fullsize_w = fields.Integer(related='btntemplate.fullsize_w',string="Auflösung Breite",tracking=True) + btntemplate_displaytemplate_fullsize_h = fields.Integer(related='btntemplate.fullsize_h',string="Auflösung Höhe",tracking=True) standort = fields.Char('Beschreibung des Standortes') standort_strasse = fields.Char('Strasse des Projektes',tracking=True) @@ -111,6 +119,9 @@ class dssprojects(models.Model): zeitenf_off = fields.Float('Ausschaltzeit',tracking=True) zeiten_notiz = fields.Char('Schaltzeiten Notizen', tracking=True) errichtet_am = fields.Date('Errichtungstag',tracking=True) + cancel_am_in = fields.Date('Kündigung Insti - Eingang Kündigung',tracking=True) + cancel_am_to = fields.Date('Kündigung Insti - Kündigung zum',tracking=True) + finish_am = fields.Date('Beendigungstag',tracking=True) standort_inout = fields.Selection([('indoor','im Gebäude'), ('outdoor','Aussenbereich'), ('semiindoor','Überdachter Aussenbereich'),('Divers','Andere Art')],tracking=True) date_start_compute = fields.Date('Kalender Start intern',compute='_compute_calendar_start') @@ -423,13 +434,140 @@ class dssprojects(models.Model): else: _logger.info("UUID : "+str(uuid)+" not found") return False + + def getScreenViewData(self,domain): + ViewParams = {} + ViewParams.screensize_x=1980 + ViewParams.screensize_y=1024 + return ViewParams -def method(self): - return ( - self.env["confirmation.wizard"] - .with_context(hide_cancel=True) - .confirm_no_action_message( - message="Message", - title="Notification" - ) - ) \ No newline at end of file + def method(self): + return ( + self.env["confirmation.wizard"] + .with_context(hide_cancel=True) + .confirm_no_action_message( + message="Message", + title="Notification" + ) + ) + @api.model + def newwizzard(self): + _logger.info("Create new Project") + action = self.env["ir.actions.actions"]._for_xml_id("DigitalSignage.new_wizard_action") + action['context'] = {'default_state': 'start'} + + return action + + + +class dssprojects_new_wizard(models.TransientModel): + _name = "dss.projects.new.wizard" + _description = "DigitalSignage Projekte - Wizard" + #_inherit = ['mail.thread','mail.activity.mixin'] + _inherit = ['multi.step.wizard.mixin'] + _rec_name = "projectid" + + state = fields.Selection(selection='_selection_state', string='Status', default='start') + allow_back = fields.Boolean('Allow Back', default=False) + projectid = fields.Integer('Projekt ID', required=True) + projektname = fields.Char('Projektname', required=True) + name = fields.Char('Interner Name', required=True) + aktstatus = fields.Many2one('dss.projectstate',string='Aktueller Status:') + grundsystemname = fields.Many2one('dss.systemtypen', required=True) + grundsystemnameuuid = fields.Char(related='grundsystemname.uuid') + grundsystemicon = fields.Image(related='grundsystemname.icon') + grundsystem_default_adstructure = fields.Many2one(related='grundsystemname.default_adstructure') + grundsystem_ordner = fields.Char(related='grundsystemname.default_cloud_path') + isdifferendcouldstructure = fields.Boolean('Andere Cloud Struktur ?') + cloudgenerate = fields.Boolean('Cloud Struktur erzeugen ?') + differendcouldstructurefolder = fields.Char('Cloud Struktur') + kundenbeschreibung = fields.Char('Kundenbeschreibung') + run_uni_trigger = fields.Boolean('Allgemeine Trigger aktiv',default=True) + cloudlink = fields.Char('Cloud Verzeichnis',help='Verzeichnis für das Project innerhalb des Cloud Struktur') + + standort = fields.Char('Beschreibung des Standortes') + standort_strasse = fields.Char('Strasse des Projektes') + standort_plz = fields.Char('PLZ des Projektes') + standort_ort = fields.Char('Ort des Projektes') + standort_bundesland = fields.Many2one('res.country.state',string='Bundesland des Projektes') + standort_land = fields.Many2one('res.country',string='Land des Projektes') + + vertragsschreiber = fields.Many2one('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_vertrieb','=',True)]") + standortpartner = fields.Many2one('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_standort','=',True)]") + vertriebspartner = fields.Many2many('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_vertrieb','=',True)]") + project_grafiker = fields.Many2one('res.partner',domain="['&',('dssinternpartner','=',True),('dssinternpartner_grafik','=',True)]") + + @api.model + def _selection_state(self): + return [ + ('start', 'Start'), + ('configure', 'Configure'), + ('custom', 'Customize'), + ('final', 'Final'), + ] + + def open_next(self): + _logger.info("Open Next") +# if self.state == 'start': self.state = 'configure' +# elif self.state == 'configure': self.state = 'custom' +# elif self.state == 'custom': self.state = 'final' +# elif self.state == 'final': self.action_create_project() + self.action_create_project() + + def open_previous(self): + _logger.info("Open Previous") + if self.state == 'configure': + self.state = 'start' + elif self.state == 'custom': + self.state = 'configure' + elif self.state == 'final': + self.state = 'custom' + + def state_exit_start(self): + self.state = 'configure' + + def state_exit_configure(self): + self.state = 'custom' + + def state_exit_custom(self): + self.state = 'final' + + def _create_cloud_structure(self, newProjekt, isdifferendcouldstructure, differendcouldstructurefolder): + _logger.info("Create Cloud Structure for Project "+str(newProjekt.id)+" - "+str(newProjekt.cloudlink)) + if isdifferendcouldstructure: + cloudpath = str(differendcouldstructurefolder) + else: + cloudpath = str(newProjekt.grundsystem_default_cloud_structure_project) + + client = Client("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav")) + new_folder = dss_settings.dssSettings.getprojectpath(self,newProjekt) + _logger.info("Neuer Cloud Path : "+str(new_folder)) + try: + #client.mkdir(new_folder) + #_logger.info("Make Cloud Path : "+str(new_folder)) + if isdifferendcouldstructure: + _logger.info("Create Differend Cloud Structure for Project "+str(newProjekt.id)+" - "+str(newProjekt.cloudlink)) + client.copy(differendcouldstructurefolder+'/',new_folder) + _logger.info("Make Differend Cloud Path : "+str(new_folder+'/'+str(differendcouldstructurefolder))) + else: + _logger.info("Create Standard Cloud Structure for Project "+str(newProjekt.id)+" - "+str(newProjekt.cloudlink)) + client.copy(newProjekt.grundsystem_default_cloud_structure_project+'/',new_folder) + _logger.info("Make Standard Cloud Path : "+str(new_folder+'/'+str(newProjekt.grundsystem_default_cloud_structure_project))) + except Exception as e: + _logger.info("Make Cloud Path error : "+str(e)) + return True + + + def action_create_project(self): + _logger.info("Create Project") + newProjekt = self.env['dss.projects'].create({'projektname':self.projektname,'name':self.name,'aktstatus':self.aktstatus.id,'projectid':self.projectid,'grundsystemname':self.grundsystemname.id,'grundsystemnameuuid':self.grundsystemnameuuid,'grundsystemicon':self.grundsystemicon,'grundsystem_ordner':self.grundsystem_ordner,'grundsystem_default_adstructure':self.grundsystem_default_adstructure,'standort':self.standort,'standort_ort':self.standort_ort,'standort_plz':self.standort_plz,'standort_land':self.standort_land.id,'standort_bundesland':self.standort_bundesland.id,'standort_strasse':self.standort_strasse,'vertragsschreiber':self.vertragsschreiber.id,'standortpartner':self.standortpartner.id,'vertriebspartner': self.vertriebspartner.ids,'project_grafiker': self.project_grafiker.id,'short_partner_description':self.kundenbeschreibung}) + newProjekt.cloudlink = dss_settings.dssSettings.getprojectpath(self,newProjekt) + if newProjekt: + _logger.info("Project created with ID : "+str(newProjekt.id)) + if self.cloudgenerate: + _logger.info("Create Cloud Structure for Project "+str(newProjekt.id)+" - "+str(newProjekt.cloudlink)) + self._create_cloud_structure(newProjekt,self.isdifferendcouldstructure, self.differendcouldstructurefolder) + return True + + + \ No newline at end of file diff --git a/models/dss_settings.py b/models/dss_settings.py index 0555be9..e02a58a 100755 --- a/models/dss_settings.py +++ b/models/dss_settings.py @@ -68,7 +68,7 @@ class dssSettings(models.Model): settings = (self.env['dss.settings'].search([],limit=1)) wert = settings._origin.read([valuename])[0][valuename] return wert - + @api.model def _get_path_converted(self,path,record): alls = '' _logger.info("GetPath with " + str(path)+ " and Record : "+str(record.id)) @@ -158,6 +158,29 @@ class dssSettings(models.Model): myview.unlink() return 0 + @api.model + def getprojectpath(self,project): + _logger.info("Get Project Path for "+str(project.id)) + if project: + settings = (self.env['dss.settings'].search([],limit=1)) + alls = dssSettings._get_path_converted(self,settings.def_project_cloudpath,project) + _logger.info("Get Project Path - Ergebnis : " + str(alls)) + return alls + else: + _logger.info("Get Project Path - kein Projekt gefunden") + return '' + + @api.model + def getClientpath(self,client): + _logger.info("Get Client Path for "+str(client.id)) + if client: + settings = (self.env['dss.settings'].search([],limit=1)) + alls = dssSettings._get_path_converted(self,settings.def_contract_cloudpath,client) + _logger.info("Get Client Path - Ergebnis : " + str(alls)) + return alls + else: + _logger.info("Get Client Path - kein Client gefunden") + return '' class dssSettingsSave(models.Model): diff --git a/models/dss_systemtypen.py b/models/dss_systemtypen.py index 9fffa7f..4970f0f 100755 --- a/models/dss_systemtypen.py +++ b/models/dss_systemtypen.py @@ -41,7 +41,9 @@ class dsssystemtypen(models.Model): icon = fields.Image() icon_5050 = fields.Image("Icon 50",compute='_compute_icon_5050') default_adstructure = fields.Many2one('dss.adstructures',string='Standard-Werbeaufbau', tracking=True) - default_cloud_path = fields.Char('Standard Cloud Path', tracking=True) + default_cloud_path = fields.Char('Standard Cloud Pfad', tracking=True) + default_cloud_structure_project = fields.Char('Standard Cloud Projekt-Struktur (Pfad)', tracking=True) + default_cloud_structure_contract = fields.Char('Standard Cloud Kunden-Struktur (Pfad)', tracking=True) email_template_welcome = fields.Many2one('mail.template',string='Mailvorlage für Willkommen', tracking=True) email_template_zuarbeit = fields.Many2one('mail.template',string='Mailvorlage für Zuarbeiterrinnerung', tracking=True) email_template_abzug = fields.Many2one('mail.template',string='Mailvorlage für Korrekturabzug', tracking=True) diff --git a/models/dss_web_contracts.py b/models/dss_web_contracts.py index 6b18ca0..3ed78e4 100755 --- a/models/dss_web_contracts.py +++ b/models/dss_web_contracts.py @@ -83,6 +83,7 @@ class dsscontracts(models.Model): werbe_feld_tv = fields.Selection([('L-Banner','L-Banner'),('Countdown','Countdown')], 'Paket', tracking=True) werbe_feld_web = fields.Selection([('Standard','Standard'),('Premium','Premium')], 'Paket', tracking=True) zahlweise = fields.Selection([('einmalig','einmalig'),('jaehrlich','jährlich'),('sonder','Sonderzahlweise')], 'Zahlweise', tracking=True) + paymentinterval = fields.Many2one('dss.payintervals',string='Abrechnungsinterval',tracking=True) main_runtime = fields.Integer('Gesamtcliplänge',tracking=True) split_runtime_count = fields.Integer('Clip Teilungen',tracking=True) @@ -113,12 +114,14 @@ class dsscontracts(models.Model): tv_reach_PLZ = fields.Char('Reichweite PLZ',tracking=True) ads_radius_PLZ = fields.Integer('Umkreis PLZ in Km',tracking=True) - ads_count_perYear = fields.Selection([('30000','30.000'),('60000','60.000'),('120000','120.000'),('1000000','1.000.000')],'Einblendungen',tracking=True) -# ads_count_perYear_related = fields.Selection(related='dss.contracts.ads_count_perYear',tracking=True) + ads_count_perYear = fields.Selection([('30000','30.000'),('60000','60.000'),('120000','120.000'),('1000000','1.000.000')],'Einblendungen alt',tracking=True) + ads_count_perYear2 = fields.Integer('Einblendungen',tracking=True) +# ads_count_perYear_related_re = fields.Selection(related='dss.contracts.ads_count_perYear',tracking=True) ads_topic = fields.Selection([('auto','Auto'),('beauty','Beauty & Fashion'),('wirtschaft','Wirtschaft, Finanzen & News'),('food','Food'),('gesundheit','Gesundheit'),('lifestyle','Lifestyle'),('living','Living'),('entertainment','Entertainment'),('reise','Reise'),('technik','Technik'),('individuell','Individuell')],'Themen', tracking=True) ads_topics = fields.Many2many('dss.contracts_ads_topics', string='Themenliste', tracking=True) grafik_zuarbeitBis = fields.Date("Zuarbeit bis", tracking=True) grafikerstellung = fields.Boolean("Grafikerstellung Logumedia", tracking=True) + boarding = fields.Boolean("Boarding", tracking=True) scan_vertrag = fields.Binary('Datei') file_name = fields.Char(string='Dateiname') @@ -167,6 +170,7 @@ class dsscontracts(models.Model): 'contract_auto_id': self.contract_auto_id, 'contract_name': self.contract_name, 'contract_state': self.env['dss.contractstate'].search([("statusname","=","Angelegt")]).id, + 'paymentinterval': self.paymentinterval.id, 'werbe_feld_selected': self.werbe_feld_selected, 'client': self.client.id, 'client_short_vorname': self.client_short_vorname, @@ -179,7 +183,7 @@ class dsscontracts(models.Model): 'client_short_plz': self.client_short_plz, 'client_short_website': self.client_short_website, 'client_short_company': self.client_short_company, - 'ads_count_perYear': self.ads_count_perYear, + 'ads_count_perYear2': self.ads_count_perYear2, 'runtimesystem': self.runtimesystem, 'runtime_m': self.runtime_m, 'runtime_t': self.runtime_t, diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv index 39cc314..4fa90b3 100755 --- a/security/ir.model.access.csv +++ b/security/ir.model.access.csv @@ -1,5 +1,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink digitalsignage_dss_projects_group_user,access.dss.projects,model_dss_projects,base.group_user,1,1,1,1 +digitalsignage_dss_projects_new_wizard_group_user,access.dss.projects.new.wizard,model_dss_projects_new_wizard,base.group_user,1,1,1,1 digitalsignage_dss_systems_group_user,access.dss.systems,model_dss_systems,base.group_user,1,1,1,1 digitalsignage_dss_geraetetypen_group_user,access.dss.geraetetypen,model_dss_geraetetypen,base.group_user,1,1,1,1 digitalsignage_dss_systemtypen_group_user,access.dss.systemtypen,model_dss_systemtypen,base.group_user,1,1,1,1 diff --git a/static/src/js/dss_nextcloudwidget.js b/static/src/js/dss_nextcloudwidget.js new file mode 100755 index 0000000..85f5e27 --- /dev/null +++ b/static/src/js/dss_nextcloudwidget.js @@ -0,0 +1,448 @@ +/** @odoo-module **/ +import { registry } from "@web/core/registry"; +import { useBus, useService } from "@web/core/utils/hooks"; +import { useInputField } from "@web/views/fields/input_field_hook"; +import time from 'web.time'; + + +var translation = require('web.translation'); +var _t = translation._t; +const { Component,useRef} = owl; +var rpc = require('web.rpc') + +export class cloudFolderViewerField extends Component { + static template = 'FieldDateMultipleDate' + setup(){ + super.setup(); + this.input = useRef('inputdate') + this.rpc = useService('rpc') + window.input = useRef('inputpath') + this.input = useRef('inputpath') + window.this=this + useInputField({ getValue: () => this.props.value || "", refName: "inputpath" }); + if (this.props.value) { + this.readfiles(this.props.value); + } else { + this.readfiles(''); + } + window.oncontextmenu = function (ev) { + if (ev.target.classList.contains('FileExplorerFilesField')) { + var ele = ev.target.parentElement; + } else { + if (ev.target.classList.contains('Breadcrumb_Text')) { + var ele = ev.target.parentElement; + } else { + var ele = ev.target; + } + } + console.log(ele); + if (ele.classList.contains('FileExplorerFilesLine') || ele.classList.contains('Breadcrumb')) { + console.log(ele); + if ((ele.dataset.type == "Breadcrumb") || (ele.dataset.type == "Folder")) { + var MainBox = document.querySelector(".CloudfileBrowser"); + var contextBox = document.querySelector(".ContextFolderMenu"); + var FeldSelectBox = document.querySelector(".FieldSelectMenu"); + var CloudText = document.querySelector(".ContextCloudLinkMenuItem_text"); + contextBox.style.left = `${ev.clientX-ele.offsetLeft}px`; + contextBox.style.top = `${ev.layerY}px`; + FeldSelectBox.style.left = `${ev.clientX-ele.offsetLeft}px`; + FeldSelectBox.style.top = `${ev.pageY}px`; + contextBox.classList.add("visible"); + contextBox.classList.remove("hidden"); + CloudText.innerHTML = ""; + contextBox.dataset.file=ele.dataset.file; + CloudText.innerHTML = ele.dataset.file; + return false; // cancel default menu + } + if (ele.dataset.type == "File") { + var contextBox = document.querySelector(".ContextFileMenu"); + var FeldSelectBox = document.querySelector(".FieldSelectMenu"); + contextBox.style.left = `${ev.clientX-ele.offsetLeft}px`; + contextBox.style.top = `${ev.layerY}px`; + FeldSelectBox.style.left = `${ev.clientX-ele.offsetLeft}px`; + FeldSelectBox.style.top = `${ele.offsetTop}px`; + contextBox.classList.add("visible"); + contextBox.classList.remove("hidden"); + contextBox.dataset.file=ele.dataset.file; + return false; // cancel default menu + } + + } + return false; // cancel default menu + } + + } + + _onUploadClick(ev) { + var contextBox = document.querySelector(".ContextMenu"); + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + var ext = contextBox.dataset.file; + const toBase64 = file => new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => resolve(reader.result); + reader.onerror = reject; + }); + const fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.multiple = true; + fileInput.addEventListener('change', async (event) => { + const files = event.target.files; + if (files.length > 0) { + for (const file of files) { + try { + await rpc.query({ + route: '/my/webdav/upload', + params: { + path: ext || '/', + filename: file.name, + filedata: await toBase64(file), + }, + }); + alert(_t(`File "${file.name}" uploaded successfully.`)); + } catch (error) { + alert(_t(`Failed to upload file "${file.name}".`)); + } + } + this.readfiles(ext || '/'); + } + }); + fileInput.click(); + } + + _onSetCloudClick(ev) { + console.log(ev); + if (ev.target.classList.contains('FileExplorerFilesLine')) { + var ele = ev.target.parentElement; + } else { + if (ev.target.classList.contains('Breadcrumb_Text')) { + var ele = ev.target.parentElement; + } else { + if (ev.target.classList.contains('ContextMenuItem_text')) { + var ele = ev.target.parentElement.parentElement; + } else { + if (ev.target.classList.contains('ContextCloudLinkMenuItem_text')) { + var ele = ev.target.parentElement.parentElement; + } else { + var ele = ev.target; + } + } + } + } + console.log(ele); + if (confirm(_t("Folder selected : " + ele.dataset.file + "\nAre you sure you want to select this folder?"))) { + window.this.props.record.update({ [window.this.props.name]: '/'+ele.dataset.file }); + return false; + } + } + _onContextMenueMouseLeave(ev) { + var contextBox = document.querySelector(".ContextFileMenu"); + if (contextBox.dataset.file != undefined) { + contextBox.dataset.file = undefined; + } + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + var contextBox = document.querySelector(".ContextFolderMenu"); + if (contextBox.dataset.file != undefined) { + contextBox.dataset.file = undefined; + } + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + var contextBox = document.querySelector(".ContextMenu"); + if (contextBox.dataset.file != undefined) { + contextBox.dataset.file = undefined; + } + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + var FeldSelectBox = document.querySelector(".FieldSelectMenu"); + if (FeldSelectBox.dataset.file != undefined) { + FeldSelectBox.dataset.file = undefined; + } + FeldSelectBox.classList.remove("visible"); + FeldSelectBox.classList.add("hidden"); + } + + _onSetBtnImageClickField(ev) { + var FeldSelectBox = document.querySelector(".FieldSelectMenu"); + FeldSelectBox.classList.remove("visible"); + FeldSelectBox.classList.add("hidden"); + console.log(ev); + var ele = ev.target.parentElement; + console.log(ele); + var ext = ele.dataset.file; + console.log(ext); + console.log(ele.dataset.feldid); + //.split('.').pop().trim(); + console.log('/'+ext+'/'); + if (ext.match(/\.(jpg|jpeg|png|gif)$/i)) { + console.log('/'+ext+'/+'); + rpc.query({ + route: '/dss/setbtnfilefeld', + params: {contract: this.props.record.data.id, + filename: ele.dataset.file, + feldid: ele.dataset.feldid}, + }).then(success => { + console.log(success); + if (success != true) { + alert(_t("Error: " + success)); + } else { + alert(_t(" Erfolgreich zugewiesen !")); + } + + }) + } + } + + + _onSetBtnImageClick(ev) { + console.log(this.props.record.data.id); + var contextBox = document.querySelector(".ContextMenu"); + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + var ext = contextBox.dataset.file; + //.split('.').pop().trim(); + console.log('/'+ext+'/'); + if (ext.match(/\.(jpg|jpeg|png|gif)$/i)) { + console.log('/'+ext+'/+'); + rpc.query({ + route: '/dss/setbtnfile', + params: {contract: this.props.record.data.id, + filename: contextBox.dataset.file}, + }).then(success => { + console.log(success); + if (success != true) { + if (success.startsWith("MULTI")) { + var fields = success.split("/")[1] + var fieldIds = success.split("/")[2] + var FeldSelectBox = document.querySelector(".FieldSelectMenu"); + FeldSelectBox.classList.add("visible"); + FeldSelectBox.classList.remove("hidden"); + var FeldSelectBox = document.querySelector(".item0"); + if (FeldSelectBox != undefined) { + FeldSelectBox.parentNode.dataset.feldid = fieldIds; + FeldSelectBox.parentNode.dataset.feld = fields; + } + var Singlefields = fields.split(":"); + var Singlefieldids = fieldIds.split(":"); + var Nr = 0; + Singlefields.forEach(element => { + Nr += 1; + var FeldSelectBox = document.querySelector(".item"+Nr); + if (FeldSelectBox != undefined) { + FeldSelectBox.parentNode.classList.add("visible"); + FeldSelectBox.parentNode.classList.remove("hidden"); + FeldSelectBox.parentNode.dataset.feldid = Singlefieldids[Nr-1]; + FeldSelectBox.parentNode.dataset.feld = element; + FeldSelectBox.parentNode.dataset.file = ext; + FeldSelectBox.innerHTML = 'Auf Feld '+element+' zuweisen'; + FeldSelectBox.dataset.field = Singlefieldids[Nr-1]; + } + }); + } else { + alert(_t("Error: " + success)); + } + + } + }) + } + } + + _onMoveToArchivClick(ev) { + var contextBox = document.querySelector(".ContextMenu"); + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + alert('move to archive'); + } + + _onDownloadClick(ev) { + var contextBox = document.querySelector(".ContextMenu"); + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + alert('download'); + } + + _onDeleteClick(ev) { + var contextBox = document.querySelector(".ContextMenu"); + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + var filename = contextBox.dataset.file; + console.log(filename); + try { + rpc.query({ + route: '/my/webdav/deletefile', + params: { + filename: filename || '/', + }, + }).then(success => {; + console.log(success); + if (success != true) { + alert(_t("Error: " + success)); + } else { + alert(_t(" Datein "+filename+" Erfolgreich gelöscht !")); + } + $(".FileExplorerFilesBackground").html(""); + const parentPath = filename.substring(0, filename.lastIndexOf('/')); + console.log(filename); + console.log(parentPath); + this.readfiles(parentPath); + }); + } catch (error) { + console.error(error); + alert(_t(`Failed to delete file "${filename}".`)); + } + } + + _onMakeFolderClick(ev) { + var contextBox = document.querySelector(".ContextMenu"); + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + var filename = contextBox.dataset.file; + console.log(filename); + var foldername = prompt(_t("Folder name"), "New Folder"); + if (foldername == null) { + return false; + } + if (foldername == "") { + alert(_t("Error: Folder name is empty")); + return false; + } + try { + rpc.query({ + route: '/my/webdav/makefolder', + params: { + filename: filename || '/', + foldername: foldername, + }, + }).then(success => {; + console.log(success); + if (success != true) { + alert(_t("Error: " + success)); + } else { + alert(_t(" Ordner "+foldername+" Erfolgreich erstellt !")); + } + }); + } catch (error) { + console.error(error); + alert(_t(`Failed to create folder "${foldername}".`)); + } + $(".FileExplorerFilesBackground").html(""); + this.readfiles(filename); + } + + _onSelectDateField(ev) { + $(".FileExplorerFilesBackground").html(""); + this.readfiles(this.input.el.value); + } + + readfiles(path) { + $(".FileExplorerFilesBackground").html(""); + path = path.trim(); // Trim whitespace from the path + var prepath = path; + rpc.query({ + route: '/my/webdav/files', + params: {path: path}, + }).then(files => { + //container = ev.document.getElementById('FileExplorerFiles'); + //console.log(conatiner); + var etype = ""; + var myline =""; + if (path != "") { + var preprepath = prepath.substring(0, prepath.lastIndexOf('/')); + myline = "
"; + myline += "
Folder
"; + myline += "
..
"; + myline += "
-
"; + myline += "
-
"; + myline += "
"; + self.$('.FileExplorerFilesBackground').append(myline) + } + var breadcrumbox = document.querySelector(".Breadcrumb_Text"); + breadcrumbox.innerHTML=""; + breadcrumbox.innerHTML=prepath; + breadcrumbox = document.querySelector(".Breadcrumb"); + breadcrumbox.dataset.file=prepath; + files.forEach(element => { + myline=""; + if (element.type == "file") { + etype = "File" + } else { + etype = "Folder" + }; + if (path != "") { + var mypath = path.length; + if (path[0] == "/") { + mypath = mypath - 1; + } + var ename = element.name.slice(mypath+1); + } else { + var ename = element.name; + } + + myline += "
"; + myline += "
"+etype+"
"; + myline += "
"+ename+"
"; + myline += "
"+element.size+"
"; + myline += "
"+element.modified+"
"; + myline += "
"; + self.$('.FileExplorerFilesBackground').append(myline) + //container.appendChild(myline); + }); + }); + } + + _onFileclick(ev){ + this._onContextMenueMouseLeave(ev); + if (ev.target.classList.contains('FileExplorerFilesField')) { + var ele = ev.target.parentElement; + } else { + var ele = ev.target; + } + + if (ele.dataset.type == "Folder") { + $(".FileExplorerFilesBackground").html(""); + this.readfiles(ele.dataset.file); + } + + if (ele.dataset.type == "File") { + var ext = ele.dataset.file; + //.split('.').pop().trim(); + console.log('/'+ext+'/'); + if (ext.match(/\.(jpg|jpeg|png|gif)$/i)) { + console.log('/'+ext+'/+'); + rpc.query({ + route: '/my/webdav/getfile', + params: {path: ele.dataset.prepath, + filename: ele.dataset.fileonly}, + }).then(file64 => { + console.log(file64); + var contentbox = document.querySelector(".o_content"); + var imgelement = document.querySelector(".ImageShowContainerBlur"); + console.log(imgelement); + imgelement.classList.add("ImageShowContainerBlurVisible"); + imgelement.classList.remove("hidden"); + imgelement.classList.add("isvisible"); + var img = imgelement.querySelector(".ImageShow"); + img.src = "data:image/*;base64,"+file64; + contentbox.append(imgelement); + }); + }; + } + } + + _onImageClick(ev) { + var contentbox = document.querySelector(".o_content"); + var imgelement = document.querySelector(".ImageShowContainerBlurVisible"); + imgelement.classList.remove("isvisible"); + imgelement.classList.add("hidden"); + } + + _onCloseclick(ev) { + var contentbox = document.querySelector(".o_content"); + var imgelement = document.querySelector(".ImageShowContainerBlurVisible"); + imgelement.classList.remove("isvisible"); + imgelement.classList.add("hidden"); + } + +} +registry.category("fields").add("cloudFolderViewer", cloudFolderViewerField); \ No newline at end of file diff --git a/static/src/js/dss_nextcloudwidget_short.js b/static/src/js/dss_nextcloudwidget_short.js new file mode 100755 index 0000000..e1b49ce --- /dev/null +++ b/static/src/js/dss_nextcloudwidget_short.js @@ -0,0 +1,251 @@ +/** @odoo-module **/ +import { registry } from "@web/core/registry"; +import { useBus, useService } from "@web/core/utils/hooks"; +import { useInputField } from "@web/views/fields/input_field_hook"; +import time from 'web.time'; +import { configListController } from "./form_button"; + + +var translation = require('web.translation'); +var _t = translation._t; +const { Component,useRef} = owl; +var rpc = require('web.rpc') + +export class cloudFolderViewerFieldShort extends Component { + static template = 'cloudFolderViewerShort' + setup(){ + super.setup(); + this.input = useRef('inputdate') + this.rpc = useService('rpc') + this.id = Math.random().toString().slice(2, 6); // Generate a 4-digit random number as a string + this.insertid = false + window.input = useRef('inputpath'); + this.input = useRef('inputpath') + window. + window.this=this + useInputField({ getValue: () => this.props.value || "", refName: "inputpath" }); + + window.onmousedown = function (ev) { + if (ev.target.classList.contains('CloudfileBrowserShort_Input')) { + ev.target.innerHTML = ""; + const template = document.createElement('template'); + template.innerHTML = ` +
+ +
+
+
+
+
+ Typ +
+
+ Name +
+
+ Größe +
+
+ Datum +
+
+
+
+
+ + + `; + ev.target.parentElement.appendChild(template.content.cloneNode(true)); + if (this.props.value) { + this.readfiles(this.props.value); + } else { + this.readfiles(''); + } + } + } + + window.onmouseenter = function (ev) { + ev.target.add('hover'); + } + + window.oncontextmenu = function (ev) { + if (ev.target.classList.contains('FileExplorerFilesField_'+this.id)) { + var ele = ev.target.parentElement; + } else { + if (ev.target.classList.contains('Breadcrumb_Text')) { + var ele = ev.target.parentElement; + } else { + var ele = ev.target; + } + } + console.log(ele); + if (ele.classList.contains('FileExplorerFilesLine '+window.this.id) || ele.classList.contains('Breadcrumb '+window.this.id)) { + console.log(ele); + if ((ele.dataset.type == "Breadcrumb") || (ele.dataset.type == "Folder")) { + var MainBox = document.querySelector(".CloudfileBrowser ."+window.this.id); + var contextBox = document.querySelector(".ContextFolderMenu ."+window.this.id); + var CloudText = document.querySelector(".ContextCloudLinkMenuItem_text ."+window.this.id); + contextBox.style.left = `${ev.clientX-ele.offsetLeft}px`; + contextBox.style.top = `${ev.layerY}px`; + contextBox.classList.add("visible"); + contextBox.classList.remove("hidden"); + CloudText.innerHTML = ""; + contextBox.dataset.file=ele.dataset.file; + CloudText.innerHTML = ele.dataset.file; + return false; // cancel default menu + } + + } + return false; // cancel default menu + } + + } + + _onSetCloudClick(ev) { + console.log(ev); + if (ev.target.classList.contains('FileExplorerFilesLine '+window.this.id)) { + var ele = ev.target.parentElement; + } else { + if (ev.target.classList.contains('Breadcrumb_Text '+window.this.id)) { + var ele = ev.target.parentElement; + } else { + if (ev.target.classList.contains('ContextMenuItem_text')) { + var ele = ev.target.parentElement.parentElement; + } else { + if (ev.target.classList.contains('ContextCloudLinkMenuItem_text')) { + var ele = ev.target.parentElement.parentElement; + } else { + var ele = ev.target; + } + } + } + } + console.log(ele); + if (confirm(_t("Folder selected : " + ele.dataset.file + "\nAre you sure you want to select this folder?"))) { + window.this.props.record.update({ [window.this.props.name]: '/'+ele.dataset.file }); + return false; + } + } + _onContextMenueMouseLeave(ev) { + var contextBox = document.querySelector(".ContextFolderMenu"); + if (contextBox.dataset.file != undefined) { + contextBox.dataset.file = undefined; + } + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + var contextBox = document.querySelector(".ContextMenu"); + if (contextBox.dataset.file != undefined) { + contextBox.dataset.file = undefined; + } + contextBox.classList.remove("visible"); + contextBox.classList.add("hidden"); + } + + _onSelectDateField(ev) { + $(".FileExplorerFilesBackground_"+this.id).html(""); + this.readfiles(this.input.el.value); + } + + readfiles(path) { + if (this.insertid == false) { + var s = self.$(".CloudfileBrowserShort"); + console.log(s); + s.addClass("CloudfileBrowserShort_" + this.id); + this.insertid = true; + } +// $(".FileExplorerFilesBackground_"+this.id).html(""); + path = path.trim(); // Trim whitespace from the path + var prepath = path; + rpc.query({ + route: '/my/webdav/files', + params: {path: path}, + }).then(files => { + //container = ev.document.getElementById('FileExplorerFiles'); + //console.log(conatiner); + var etype = ""; + var myline =""; + if (path != "") { + var preprepath = prepath.substring(0, prepath.lastIndexOf('/')); + myline = "
"; + myline += "
Folder
"; + myline += "
..
"; + myline += "
-
"; + myline += "
-
"; + myline += "
"; + self.$('.FileExplorerFilesBackground').append(myline) + } + var breadcrumbox = document.querySelector(".Breadcrumb_Text ."+window.this.id); + breadcrumbox.innerHTML=""; + breadcrumbox.innerHTML=prepath; + breadcrumbox = document.querySelector(".Breadcrumb ."+window.this.id); + breadcrumbox.dataset.file=prepath; + files.forEach(element => { + myline=""; + if (element.type == "file") { + etype = "File" + } else { + etype = "Folder" + }; + if (path != "") { + var mypath = path.length; + if (path[0] == "/") { + mypath = mypath - 1; + } + var ename = element.name.slice(mypath+1); + } else { + var ename = element.name; + } + + myline += "
"; + myline += "
"+etype+"
"; + myline += "
"+ename+"
"; + myline += "
"+element.size+"
"; + myline += "
"+element.modified+"
"; + myline += "
"; + self.$('.FileExplorerFilesBackground '+window.this.id).append(myline) + //container.appendChild(myline); + }); + }); + } + + _onFileclick(ev){ + this._onContextMenueMouseLeave(ev); + if (ev.target.classList.contains('FileExplorerFilesField') && ev.target.classList.contains(window.this.id)) { + var ele = ev.target.parentElement; + } else { + var ele = ev.target; + } + + if (ele.dataset.type == "Folder") { + $(".FileExplorerFilesBackground "+window.this.id).html(""); + this.readfiles(ele.dataset.file); + } + + if (ele.dataset.type == "File") { + } + } + + _onImageClick(ev) { + var contentbox = document.querySelector(".o_content"); + var imgelement = document.querySelector(".ImageShowContainerBlurVisible"); + imgelement.classList.remove("isvisible"); + imgelement.classList.add("hidden"); + } + + _onCloseclick(ev) { + var contentbox = document.querySelector(".o_content"); + var imgelement = document.querySelector(".ImageShowContainerBlurVisible"); + imgelement.classList.remove("isvisible"); + imgelement.classList.add("hidden"); + } + +} +registry.category("fields").add("cloudFolderViewerShort", cloudFolderViewerFieldShort); \ No newline at end of file diff --git a/static/src/js/dss_screenview_archparser.js b/static/src/js/dss_screenview_archparser.js index f4e8b57..e9701ac 100755 --- a/static/src/js/dss_screenview_archparser.js +++ b/static/src/js/dss_screenview_archparser.js @@ -14,7 +14,6 @@ export class ScreenViewArchParser extends XMLParser { const fieldNextIds = {}; let autofocusFieldId = null; const activeFields = {}; - alert("begin") this.visitXML(xmlDoc, (node) => { if (node.tagName === "field") { alert('field') diff --git a/static/src/js/dss_screenview_controller.js b/static/src/js/dss_screenview_controller.js index df55263..55aa89e 100755 --- a/static/src/js/dss_screenview_controller.js +++ b/static/src/js/dss_screenview_controller.js @@ -3,60 +3,36 @@ import { Layout } from "@web/search/layout"; import { useBus, useService } from "@web/core/utils/hooks"; import { useModel } from "@web/views/model"; import { Component, onWillStart, useState} from "@odoo/owl"; +import { ScreenViewRenderer } from "./dss_screenview_renderer"; const { onRendered } = owl; export class ScreenViewController extends Component { setup() { - alert('setup') -/* this.orm = useService("orm"); + this.orm = useService("orm"); this.dialogService = useService("dialog"); this.router = useService("router"); this.user = useService("user"); this.viewService = useService("view"); this.ui = useService("ui"); - this.state = useState({ - isDisabled: false, - fieldIsDirty: false, - }); - useBus(this.ui.bus, "resize", this.render); + this.resModel = this.props.resModel + this.resDomain = this.props.domain +// useBus(this.ui.bus, "resize", this.render); + var Container = document.querySelector('.o_action_manager'); + var DarkPanel = '
'; + console.log(Container); + console.log(DarkPanel); + Container.insertAdjacentHTML('afterend', DarkPanel); + this.model = useState( + new this.props.Model( + this.orm, + this.props.resModel, + this.props.fields, + this.props.archInfo, + this.props.domain + ) + ); - this.archInfo = this.props.archInfo; - const activeFields = this.archInfo.activeFields; - - this.beforeLoadResolver = null; - const beforeLoadProm = new Promise((r) => { - this.beforeLoadResolver = r; - }); - - const { create, edit } = this.archInfo.activeActions; - this.canCreate = create && !this.props.preventCreate; - this.canEdit = edit && !this.props.preventEdit; - - let mode = this.props.mode || "edit"; - if (!this.canEdit) { - mode = "readonly"; - } - - this.model = useModel( - this.props.Model, - { - resModel: this.props.resModel, - resId: this.props.resId || false, - resIds: this.props.resIds, - fields: this.props.fields, - activeFields, - viewMode: "form", - rootType: "record", - mode, - beforeLoadProm, - component: this, - }, - { - ignoreUseSampleModel: true, - } - ); - */ // The controller create the model and make it reactive so whenever this.model is // accessed and edited then it'll cause a rerendering // this.model = useState( @@ -71,6 +47,7 @@ export class ScreenViewController extends Component { onWillStart(async () => { await this.model.load(); + }); onRendered(() => { @@ -78,11 +55,15 @@ export class ScreenViewController extends Component { }); } - displayName() { - return this.model.root.data.display_name || this.env._t("New"); + openView(domain, views, context) { + alert('openview'); } + + displayName() { + return "DigitalSignage Projekt Vertraege - ScreenView "; + } }; ScreenViewController.template = "dss.screenview"; -ScreenViewController.components = { Layout }; +ScreenViewController.components = { Layout, ScreenViewRenderer }; diff --git a/static/src/js/dss_screenview_injector.js b/static/src/js/dss_screenview_injector.js old mode 100644 new mode 100755 diff --git a/static/src/js/dss_screenview_model.js b/static/src/js/dss_screenview_model.js index 8975369..f6cb989 100755 --- a/static/src/js/dss_screenview_model.js +++ b/static/src/js/dss_screenview_model.js @@ -1,27 +1,111 @@ /** @odoo-module **/ +import { useService } from "@web/core/utils/hooks"; import { KeepLast } from "@web/core/utils/concurrency"; import { Model } from "@web/views/model"; -export class ScreenViewModel extends Model { - setup(params) { - // concurrency management +export class ScreenViewModel { + constructor(orm, resModel, fields, archInfo, domain) { + this.orm = orm; + this.resModel = resModel; + // We can access arch information parsed by the beautiful arch parser + const { fieldFromTheArch } = archInfo; + this.fieldFromTheArch = fieldFromTheArch; + this.fields = fields; + this.domain = domain; this.keepLast = new KeepLast(); - this.searchParams = { - context: {}, - domain: [], - domains: [], - groupBy: [], - }; - this.domain = [] } + // setup(params) { + // // concurrency management + // //alert(params.toString()); + // this.rpc = useService("rpc"); + // this.keepLast = new KeepLast(); + // this.resModel = params.resModel; + // this.resDomain = params.component.props.domain; + // this.searchParams = { + // context: {}, + // domain: [], + // domains: [], + // groupBy: [], + // }; + // this.params = params; + // this.domain = [] + // } async load() { - //The keeplast protect against concurrency call - alert('load') -// const { length, records } = await this.keepLast.add( -// this.orm.webSearchRead(this.resModel, this.domain, [this.fieldFromTheArch], {}) -// ); -// this.records = records; -// this.recordsLength = length; + //The keeplast protect against concurrency call + console.log(this); + await this.keepLast.add(this.loaddata(this)); //this.loaddata(records)); + console.log(this); + var element=document.querySelector('.o_dark_panel') + element.remove();; } + /** + * @protected + */ + + async loaddata(data) { + var newrecords = []; + var nullrecord = {}; + var x = 0; + const projectrecord = await this.orm.searchRead('dss.projects', [['id','=',this.domain[0][2]]], [],{}); + console.log('00- '+JSON.stringify(projectrecord)); + nullrecord.max_w=projectrecord[0].btntemplate_displaytemplate_fullsize_w; + console.log(projectrecord[0].btntemplate_displaytemplate_fullsize_w); + nullrecord.max_h=projectrecord[0].btntemplate_displaytemplate_fullsize_h; + console.log(projectrecord[0].btntemplate_displaytemplate_fullsize_h); + var width = window.innerWidth-140; + console.log(width); + var scale_faktor = (width / nullrecord.max_w); + var height = Math.round((nullrecord.max_h+40) * scale_faktor) ; + console.log(height); + nullrecord.scale = scale_faktor; + nullrecord.screenwidth = width + 40; + nullrecord.screenheight = height + 100; + nullrecord.key=1111; + nullrecord.id=1111; + newrecords[0] = nullrecord; + x=1; + const { length, records } = await this.orm.webSearchRead('dss.contracts', this.domain, [],{}); + for (const rawRecord of records) { + for (const feld of rawRecord.werbe_feld_selected) { + const feldrecords = await this.orm.searchRead('dss.advertisefields', [['id','=',feld],['is_btn','=',true]], [],{}); + if (feldrecords.length > 0) { + var frecord = {} + frecord.id=rawRecord.id+'_'+feldrecords[0].id; + frecord.werbe_feld_selected_btn_pos_x=feldrecords[0].btn_pos_x*scale_faktor; + frecord.werbe_feld_selected_btn_pos_y=feldrecords[0].btn_pos_y*scale_faktor ; + frecord.werbe_feld_selected_btn_pos_w=feldrecords[0].btn_pos_w*scale_faktor; + frecord.werbe_feld_selected_btn_pos_h=feldrecords[0].btn_pos_h*scale_faktor; + frecord.werbe_feld_selected_btn_img=feldrecords[0].btn_image_bin; + frecord.uuid = rawRecord.uuid; + frecord.contractid = rawRecord.id; + frecord.shortwerbe_feld_selected = feldrecords[0].btn_fieldname; + frecord.client_short_company = rawRecord.client_short_company; + frecord.client_short_name = rawRecord.client_short_name; + frecord.client_short_vorname = rawRecord.client_short_vorname; + frecord.client_short_strasse = rawRecord.client_short_strasse; + frecord.client_short_plz = rawRecord.client_short_plz; + frecord.client_short_ort = rawRecord.client_short_ort; + frecord.key=rawRecord.id+'_'+feldrecords[0].id; + newrecords[x] = frecord; + x++; + } + } + } + this.records = newrecords; + this.recordsLength = newrecords.length; + + } + + + async fetchrecords(length,data) { + //alert('fetchrecords') + alert(this.active_id) + const rawRecords = await this.orm.searchRead('dss.contracts', this.domain, []); + for (const rawRecord of rawRecords) { + records[rawRecord.id] = rawRecord; + } + return records; + } + } \ No newline at end of file diff --git a/static/src/js/dss_screenview_register.js b/static/src/js/dss_screenview_register.js index f0e5fb2..e4c9769 100755 --- a/static/src/js/dss_screenview_register.js +++ b/static/src/js/dss_screenview_register.js @@ -1,30 +1,45 @@ /** @odoo-module **/ -import AbstractView from "web.AbstractView"; -import BasicView from "web.BasicView"; -import view_registry from 'web.view_registry'; +import { registry } from "@web/core/registry"; import { ScreenViewModel } from "./dss_screenview_model"; import { ScreenViewController } from "./dss_screenview_controller"; import { ScreenViewRenderer } from "./dss_screenview_renderer"; +import { ScreenViewArchParser } from "./dss_screenview_archparser"; +import AbstractView from "web.AbstractView"; +import BasicView from "web.BasicView"; +import view_registry from 'web.view_registry'; import RendererWrapper from 'web.RendererWrapper'; -export const HelloWorldView = BasicView.extend({ - viewType: 'screenview', - config: _.extend({}, BasicView.prototype.config, { - Renderer: ScreenViewRenderer - }), +export const ScreenView = { + type: "screenview", - getRenderer(parent, state) { - // alert('getRenderer') - state = Object.assign({}, state, this.rendererParams); - return new RendererWrapper(null, this.config.Renderer, state); + display_name: "ScreenView ", + icon: "fa fa-picture-o", + multiRecord: true, + + ArchParser: ScreenViewArchParser, + Controller: ScreenViewController, + Model: ScreenViewModel, + Renderer: ScreenViewRenderer, + + props: (genericProps, view) => { + const { ArchParser } = view; + const { arch } = genericProps; + const archInfo = new ArchParser().parse(arch); + return { + ...genericProps, + Model: view.Model, + Renderer: view.Renderer, + archInfo, + }; }, -}); +}; -view_registry.add('screenview', HelloWorldView) +registry.category("views").add("screenview", ScreenView); +//view_registry.add('screenview', HelloWorldView) + +return ScreenView; -return HelloWorldView; -ScreenViewModel // /* // /** @odoo-module **/ diff --git a/static/src/js/dss_screenview_renderer.js b/static/src/js/dss_screenview_renderer.js index 08c3326..a0e0970 100755 --- a/static/src/js/dss_screenview_renderer.js +++ b/static/src/js/dss_screenview_renderer.js @@ -4,6 +4,7 @@ import { useEnv, Component, markup, onWillStart,onMounted,onWillUnmount, useRef, import { registry } from "@web/core/registry"; import { browser } from "@web/core/browser/browser"; +var rpc = require('web.rpc') export class ScreenViewRenderer extends Component { aktcontext = ""; @@ -11,16 +12,13 @@ export class ScreenViewRenderer extends Component { setup() { // alert('render '+JSON.stringify(this.props)) this.rpc = useService("rpc"); - //this.action = useService("action"); + this.action = useService("action"); this.env = useEnv(); onWillStart(async () => { await this.willStart(this.props) }); - -// this._onClickGlobal = this._handleClick.bind(this); -// onMounted(() => browser.addEventListener("click", this._onClickGlobal)); -// onWillUnmount(() => browser.removeEventListener("click", this._onClickGlobal)); + } async willStart(props) { @@ -28,106 +26,42 @@ export class ScreenViewRenderer extends Component { await this.render_Screen(props) } - // Event-Handler für den Click //_handleClick(event) { handleClick() { -// if (event.target.classList.contains("tooltip-container")) { + if (event.target.classList.contains("clickcontainer")) { console.log("Div clicked!", event.target); - this.rpc({ - model : 'dss.projects', - method: "go_contract", - args: [event.target.dataset.uuid] - }).then(function (action) { - alert(JSON.stringify(action)) - if (action.error) { - console.error(action.error); - } else { - this.action.doAction(action); - } - }) -// } - } - -/* this.rpc('/dss/gocontract',{ - id: event.target.dataset.uuid - }).then(function (action) { - alert(action) - if (action.error) { - console.error(action.error); - } else { - // Zugriff auf den actionService - const actionService = registry.category("services").get("action"); - actionService.do_action(action).catch((error) => { - console.error("Error executing action:", error); - }); - - } - }).catch((error) => { - console.error("Error fetching action:", error); + console.log(event.target.dataset.uuid); + console.log(event.target.dataset.id); + this.action.doAction({ + type: 'ir.actions.act_window', + res_model: 'dss.contracts', + res_id: parseInt(event.target.dataset.id), + resId: parseInt(event.target.dataset.id), + views: [[false, "form"]], + view_mode: "form", + target: "current", }); - alert("Div clicked!"); - */ - // Lifecycle-Methode: Wird aufgerufen, bevor die Komponente aus dem DOM entfernt wird + }} async render_Screen(props) { - var meins = ""; - var divele = ""; - var templates = [] - var templates = ['MainSection']; - -// document.addEventListener("click",_onclickevent) -// document.addEventListener("change",_onchangeevent) - - if (props.domain != []) { -// alert(' - '+props) - var def1 =this.rpc({ -// model: 'dss.advertisefields.templates', -// method: "get_data", - model: 'dss.projects', - method: "get_data", - args: [[props.context.active_id]], - }).then(function (result) { - var displaycss = 'background-color:#38AFA0;float:left;border-style: solid;border-width: 0.1px;' - const doelement = document.querySelector('.meincanvas') -// document.addEventListener("click",_onclickevent) - const rect = doelement.getBoundingClientRect(); - const topPosition = rect.top //+ window.scrollY; - var maxx = 1920 - var maxy = 1080 - var topstart = topPosition + 60 - var width = window.innerWidth-40; - var scale_faktor = (width / maxx) - var height = Math.round((maxy+40) * scale_faktor) - meins = '
' - if (result.length<2) { - if (result[0].error) { - alert(result[0].error); - } - } else { - result.forEach(element => { - var ele_pos_x=element.pos_x*scale_faktor+20 - var ele_pos_y=element.pos_y*scale_faktor+20//+topstart - var ele_pos_h=element.pos_h*scale_faktor - var ele_pos_w=element.pos_w*scale_faktor - divele = '
' - if (element.btn_image != '') { - divele += ''; - } - divele += '' - divele += '
'+element.feldname+'
' - divele += '
'+element.kunde_1+'
' - divele += '
'+element.kunde_2+'
' - divele += '
'+element.kunde_3+'
' - divele += '
'+element.kunde_4+'
' - divele += '
' - meins = meins + divele - }); - } - _.each(templates, function(template) {doelement.innerHTML= meins}); - }) - } - + var meins = ""; + var divele = ""; + var templates = [] + var templates = ['MainSection']; + console.log('1!!'+JSON.stringify(props)) + console.log(this); + console.log(this.max_h); + var maxx = props.records[0].max_w; + var maxy = props.records[0].max_h; + var width = window.innerWidth-140; + var scale_faktor = (width / maxx) + var height = Math.round((maxy+40) * scale_faktor) + props.screenwidth = width + 40 + props.scale = scale_faktor + props.screenheight = height + 100 + props.records.resId = false + console.log('1!! - '+props); } } diff --git a/static/src/js/dss_tagclick.js b/static/src/js/dss_tagclick.js new file mode 100755 index 0000000..015b2e1 --- /dev/null +++ b/static/src/js/dss_tagclick.js @@ -0,0 +1,47 @@ +/** @odoo-module **/ +import { _t } from 'web.core'; +import { useService } from "@web/core/utils/hooks"; +import { Many2ManyTagsFieldColorEditable } from "@web/views/fields/many2many_tags/many2many_tags_field"; +import { patch } from "@web/core/utils/patch"; +const Dialog = require('web.Dialog'); + +patch(Many2ManyTagsFieldColorEditable.prototype, '/DigitalSignage/static/src/js/dss_tagclick.js',{ + setup(){ + this._super.apply(this,arguments); + this.action = useService("action"); + }, + onBadgeClick(ev, record) { + var copytext = ev.target.innerText; + var buttons = [ + { + text: _t("Ok"), + classes: 'btn-primary', + close: true, + }, + ]; + new Dialog(self, { + size: 'medium', + buttons: [ + { + text: _t("Bearbeiten"), classes: 'btn-primary', close: true, + click: () => { + this.action.doAction({ + type: 'ir.actions.act_window', + res_model: this.props.relation, + res_id: record.data.id, + views: [[false, 'form']], + target: 'current', + }); + }, + }, + { + text: _t("Cancel"), close: true + }, + ], + $content: $('
', { + text: _t(" Feld bearbeiten ?"), + }), + }).open(); + return this._super.apply(this, arguments); + } + }) \ No newline at end of file diff --git a/static/src/js/kanban_button.js b/static/src/js/kanban_button.js index df5f169..0c5db4d 100755 --- a/static/src/js/kanban_button.js +++ b/static/src/js/kanban_button.js @@ -9,6 +9,7 @@ var rpc = require('web.rpc') export class configKanbanController extends KanbanController { setup() { super.setup(); + this.action = useService("action"); } SaveButtonClicked() { alert("") @@ -59,6 +60,26 @@ export class configKanbanController extends KanbanController { args: [], }); } + + newwizzard() { + const queryString = window.location.hash; + const urlParams = new URLSearchParams(queryString); + if (urlParams.get('model') == 'dss.projects') { + var action = rpc.query({ + model: 'dss.projects', + method: 'newwizzard', + args: [], + }); + } + if (urlParams.get('model') == 'dss.contracts') { + var action = rpc.query({ + model: 'dss.contracts', + method: 'newwizzard', + args: [urlParams.get('active_id')], + }); + } + this.action.doAction(action); + } } registry.category("views").add("button_in_kanban", { diff --git a/static/src/scss/dss_nextcloudwidget.scss b/static/src/scss/dss_nextcloudwidget.scss new file mode 100755 index 0000000..49d6a51 --- /dev/null +++ b/static/src/scss/dss_nextcloudwidget.scss @@ -0,0 +1,276 @@ +.datepicker-dropdown { + top: 0; + left: 0; + padding: 4px + } + + .FileExplorerBackground { + background-color: #5b5b5b; + border-color: #000000 ; + border-radius: 5px; + padding: 5px; + height: 400px + } + .FileExplorerHeaderBackground { + background-color: #3b3b3b; + border-color: #000000 ; + border-radius: 5px; + padding: 2px; + height: 35px; + width: 100%; + } + .FileExplorerHeader_fields { + background-color: #5b5bbb; + border-color: #000000 ; + border-radius: 5px; + padding: 5px; + float: left; + margin-left: 2px; + margin-right: 2px; + height: 100%; +} +.FileExplorerHeader_field_type { + width: 10%; +} +.FileExplorerHeader_field_name { + width: 40%; +} +.FileExplorerHeader_field_size { + width: 20%; +} +.FileExplorerHeader_field_date { + width: 27%; +} + +.header_field_type { + color: #fff; +} + +.header_field_name { + color: #fff; +} + +.header_field_size { + color: #fff; +} + +.header_field_date { + color: #fff; +} + +.FileExplorerFilesBackground { + background-color: #5b5b5b; + border-color: #000000 ; + border-radius: 5px; + padding: 5px; + height: 90%; + width: 100%; + overflow: auto; +} + +.FileExplorerFilesLine { + background-color: #3b3b3b; + border-color: #000000 ; + border-radius: 5px; + height: 20px; + width: 100%; +} + +.FileExplorerFilesLine:hover { + background-color: #5b5bbb; +} + +.FileExplorerFilesField { + white-space: nowrap; + overflow:hidden; + text-overflow: ellipsis; + color: #fff; + float: left; +} + +.FileExplorerFilesLineIcon { + padding-left: 2px; + width: 10%; +} + +.FileExplorerFilesLineName { + width: 40%; +} + +.FileExplorerFilesLineSize { + width: 20%; +} + +.FileExplorerFilesLineDate { + width: 27%; +} + +.ImageShowContainerBlur { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.ImageShowContainer_shadow { + background-color: #5b5bbb; + position: fixed; + width: 90%; + height: 90%; + top: 120px; + left: 5%; + /* for IE */ + opacity: 0.7; + box-shadow: 0 0 0 1000px rgba(0,0,0,.9); + /* for real browsers */ + box-shadow: 0 0 0 100vmax rgba(0,0,0,.9); + pointer-events: none; +} + +.ImageShowContainer_Header { + background-color: #FFFFFF; + position: fixed; + width: 100%; + height: 40px; + top: 0px; + left: 0px; +} + +.ImageShowContainer_Header_text { + color: #000; + font-size: 20px; + font-weight: bold; + padding-left: 10px; + padding-top: 10px; +} + +.ImageShowContainer { + background-color: #5b5bbb; + position: fixed; + width: 90%; + height: 90%; + top: 50px; + left: 5%; +} + +.ImageShowClose { + position: absolute; + top: 0px; + right: 0px; + background-color: #5b5bbb; + border-radius: 5px; + padding: 2px; + width: 40px; + height: 40px; + text-align: center; + font-size: 20px; + color: #fff; + font-weight: bold; +} + +.ImageShowClose:hover { + background-color: #8b8bbb; +} + +.ImageShowCloseIcon { + color: #fff; + font-size: 20px; +} +.hidden { + display: none; +} +.isvisible { + display: block; +} + +.visible { + display: block; +} + +.ImageShow { + position: relative; + width: 90%; + top: 10px; + left: 10px; +} + +.ContextMenu { + position: absolute; + background-color: #5b5bbb; + border-radius: 5px; + padding: 2px; + width: 200px; + height: auto; + z-index: 9999; +} +.ContextMenuItem { + background-color: #5b5bbb; +} +.ContextMenuItem:hover { + background-color: #8b8bbb; +} +.ContextMenuItem_text { + color: #fff; + font-size: 12px; + padding: 5px; +} + +.ContextMenuItemSeperator { + background-color: #5b5bbb; +} + +.ContextMenuItemSeperatorText { + color: #aaf; + font-size: 10px; + text-decoration: italic; +} + +.FieldSelectMenu { + position: absolute; + background-color: #5b5bbb; + border-radius: 5px; + padding: 2px; + width: 200px; + height: auto; + z-index: 9999; +} +.FieldSelectMenuItem { + background-color: #5b5bbb; +} +.FieldSelectMenuItem:hover { + background-color: #8b8bbb; +} +.FieldSelectMenuItem_text { + color: #fff; + font-size: 12px; + padding: 5px; +} +.FieldSelectMenuItemSeperator { + background-color: #5b5bbb; +} + +.ContextCloudLinkMenuItem_text { + color: #b9f; + font-size: 10px; + padding: -2px; + padding-left:5px; +} + +.BreadcrumbBackground { + background-color: #5b5b5b; + border-color: #000000 ; + border-radius: 5px; + padding: 2px; + padding-left:5px; + height: 25px +} + +.Breadcrumb { + +} + +.Breadcrumb_Text { + color: #b9f; + font-size: 12px; +} diff --git a/static/src/scss/style.scss b/static/src/scss/style.scss index 0a8f50e..1f0be57 100755 --- a/static/src/scss/style.scss +++ b/static/src/scss/style.scss @@ -95,4 +95,37 @@ -ms-transform: scale(1); transform: scale(1); } - \ No newline at end of file + + .screenview_main { + background-color:#000000; + padding:20px; + float:left; + } + + .screenview_field { + background-color:#38AFA0; + float:left; + border-style: solid; + border-width: 0.1px; + position:absolute; + } + + .screenview_image { + width:100%; + height:100%; + } + + .o_dark_panel { + background-color: #000000; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0.7; + z-index: 100; + } + + .hidden { + display: none; + } diff --git a/static/src/xml/dss_nextcloudwidget.xml b/static/src/xml/dss_nextcloudwidget.xml new file mode 100755 index 0000000..62eeab3 --- /dev/null +++ b/static/src/xml/dss_nextcloudwidget.xml @@ -0,0 +1,122 @@ + + +
+ + +
+
+
+ Typ +
+
+ Name +
+
+ Größe +
+
+ Datum +
+
+
+
+
+ + + + +
+
+
\ No newline at end of file diff --git a/static/src/xml/dss_nextcloudwidget_short.xml b/static/src/xml/dss_nextcloudwidget_short.xml new file mode 100755 index 0000000..d188b3a --- /dev/null +++ b/static/src/xml/dss_nextcloudwidget_short.xml @@ -0,0 +1,7 @@ + + +
+ +
+
+
\ No newline at end of file diff --git a/static/src/xml/dss_screenview_controller.xml b/static/src/xml/dss_screenview_controller.xml index 6381d3c..48a4053 100755 --- a/static/src/xml/dss_screenview_controller.xml +++ b/static/src/xml/dss_screenview_controller.xml @@ -4,7 +4,9 @@ -

Test

-
+
+

Scrollraum

+
+ \ No newline at end of file diff --git a/static/src/xml/dss_screenview_renderer.xml b/static/src/xml/dss_screenview_renderer.xml index bfbe299..d6092e2 100755 --- a/static/src/xml/dss_screenview_renderer.xml +++ b/static/src/xml/dss_screenview_renderer.xml @@ -2,8 +2,25 @@ - - +
+ + + + + + +
+ + +
+
+
+
+
+
+
+ +
\ No newline at end of file diff --git a/static/src/xml/form_button.xml b/static/src/xml/form_button.xml index 596ee1f..f0841a4 100755 --- a/static/src/xml/form_button.xml +++ b/static/src/xml/form_button.xml @@ -1,18 +1,14 @@ - -
+
+
+
+
+
+
+ + + + +
+ + + + + + + + + + + + + + + + @@ -138,8 +175,10 @@ - - + + + + @@ -179,7 +218,7 @@ action = records.check_contract_multi_Values() - + dss_advertisefields_fill ir.actions.act_window diff --git a/views/dss_advertisementfields_templates.xml b/views/dss_advertisementfields_templates.xml index 9d61110..9bdc8de 100755 --- a/views/dss_advertisementfields_templates.xml +++ b/views/dss_advertisementfields_templates.xml @@ -7,6 +7,7 @@ + diff --git a/views/dss_contracts.xml b/views/dss_contracts.xml index 3eaf541..f7a93f1 100755 --- a/views/dss_contracts.xml +++ b/views/dss_contracts.xml @@ -128,7 +128,7 @@ dss.contracts - + @@ -179,6 +179,18 @@ + + dss_project_contracts_kanban_inherit + dss.contracts + + + + button_in_kanban + + + + + DigitalSignage Projekt Vertraege ir.actions.act_window @@ -207,6 +219,15 @@