From 81f89a60f9343e89e892d681a88c5b183c413562 Mon Sep 17 00:00:00 2001 From: Andrew Yushev Date: Fri, 4 Mar 2022 11:06:44 +0300 Subject: [PATCH 01/72] Builder bug when selecting search field in View form dialog fixed --- jam/__init__.py | 2 +- jam/admin/builder.py | 18 +++++++++--------- jam/js/jam.js | 32 +++++++++++++++++--------------- jam/js/jam.min.js | 4 ++-- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/jam/__init__.py b/jam/__init__.py index 4526455..3ede76a 100644 --- a/jam/__init__.py +++ b/jam/__init__.py @@ -1,4 +1,4 @@ -__version__ = (5, 4, 116) +__version__ = (5, 4, 117) def version(): return '%s.%s.%s' % __version__ diff --git a/jam/admin/builder.py b/jam/admin/builder.py index d5c48b4..901141b 100644 --- a/jam/admin/builder.py +++ b/jam/admin/builder.py @@ -28,7 +28,7 @@ 'label_size': ['xSmall', 'Small', 'Medium', 'Large', 'xLarge'], 'group_type': consts.GROUP_TYPES } - + def get_value_list(str_list): result = [] for i, s in enumerate(str_list): @@ -65,17 +65,17 @@ def restore_caption_keys(task): def restore_keys(item): if hasattr(item, 'field_defs'): for field_def in item.field_defs: - field_def[FIELD_CAPTION] = item.__caption_keys[field_def[FIELD_NAME]] + field_def[FIELD_CAPTION] = item.__caption_keys[field_def[FIELD_NAME]] task.all(restore_keys) def change_language(task): - + def change_fields_lang(item): if hasattr(item, 'field_defs'): for field_def in item.field_defs: field_def[FIELD_CAPTION] = item.task.language(field_def[FIELD_CAPTION]) - + restore_caption_keys(task) consts.read_language() task.all(change_fields_lang) @@ -717,11 +717,11 @@ def server_save_edit(task, item_id, text, is_server): def set_server_modified(task): if task.item_name == 'admin': task.app.server_modified = True - + def set_client_modified(task): if task.item_name == 'admin': task.app.client_modified = True - + def server_file_info(task, file_name): result = {} file_path = file_name @@ -802,7 +802,7 @@ def server_can_delete_lookup_list(task, list_id): def server_valid_field_accept_value(task, accept): try: - get_ext_list(accept) + get_ext_list(accept) return True except: return False @@ -1169,7 +1169,7 @@ def upload_file(task, path, file_name, f): os.makedirs(dir_path) f.save(os.path.join(dir_path, file_name)) return path, file_name - + ############################################################################### # sys_items # @@ -1505,7 +1505,7 @@ def server_store_interface(item, id_value, info): item.open(fields=['id', 'f_info']) item._view_list = info['view_list'] item._edit_list = info['edit_list'] - item._order_list = info['order_list'] + item._order_list = info['order_list'] item._reports_list = info['reports_list'] item.store_interface() set_server_modified(item.task) diff --git a/jam/js/jam.js b/jam/js/jam.js index 46a7a40..06be99a 100644 --- a/jam/js/jam.js +++ b/jam/js/jam.js @@ -11801,22 +11801,24 @@ field = this.item.field_by_name(td.data('field_name')), $row = td.parent(); rec = this.record_by_row($row); - if (this.edit_mode && rec !== this.item.rec_no) { - if (!this.item.is_edited()) { - this.item.edit(); + if (rec !== undefined) { + if (this.edit_mode && rec !== this.item.rec_no) { + if (!this.item.is_edited()) { + this.item.edit(); + } + this.flush_editor(); + this.item.post(); + } + this.item.rec_no = rec; + if (!this.editing && !this.is_focused()) { + this.focus(); + } + if (field) { + this.set_selected_field(field); + } + if (e.type === "dblclick") { + this.do_on_edit(field); } - this.flush_editor(); - this.item.post(); - } - this.item.rec_no = rec; - if (!this.editing && !this.is_focused()) { - this.focus(); - } - if (field) { - this.set_selected_field(field); - } - if (e.type === "dblclick") { - this.do_on_edit(field); } }, diff --git a/jam/js/jam.min.js b/jam/js/jam.min.js index d526f58..f332aa2 100644 --- a/jam/js/jam.min.js +++ b/jam/js/jam.min.js @@ -1233,11 +1233,11 @@ if(html!==div.html()){div.html(html);if(this.item.record_count()<3&&(!this.item. if(!refreshingRow){this.update_selected(row);}}}}},update_selected:function(row){if(!row){row=this.row_by_record();} if(this.options.row_callback){this.options.row_callback(row,this.item);}},record_by_row:function(row){for(var i=0;i Date: Thu, 17 Mar 2022 13:07:05 +0300 Subject: [PATCH 02/72] in App builder help badge added to Field Editor Dialog when manual mode is set in App builder changing item name won't change item table name --- builder/admin.sqlite | Bin 476160 -> 476160 bytes builder/builder.sqlite | Bin 96256 -> 96256 bytes builder/js/app_builder.js | 11 ++++++----- jam/__init__.py | 2 +- jam/js/admin.js | 11 ++++++----- jam/js/admin.min.js | 6 +++--- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/builder/admin.sqlite b/builder/admin.sqlite index db0628afe00405748b1d296eb3e8c226cb74875e..c15fc256d6056e66e3d12ff0274caf130dddadde 100644 GIT binary patch delta 5635 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 I+ndDy0~`Ff<^TWy diff --git a/builder/builder.sqlite b/builder/builder.sqlite index 13020fae34ef154d6a108ada50f21f5cc927a882..1429752ae203d6d6bdfc06bb50fdf996b50caa51 100644 GIT binary patch delta 22 dcmZqpz}oPEb%Hb_??f4AM&8DRtqF_^$^l%&2e1GD delta 22 dcmZqpz}oPEb%Hb_&qNt#MxMrmtqF_^$^l%j2d)4B diff --git a/builder/js/app_builder.js b/builder/js/app_builder.js index 9a6f0c3..7e2bf99 100644 --- a/builder/js/app_builder.js +++ b/builder/js/app_builder.js @@ -1694,7 +1694,7 @@ function Events3() { // sys_items item = field.owner if (item.is_new() && item.type_id.value != item.task.item_types.DETAIL_TYPE) { if (field.field_name == 'f_item_name' && !item.f_virtual_table.value && - item.type_id.value !== item.task.item_types.ITEMS_TYPE) { + !task._manual_update && item.type_id.value !== item.task.item_types.ITEMS_TYPE) { names = item.task.server('get_new_table_name', field.value); item.f_table_name.value = names[0]; if (item.task.db_options.NEED_GENERATOR) { @@ -5338,13 +5338,14 @@ function Events26() { // app_builder.catalogs.sys_items.sys_fields } function on_edit_form_shown(item) { - var caption = 'Field Editor'; - + let caption = 'Field Editor', + link = task.help_badge('http://jam-py.com/docs/admin/items/field_editor_dialog.html'); if (item.f_field_name.value) { - item.edit_form.find('h4.modal-title').html(caption + ' ' + item.f_field_name.value + ''); + item.edit_form.find('h4.modal-title') + .html(caption + ' ' + item.f_field_name.value + '' + link); } else { - item.edit_form.find('h4.modal-title').html(caption); + item.edit_form.find('h4.modal-title').html(caption + link); } } diff --git a/jam/__init__.py b/jam/__init__.py index 3ede76a..7de3c2f 100644 --- a/jam/__init__.py +++ b/jam/__init__.py @@ -1,4 +1,4 @@ -__version__ = (5, 4, 117) +__version__ = (5, 4, 118) def version(): return '%s.%s.%s' % __version__ diff --git a/jam/js/admin.js b/jam/js/admin.js index 9731b1f..877afa9 100644 --- a/jam/js/admin.js +++ b/jam/js/admin.js @@ -1694,7 +1694,7 @@ function Events3() { // sys_items item = field.owner if (item.is_new() && item.type_id.value != item.task.item_types.DETAIL_TYPE) { if (field.field_name == 'f_item_name' && !item.f_virtual_table.value && - item.type_id.value !== item.task.item_types.ITEMS_TYPE) { + !task._manual_update && item.type_id.value !== item.task.item_types.ITEMS_TYPE) { names = item.task.server('get_new_table_name', field.value); item.f_table_name.value = names[0]; if (item.task.db_options.NEED_GENERATOR) { @@ -5338,13 +5338,14 @@ function Events26() { // app_builder.catalogs.sys_items.sys_fields } function on_edit_form_shown(item) { - var caption = 'Field Editor'; - + let caption = 'Field Editor', + link = task.help_badge('http://jam-py.com/docs/admin/items/field_editor_dialog.html'); if (item.f_field_name.value) { - item.edit_form.find('h4.modal-title').html(caption + ' ' + item.f_field_name.value + ''); + item.edit_form.find('h4.modal-title') + .html(caption + ' ' + item.f_field_name.value + '' + link); } else { - item.edit_form.find('h4.modal-title').html(caption); + item.edit_form.find('h4.modal-title').html(caption + link); } } diff --git a/jam/js/admin.min.js b/jam/js/admin.min.js index d294d2e..91c7465 100644 --- a/jam/js/admin.min.js +++ b/jam/js/admin.min.js @@ -230,7 +230,7 @@ else if(field.field_name==='f_primary_key'){if(!field.value&&!item.f_virtual_tab else if(field.field_name==='f_master_id'&&!item.task._manual_update&&item.is_new()){if(!field.value&&!item.f_virtual_table.value&&item.type_id.value===types.TABLE_TYPE){return item.task.language.value_required;}} else if(field.field_name==='f_master_rec_id'){if(!field.value&&!item.f_virtual_table.value&&item.type_id.value===types.TABLE_TYPE){return item.task.language.value_required;}}} function on_field_changed(field,lookup_item){var copy,ident,names,item=field.owner -if(item.is_new()&&item.type_id.value!=item.task.item_types.DETAIL_TYPE){if(field.field_name=='f_item_name'&&!item.f_virtual_table.value&&item.type_id.value!==item.task.item_types.ITEMS_TYPE){names=item.task.server('get_new_table_name',field.value);item.f_table_name.value=names[0];if(item.task.db_options.NEED_GENERATOR){item.f_gen_name.value=names[1];}} +if(item.is_new()&&item.type_id.value!=item.task.item_types.DETAIL_TYPE){if(field.field_name=='f_item_name'&&!item.f_virtual_table.value&&!task._manual_update&&item.type_id.value!==item.task.item_types.ITEMS_TYPE){names=item.task.server('get_new_table_name',field.value);item.f_table_name.value=names[0];if(item.task.db_options.NEED_GENERATOR){item.f_gen_name.value=names[1];}} if(field.field_name==='f_name'&&!item.f_item_name.value){try{ident=field.text.split(' ').join('_');ident=ident.toLowerCase();if(valid_identifier(ident)){item.f_item_name.value=ident;}} catch(e){}}} if(field.field_name==='f_deleted_flag'){if(field.value){item.f_soft_delete.read_only=false;item.f_soft_delete.value=true;} @@ -712,8 +712,8 @@ else if(item.f_data_type.value===item.task.consts.FILE){item.edit_form.find("#in else if(item.f_data_type.value===item.task.consts.IMAGE){item.edit_form.find("#interface").hide();item.edit_form.find("#text-interface").hide();item.edit_form.find("#image-interface").show();item.edit_form.find("#file-interface").hide();if(item.is_changing()){if(!item.f_image_view_width.value&&!item.f_image_view_height.value){item.f_image_view_width.value=100;} if(!item.f_image_edit_width.value&&!item.f_image_edit_height.value){item.f_image_edit_width.value=200;}}} else{item.edit_form.find("#interface").show();item.edit_form.find("#text-interface").hide();item.edit_form.find("#image-interface").hide();item.edit_form.find("#file-interface").hide();}} -function on_edit_form_shown(item){var caption='Field Editor';if(item.f_field_name.value){item.edit_form.find('h4.modal-title').html(caption+' '+item.f_field_name.value+'');} -else{item.edit_form.find('h4.modal-title').html(caption);}} +function on_edit_form_shown(item){let caption='Field Editor',link=task.help_badge('http://jam-py.com/docs/admin/items/field_editor_dialog.html');if(item.f_field_name.value){item.edit_form.find('h4.modal-title').html(caption+' '+item.f_field_name.value+''+link);} +else{item.edit_form.find('h4.modal-title').html(caption+link);}} function on_after_open(item){item._old_fields={} item.disable_controls();try{item.each(function(i){item._old_fields[i.id.value+'']=true;})}finally{item.first() item.enable_controls();}} From 2e4d450fe94b67a3e75783d67f5ddd82dcdce91b Mon Sep 17 00:00:00 2001 From: Andrew Yushev Date: Mon, 21 Mar 2022 14:03:05 +0300 Subject: [PATCH 03/72] Range of records can be selected in the jam.py tables using ShiftKey --- jam/__init__.py | 2 +- jam/js/jam.js | 23 +++++++++++++++++++++++ jam/js/jam.min.js | 8 ++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/jam/__init__.py b/jam/__init__.py index 7de3c2f..ae0d6cb 100644 --- a/jam/__init__.py +++ b/jam/__init__.py @@ -1,4 +1,4 @@ -__version__ = (5, 4, 118) +__version__ = (5, 4, 119) def version(): return '%s.%s.%s' % __version__ diff --git a/jam/js/jam.js b/jam/js/jam.js index 06be99a..2ed637c 100644 --- a/jam/js/jam.js +++ b/jam/js/jam.js @@ -10706,6 +10706,28 @@ self.clicked(e, $this.closest('td')); self.selections_set_selected(!checked); $this.prop('checked', self.selections_get_selected()); + if (e.shiftKey && self.prev_selected_rec_no !== undefined) { + let sels = [], + clone = self.item.clone(), + min = self.prev_selected_rec_no, + max = self.item.rec_no; + if (self.prev_selected_rec_no > self.item.rec_no) { + min = self.item.rec_no; + max = self.prev_selected_rec_no; + } + while (min < max) { + min += 1; + clone.rec_no = min; + if ($this.is(':checked')) { + self.item.selections.add(clone._primary_key_field.value); + } + else { + self.item.selections.remove(clone._primary_key_field.value); + } + } + self.refresh(); + } + self.prev_selected_rec_no = self.item.rec_no; }); this.$table.on('click', 'td input.multi-select', function(e) { @@ -11561,6 +11583,7 @@ do_after_open: function() { var self = this; + this.prev_selected_rec_no = undefined; if (this.$table.is(':visible')) { this.init_table(); this.sync_freezed(); diff --git a/jam/js/jam.min.js b/jam/js/jam.min.js index f332aa2..eac9855 100644 --- a/jam/js/jam.min.js +++ b/jam/js/jam.min.js @@ -1098,7 +1098,11 @@ else{self.next_record();}});this.$table.on('click','td',function(e){if(self.opti if(show){self.remove_tooltip();container=self.$element[0];if(Math.abs(this.offsetHeight-this.scrollHeight)>1||Math.abs(this.offsetWidth-this.scrollWidth)>1){let table_width=self.$table.width();if(self.master_table){table_width=self.master_table.$table.width();container=self.master_table.$element[0];} if(table_width-($this.offset().left+$this.width())<200){placement='left';} $td.tooltip({'placement':placement,'container':container,'title':$this.text()}).on('hide hidden show shown',function(e){if(e.target===$this.get(0)){e.stopPropagation()}}).eq(0).tooltip('show');try{$td.data('tooltip').$tip.addClass('table-tooltip');} -catch(e){}}}});this.$table.on('mousedown','td input.multi-select',function(e){var $this=$(this),checked=$this.is(':checked');self.clicked(e,$this.closest('td'));self.selections_set_selected(!checked);$this.prop('checked',self.selections_get_selected());});this.$table.on('click','td input.multi-select',function(e){var $this=$(this);e.stopPropagation();e.preventDefault();$this.prop('checked',self.selections_get_selected());});this.$element.on('click','input.multi-select-header',function(e){self.selections_set_all_selected($(this).is(':checked'));});this.$table.attr("tabindex",this.options.tabindex);this.initKeyboardEvents();this.$element.on('mousemove.grid-title','table.outer-table thead tr:first th',function(e){var $this=$(this),field_name=$this.data('field_name'),lastCell=self.$element.find("thead tr:first th:last").get(0);if($this.outerWidth()-e.offsetX<8&&!mouseX&&(this!==lastCell||self.master_table)){$this.css('cursor','col-resize');}else if(self.options.sortable&&(!self.options.sort_fields.length||self.options.sort_fields.indexOf(field_name)!==-1)){$this.css('cursor','pointer');}else{$this.css('cursor','default');}});function captureMouseMove(e){var newDelta=delta+e.screenX-mouseX,left=parseInt($selection.css("left"),10);if(mouseX){e.preventDefault();if(newDelta>-($th.innerWidth()-30)){delta=newDelta;$selection.css('left',left+e.screenX-mouseX);} +catch(e){}}}});this.$table.on('mousedown','td input.multi-select',function(e){var $this=$(this),checked=$this.is(':checked');self.clicked(e,$this.closest('td'));self.selections_set_selected(!checked);$this.prop('checked',self.selections_get_selected());if(e.shiftKey&&self.prev_selected_rec_no!==undefined){let sels=[],clone=self.item.clone(),min=self.prev_selected_rec_no,max=self.item.rec_no;if(self.prev_selected_rec_no>self.item.rec_no){min=self.item.rec_no;max=self.prev_selected_rec_no;} +while(min-($th.innerWidth()-30)){delta=newDelta;$selection.css('left',left+e.screenX-mouseX);} mouseX=e.screenX;}} function change_field_width($title,delta){var field_name=$title.data('field_name');self.change_field_width(field_name,delta);} function release_mouse_move(e){var field_name,$td,$tf,cell_width;$doc.off("mousemove.grid-title");$doc.off("mouseup.grid-title");change_field_width($th,delta);mouseX=undefined;$selection.remove()} @@ -1212,7 +1216,7 @@ cell=$('').append(div);footer.append(cell) footer.append(' Date: Mon, 16 May 2022 19:38:49 +0300 Subject: [PATCH 04/72] 1. changes from unofficial 5.4.117 release added connection parameter added to the open server method: open(self, options=None, expanded=None, fields=None, where=None, order_by=None, open_empty=False, params=None, offset=None, limit=None, funcs=None, group_by=None, safe=False, connection=None) If the connection is set to None, the application creates a connection, executes an SQL SELECT query using it, and then closes it, otherwise it uses the connection to execute the query. 2. bug when deleting a record with details from imported database fixed. --- jam/__init__.py | 2 +- jam/dataset.py | 16 +++++------ jam/server_classes.py | 67 +++++++++++++++++++++++++++++-------------- jam/sql.py | 1 - 4 files changed, 54 insertions(+), 32 deletions(-) diff --git a/jam/__init__.py b/jam/__init__.py index ae0d6cb..fd9df58 100644 --- a/jam/__init__.py +++ b/jam/__init__.py @@ -1,4 +1,4 @@ -__version__ = (5, 4, 119) +__version__ = (5, 4, 120) def version(): return '%s.%s.%s' % __version__ diff --git a/jam/dataset.py b/jam/dataset.py index b3fa564..a2fc24f 100644 --- a/jam/dataset.py +++ b/jam/dataset.py @@ -1262,7 +1262,7 @@ def rec_count(self): def record_count(self): return self.rec_count - def do_internal_open(self): + def do_internal_open(self, params, connection): pass def find_rec_info(self, rec_no=None, record=None): @@ -1467,7 +1467,7 @@ def _do_before_open(self, expanded, fields, where, order_by, open_empty, self._open_params = params def open(self, expanded, fields, where, order_by, open_empty, params, - offset, limit, funcs, group_by): + offset, limit, funcs, group_by, connection): if not params: params = {} self._do_before_open(expanded, fields, where, order_by, open_empty, @@ -1476,16 +1476,16 @@ def open(self, expanded, fields, where, order_by, open_empty, params, self._bind_fields(expanded) self._dataset = [] if not open_empty: - self.do_open(params) + self.do_open(params, connection) self._active = True # ~ self.__cur_row = None self.item_state = consts.STATE_BROWSE self.first() - def do_open(self, params=None): + def do_open(self, params=None, connection=None): if not params: params = self._open_params - rows, error_mes, info = self.do_internal_open(params) + rows, error_mes, info = self.do_internal_open(params, connection) if error_mes: raise RuntimeError(error_mes) else: @@ -1786,7 +1786,7 @@ def find_change_log(self): def open(self, options=None, expanded=None, fields=None, where=None, order_by=None, open_empty=False, params=None, offset=None, limit=None, funcs=None, - group_by=None, safe=False): + group_by=None, safe=False, connection=None): if safe and not self.can_view(): raise Exception(consts.language('cant_view') % self.item_caption) if options and type(options) == dict: @@ -1843,13 +1843,13 @@ def open(self, options=None, expanded=None, fields=None, where=None, order_by=No params['__master_rec_id'] = self.master.field_by_name(self.master._primary_key).value return super(MasterDetailDataset, self).open(expanded, fields, where, order_by, open_empty, params, offset, - limit, funcs, group_by) + limit, funcs, group_by, connection) else: return else: return super(MasterDetailDataset, self).open(expanded, fields, where, order_by, open_empty, params, offset, limit, - funcs, group_by) + funcs, group_by, connection) def open__in(self, ids, expanded=None, fields=None, where=None, order_by=None, open_empty=False, params=None, offset=None, limit=None): #depricated diff --git a/jam/server_classes.py b/jam/server_classes.py index 2f91031..efcb0d1 100644 --- a/jam/server_classes.py +++ b/jam/server_classes.py @@ -98,8 +98,8 @@ def create_filters(self, info): for filter_def in info: self.add_filter(*filter_def) - def do_internal_open(self, params): - return self.select_records(params) + def do_internal_open(self, params, connection): + return self.select_records(params, connection) def do_apply(self, params=None, safe=False, connection=None): if not self.master and self.log_changes: @@ -157,17 +157,20 @@ def get_version(self, locks, item_id): return 1 def execute_open(self, params, connection=None, db_module=None): + autocommit = True + if connection: + autocommit = False error_mes = '' limit = params['__limit'] offset = params['__offset'] sqls = self.get_select_queries(params, db_module) if len(sqls) == 1: - rows = self.task.select(sqls[0], connection, db_module) + rows = self.task.select(sqls[0], connection, db_module, autocommit) else: rows = [] cut = False for sql in sqls: - rows += self.task.select(sql, connection, db_module) + rows += self.task.select(sql, connection, db_module, autocommit) if limit or offset: if len(rows) >= offset + limit: rows = rows[offset:offset + limit] @@ -177,7 +180,7 @@ def execute_open(self, params, connection=None, db_module=None): rows = rows[offset:offset + limit] return rows, error_mes - def select_records(self, params, safe=False): + def select_records(self, params, connection=None, safe=False): if safe and not self.can_view(): raise Exception(consts.language('cant_view') % self.item_caption) params['__client_request'] = safe @@ -187,7 +190,7 @@ def select_records(self, params, safe=False): if result is None and self.on_open: result = self.on_open(self, params) if result is None: - result = self.execute_open(params) + result = self.execute_open(params, connection) result = list(result) result.append(self.find_rec_version(params)) return result @@ -213,11 +216,33 @@ def update_rec_version(self, delta, params, connection): locks.apply(connection) return locks.version.value + def update_delta(self, delta, update): + changes = update['changes'] + indexes = {} + for i, change in enumerate(changes): + indexes[str(change['log_id'])] = i + for d in delta: + log_id = d.get_rec_info()[consts.REC_CHANGE_ID] + index = indexes.get(str(log_id)) + change = changes[index] + rec_id = change['rec_id'] + d.edit() + d.id.value = rec_id + details = change['details'] + for detail in d.details: + for detail_update in details: + if detail.ID == int(detail_update['ID']): + self.update_delta(detail, detail_update) + d.post() + def apply_delta(self, delta, params=None, connection=None, db_module=None): if not db_module: db_module = self.task.db_module sql = delta.apply_sql(params) - return self.task.execute(sql, None, connection=connection, db_module=db_module, autocommit=False) + updates, error = self.task.execute(sql, None, connection=connection, db_module=db_module, autocommit=False) + if not error: + self.update_delta(delta, updates) + return updates, error def apply_changes(self, data, safe, connection=None): result = None @@ -818,27 +843,25 @@ def connect(self): self.app.create_connection_pool() return self.pool.connect() - def pool_execute(self, command, params=None, select=False): - con = self.connect() - try: - connection, result = execute_sql_connection(con, command, params, select, self.db_module) - finally: - con.close() - return result - def execute(self, command, params=None, connection=None, db_module=None, \ select=False, autocommit=True): if connection: - connection, result = execute_sql_connection(connection, command, \ - params, select, db_module, autocommit=autocommit) - elif self.persist_con: - result = self.pool_execute(command, params, select) + con = connection else: - result = self.pool_execute(command, params, select) + con = self.connect() + if not db_module: + db_module = self.db_module + try: + c, result = execute_sql_connection(con, command, params, select, \ + db_module, autocommit=autocommit) + finally: + if not connection: + con.close() return result - def select(self, command, connection=None, db_module=None): - result, error = self.execute(command, None, connection, db_module, select=True) + def select(self, command, connection=None, db_module=None, autocommit=True): + result, error = self.execute(command, None, connection, db_module, \ + select=True, autocommit=autocommit) if error: raise Exception(error) else: diff --git a/jam/sql.py b/jam/sql.py index 0fd9f72..d009eb5 100644 --- a/jam/sql.py +++ b/jam/sql.py @@ -156,7 +156,6 @@ def delete_detail_sql(item, detail, db_module): else: sql = 'DELETE FROM "%s" WHERE "%s" = %s' % \ (detail.table_name, detail._master_rec_id_db_field_name, id_literal) - h_sql, h_params, h_del_details = get_history_sql(detail, db_module) return sql, None, None, h_sql, h_params, h_del_details def get_history_sql(item, db_module): From 0d3862f75d55c505f4f56a95d6e430178ef103c4 Mon Sep 17 00:00:00 2001 From: Andrew Yushev Date: Tue, 24 May 2022 13:06:27 +0300 Subject: [PATCH 05/72] Docs syntax errors reported by Drazen Babic fixed --- docs/_static/jquery.js | 16 ++++++++-------- .../admin/intergation_with_existing_database.txt | 2 +- docs/faq/faq_using_other_libraries.txt | 2 +- docs/programming/data/fields.txt | 2 +- docs/programming/data/filtering_records.txt | 4 ++-- docs/programming/data/modifying_datasets.txt | 2 +- docs/programming/interface/form_exapmles.txt | 4 ++-- docs/programming/interface/form_templates.txt | 2 +- docs/programming/interface/forms.txt | 2 +- docs/programming/interface/index.txt | 2 +- docs/programming/interface/index_html.txt | 2 +- docs/programming/server/index.txt | 2 +- docs/programming/task_tree.txt | 4 ++-- docs/programming/workflow.txt | 8 ++++---- docs/refs/client/abstr_item/at_id.txt | 2 +- docs/refs/client/item/m_insert_record.txt | 2 +- docs/refs/server/abstr_item/at_id.txt | 2 +- docs/releases/version 5/version_5_3_1.txt | 4 ++-- jam/__init__.py | 2 +- 19 files changed, 33 insertions(+), 33 deletions(-) diff --git a/docs/_static/jquery.js b/docs/_static/jquery.js index eed1777..125695d 100644 --- a/docs/_static/jquery.js +++ b/docs/_static/jquery.js @@ -3169,7 +3169,7 @@ jQuery.Callbacks = function( options ) { return this; }, // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. + // If no argument is given, return whether or not list has callbacks attachd. has: function( fn ) { return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); }, @@ -4783,23 +4783,23 @@ if ( !support.focusinBubbles ) { jQuery.event.special[ fix ] = { setup: function() { var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ); + attachs = data_priv.access( doc, fix ); - if ( !attaches ) { + if ( !attachs ) { doc.addEventListener( orig, handler, true ); } - data_priv.access( doc, fix, ( attaches || 0 ) + 1 ); + data_priv.access( doc, fix, ( attachs || 0 ) + 1 ); }, teardown: function() { var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ) - 1; + attachs = data_priv.access( doc, fix ) - 1; - if ( !attaches ) { + if ( !attachs ) { doc.removeEventListener( orig, handler, true ); data_priv.remove( doc, fix ); } else { - data_priv.access( doc, fix, attaches ); + data_priv.access( doc, fix, attachs ); } } }; @@ -5485,7 +5485,7 @@ function actualDisplay( name, doc ) { var style, elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), - // getDefaultComputedStyle might be reliably used only on attached element + // getDefaultComputedStyle might be reliably used only on attachd element display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? // Use of this method is a temporary fix (more like optimization) until something better comes along, diff --git a/docs/admin/intergation_with_existing_database.txt b/docs/admin/intergation_with_existing_database.txt index e2be6b3..006fa72 100644 --- a/docs/admin/intergation_with_existing_database.txt +++ b/docs/admin/intergation_with_existing_database.txt @@ -30,7 +30,7 @@ You can use Jam.py with existing database, that is supported by the framework. You can import a subset of fields in the table. Before saving, specify the primary key field for the item and generator name, - if nessesary. + if necessary. * After saving the imported item, go to the project page and check how it is displayed. diff --git a/docs/faq/faq_using_other_libraries.txt b/docs/faq/faq_using_other_libraries.txt index b5dcdd4..50d3eaa 100644 --- a/docs/faq/faq_using_other_libraries.txt +++ b/docs/faq/faq_using_other_libraries.txt @@ -4,7 +4,7 @@ Can I use other libraries in my application You can add javascript libraries to use them for programming on the client side. -It is better to place them in the *js* folders of the *static* dicrectory of the +It is better to place them in the *js* folders of the *static* directory of the project. And refer to them using the src attribute in the