djgentelella 0.4.30__py3-none-any.whl → 0.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. djgentelella/__init__.py +4 -1
  2. djgentelella/admin.py +41 -2
  3. djgentelella/firmador_digital/consumers/sign.py +24 -3
  4. djgentelella/firmador_digital/forms.py +140 -0
  5. djgentelella/firmador_digital/models.py +19 -24
  6. djgentelella/firmador_digital/utils.py +11 -0
  7. djgentelella/firmador_digital/views.py +31 -0
  8. djgentelella/firmador_digital/viewsets.py +15 -4
  9. djgentelella/forms/forms.py +10 -2
  10. djgentelella/groute.py +4 -1
  11. djgentelella/history/api.py +145 -0
  12. djgentelella/history/filterset.py +23 -0
  13. djgentelella/history/serializers.py +50 -0
  14. djgentelella/history/utils.py +70 -0
  15. djgentelella/locale/es/LC_MESSAGES/django.mo +0 -0
  16. djgentelella/locale/es/LC_MESSAGES/django.po +105 -0
  17. djgentelella/locale/es/LC_MESSAGES/djangojs.mo +0 -0
  18. djgentelella/locale/es/LC_MESSAGES/djangojs.po +46 -0
  19. djgentelella/migrations/0014_trash.py +31 -0
  20. djgentelella/migrations/0015_trash_deleted_by.py +21 -0
  21. djgentelella/migrations/0016_trash_created_at.py +20 -0
  22. djgentelella/migrations/0017_alter_chunkedupload_status.py +18 -0
  23. djgentelella/migrations/0018_alter_chunkedupload_status.py +18 -0
  24. djgentelella/models.py +97 -0
  25. djgentelella/models_manager.py +40 -0
  26. djgentelella/serializers/firmador_digital.py +9 -1
  27. djgentelella/serializers/selects.py +14 -0
  28. djgentelella/static/djgentelella.readonly.vendors.min.css +9 -5
  29. djgentelella/static/djgentelella.readonly.vendors.min.js +1 -1
  30. djgentelella/static/gentelella/css/custom.css +23 -2
  31. djgentelella/static/gentelella/css/modern.css +15 -0
  32. djgentelella/static/gentelella/css/modern_black_white.css +15 -0
  33. djgentelella/static/gentelella/css/pdfviewer.css +43 -1
  34. djgentelella/static/gentelella/images/default.png +0 -0
  35. djgentelella/static/gentelella/js/base/digital_signature.js +318 -79
  36. djgentelella/static/gentelella/js/base/form.common.js +9 -4
  37. djgentelella/static/gentelella/js/base/select2_wrap.js +15 -1
  38. djgentelella/static/gentelella/js/base/select2related.js +5 -0
  39. djgentelella/static/gentelella/js/base.js +347 -83
  40. djgentelella/static/gentelella/js/custom.js +6 -1
  41. djgentelella/static/gentelella/js/datatables.js +15 -0
  42. djgentelella/static/gentelella/js/digital_signature_update.js +29 -0
  43. djgentelella/static/gentelella/js/obj_api_management.js +403 -344
  44. djgentelella/static/gentelella/js/widgets.js +10 -1
  45. djgentelella/static/vendors/timeline/css/timeline.css +9 -5
  46. djgentelella/static/vendors/timeline/js/timeline.js +1 -1
  47. djgentelella/templates/forms/as_grid.html +2 -2
  48. djgentelella/templates/forms/as_inline.html +3 -5
  49. djgentelella/templates/gentelella/app/sidebar.html +16 -13
  50. djgentelella/templates/gentelella/digital_signature/update_signature_settings.html +45 -0
  51. djgentelella/templates/gentelella/registration/reset_done.html +24 -0
  52. djgentelella/templates/gentelella/widgets/digital_signature.html +47 -11
  53. djgentelella/trash/api.py +77 -0
  54. djgentelella/trash/filterset.py +20 -0
  55. djgentelella/trash/serializer.py +45 -0
  56. djgentelella/urls.py +13 -2
  57. djgentelella/views/select2autocomplete.py +40 -0
  58. djgentelella/widgets/core.py +6 -5
  59. djgentelella/widgets/digital_signature.py +5 -21
  60. djgentelella/widgets/selects.py +47 -0
  61. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/METADATA +2 -2
  62. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/RECORD +66 -48
  63. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/AUTHORS +0 -0
  64. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/LICENSE.txt +0 -0
  65. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/WHEEL +0 -0
  66. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/top_level.txt +0 -0
@@ -1,48 +1,54 @@
1
- function get_selected_items(dt, table){
1
+ function get_selected_items(dt, table) {
2
2
  let values = [];
3
- $(table).find(".gtcheckable:checked").each(function() {
3
+ $(table).find(".gtcheckable:checked").each(function () {
4
4
  values.push(this.value);
5
5
  });
6
6
  return values;
7
7
  }
8
- function gt_show_actions(crud_name){
9
- return function(data, type, row, meta){
10
- var html="";
11
- if(data != null ){
12
- if(data.title != undefined){
13
- html+= data.title+" ";
14
- }
15
- for(var x=0; x<data.actions.length; x++){
8
+
9
+ function gt_show_actions(crud_name) {
10
+ return function (data, type, row, meta) {
11
+ var html = "";
12
+ if (data != null) {
13
+ if (data.title != undefined) {
14
+ html += data.title + " ";
15
+ }
16
+ for (var x = 0; x < data.actions.length; x++) {
16
17
  let action = data.actions[x];
17
- html += '<i onclick="javascript:call_obj_crud_event(\''+crud_name+'\', \''+action.name+'\', '+meta.row+');" class="'+action.i_class+'"></i>';
18
+ html += '<i onclick="javascript:call_obj_crud_event(\'' + crud_name + '\', \'' + action.name + '\', ' + meta.row + ');" class="' + action.i_class + '"></i>';
18
19
  }
19
20
  }
20
21
  return html;
21
22
  }
22
23
  }
23
24
 
24
- function GTBaseFormModal(modal_id, datatable_element, form_config) {
25
+ function GTBaseFormModal(modal_id, datatable_element, form_config) {
25
26
  var modal = $(modal_id);
26
27
  var form = modal.find('form');
27
28
  var prefix = form.find(".form_prefix").val();
28
- if(prefix.length != 0){
29
- prefix = prefix+"-"
29
+ if (prefix.length != 0) {
30
+ prefix = prefix + "-"
30
31
  }
31
32
  const default_config = {
32
33
  "btn_class": ".formadd",
33
34
  "type": "POST",
34
35
  "reload_table": true,
35
- "events": {'form_submit': function(instance){ return {} },
36
- 'success_form': function(data){},
37
- 'error_form': function(errors){}
36
+ "events": {
37
+ 'form_submit': function (instance) {
38
+ return {}
39
+ },
40
+ 'success_form': function (data) {
41
+ },
42
+ 'error_form': function (errors) {
43
+ }
38
44
 
39
- },
45
+ },
40
46
  "relation_render": {},
41
47
  "parentdiv": ".gtformfield"
42
- }
48
+ }
43
49
 
44
50
 
45
- const config = Object.assign({}, default_config, form_config);
51
+ const config = Object.assign({}, default_config, form_config);
46
52
 
47
53
  return {
48
54
  "instance": modal,
@@ -55,34 +61,36 @@ function GTBaseFormModal(modal_id, datatable_element, form_config) {
55
61
  "type": config.type,
56
62
  "btn_class": config.btn_class,
57
63
  "parentdiv": config.parentdiv,
58
- "init": function(){
64
+ "init": function () {
59
65
  var myModalEl = this.instance[0];
60
66
  myModalEl.addEventListener('hidden.bs.modal', this.hide_modalevent(this))
61
67
  this.instance.find(this.btn_class).on('click', this.add_btn_form(this));
62
- $(this.form).on('submit', (e)=>{e.preventDefault();})
63
- },
64
- "add_btn_form": function(instance){
65
- return function(event){
66
- convertToStringJson(instance.form, prefix=instance.prefix,
67
- extras=instance.config.events.form_submit(instance)).then((result) => {
68
- fetch(instance.url, {
69
- method: instance.type,
70
- body: result,
71
- headers: {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type': 'application/json'}
72
- }
68
+ $(this.form).on('submit', (e) => {
69
+ e.preventDefault();
70
+ })
71
+ },
72
+ "add_btn_form": function (instance) {
73
+ return function (event) {
74
+ convertToStringJson(instance.form, prefix = instance.prefix,
75
+ extras = instance.config.events.form_submit(instance)).then((result) => {
76
+ fetch(instance.url, {
77
+ method: instance.type,
78
+ body: result,
79
+ headers: {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type': 'application/json'}
80
+ }
73
81
  ).then(response_manage_type_data(instance, instance.error, instance.error_text))
74
- .then(instance.fn_success(instance))
75
- .catch(error => instance.handle_error(instance, error));
76
- });
82
+ .then(instance.fn_success(instance))
83
+ .catch(error => instance.handle_error(instance, error));
84
+ });
77
85
  }
78
86
  },
79
- "success": function(instance, data){
87
+ "success": function (instance, data) {
80
88
  },
81
- "fn_success": function(instance){
82
- return function(data){
83
- if(data !== false){
89
+ "fn_success": function (instance) {
90
+ return function (data) {
91
+ if (data !== false) {
84
92
  instance.config.events.success_form(data)
85
- if (instance.reload_table){
93
+ if (instance.reload_table) {
86
94
  datatable_element.ajax.reload();
87
95
  }
88
96
  instance.hide_modal();
@@ -94,87 +102,87 @@ function GTBaseFormModal(modal_id, datatable_element, form_config) {
94
102
  });
95
103
  instance.success(instance, data);
96
104
  }
97
- }
105
+ }
98
106
  },
99
- "error_text": function(instance, message){
100
- Swal.fire({icon: 'error', title: gettext('Error'), text: message });
107
+ "error_text": function (instance, message) {
108
+ Swal.fire({icon: 'error', title: gettext('Error'), text: message});
101
109
  },
102
- "error": function(instance, errors){
110
+ "error": function (instance, errors) {
103
111
  instance.config.events.error_form(errors)
104
- if(errors.hasOwnProperty('detail') && Object.keys(errors).length == 1){
105
- Swal.fire({ icon: 'error', title: gettext('Error'), text: errors.detail });
112
+ if (errors.hasOwnProperty('detail') && Object.keys(errors).length == 1) {
113
+ Swal.fire({icon: 'error', title: gettext('Error'), text: errors.detail});
106
114
  }
107
115
  instance.form.find('ul.form_errors').remove();
108
116
  form_field_errors(instance.form, errors, instance.prefix, instance.parentdiv);
109
117
  },
110
- "handle_error": function(instance, error){
111
- Swal.fire({ icon: 'error', title: gettext('Error'), text: error.message });
118
+ "handle_error": function (instance, error) {
119
+ Swal.fire({icon: 'error', title: gettext('Error'), text: error.message});
112
120
  },
113
- "hide_modal": function(){
121
+ "hide_modal": function () {
114
122
  this.instance.modal('hide');
115
123
  },
116
- "hide_modalevent": function(instance){
117
- return function(event){
124
+ "hide_modalevent": function (instance) {
125
+ return function (event) {
118
126
  clear_action_form(instance.form);
119
127
  instance.hide_modal();
120
128
  }
121
129
  },
122
- "show_modal": function(btninstance){
130
+ "show_modal": function (btninstance) {
123
131
  this.instance.modal('show');
124
132
  },
125
- "fill_form": function(datainstance){
126
- var keys = Object.keys(datainstance);
133
+ "fill_form": function (datainstance) {
134
+ var keys = Object.keys(datainstance);
127
135
  var select2Items = [];
128
136
  var instance = this;
129
- $.each(keys, function(i, e){
130
- if($("#id_"+instance.prefix+e).data('select2-id') != undefined ){
131
- select2Items.push(e);
132
- }else{
133
- instance.updateInstanceForm(instance.prefix+e, datainstance[e]);
137
+ $.each(keys, function (i, e) {
138
+ if ($("#id_" + instance.prefix + e).data('select2-id') != undefined) {
139
+ select2Items.push(e);
140
+ } else {
141
+ instance.updateInstanceForm(instance.prefix + e, datainstance[e]);
134
142
  }
135
143
 
136
- });
137
- // do select 2 items
138
- $.each(select2Items, function(i, e){
139
- var display_name_key = 'text';
140
- if(instance.relation_render.hasOwnProperty(e)){
141
- display_name_key=instance.relation_render[e];
142
- }
143
- $('#id_'+instance.prefix+e).val(null).trigger('change');
144
- if(datainstance[e]){
145
- if(Array.isArray(datainstance[e])){
146
- for(var x=0; x<datainstance[e].length; x++){
147
- $('#id_'+instance.prefix+e+' option[value="'+datainstance[e][x]['id']+'"]').remove();
148
- var newOption = new Option(datainstance[e][x][display_name_key], datainstance[e][x]['id'], true, true);
149
- $('#id_'+instance.prefix+e).append(newOption);
150
- }
151
- }else{
152
- if($('#id_'+instance.prefix+e+' option[value="'+datainstance[e]['id']+'"]').length>0){
153
- $('#id_'+instance.prefix+e).val(datainstance[e]['id']);
154
- }else{
155
- var newOption = new Option(datainstance[e][display_name_key], datainstance[e]['id'], true, true);
156
- $('#id_'+instance.prefix+e).append(newOption);
157
- }
144
+ });
145
+ // do select 2 items
146
+ $.each(select2Items, function (i, e) {
147
+ var display_name_key = 'text';
148
+ if (instance.relation_render.hasOwnProperty(e)) {
149
+ display_name_key = instance.relation_render[e];
150
+ }
151
+ $('#id_' + instance.prefix + e).val(null).trigger('change');
152
+ if (datainstance[e]) {
153
+ if (Array.isArray(datainstance[e])) {
154
+ for (var x = 0; x < datainstance[e].length; x++) {
155
+ $('#id_' + instance.prefix + e + ' option[value="' + datainstance[e][x]['id'] + '"]').remove();
156
+ var newOption = new Option(datainstance[e][x][display_name_key], datainstance[e][x]['id'], true, true);
157
+ $('#id_' + instance.prefix + e).append(newOption);
158
+ }
159
+ } else {
160
+ if ($('#id_' + instance.prefix + e + ' option[value="' + datainstance[e]['id'] + '"]').length > 0) {
161
+ $('#id_' + instance.prefix + e).val(datainstance[e]['id']);
162
+ } else {
163
+ var newOption = new Option(datainstance[e][display_name_key], datainstance[e]['id'], true, true);
164
+ $('#id_' + instance.prefix + e).append(newOption);
158
165
  }
159
- $('#id_'+instance.prefix+e).trigger('change')
160
- }
166
+ }
167
+ $('#id_' + instance.prefix + e).trigger('change')
168
+ }
161
169
  });
162
170
  },
163
- "updateInstanceForm": function (name, value){
164
- var item = this.form.find('input[name="'+name+'"], textarea[name="'+name+'"]');
165
- var parent=this;
166
- item.each(function(i, inputfield){
167
- let done=false;
168
- inputfield=$(inputfield);
169
-
170
- if(inputfield.attr('class') === "chunkedvalue"){
171
- if(value){
172
- var chunked=parent.form.find('input[name="'+name+'_widget"]').data('fileUploadWidget');
173
- chunked.addRemote(value);
171
+ "updateInstanceForm": function (name, value) {
172
+ var item = this.form.find('input[name="' + name + '"], textarea[name="' + name + '"]');
173
+ var parent = this;
174
+ item.each(function (i, inputfield) {
175
+ let done = false;
176
+ inputfield = $(inputfield);
177
+
178
+ if (inputfield.attr('class') === "chunkedvalue") {
179
+ if (value) {
180
+ var chunked = parent.form.find('input[name="' + name + '_widget"]').data('fileUploadWidget');
181
+ chunked.addRemote(value);
174
182
  }
175
- done=true;
176
- } else if(inputfield.attr('type') === 'file'){
177
- if(value){
183
+ done = true;
184
+ } else if (inputfield.attr('type') === 'file') {
185
+ if (value) {
178
186
  var newlink = document.createElement('a');
179
187
  newlink.href = value.url;
180
188
  newlink.textContent = value.name;
@@ -184,54 +192,61 @@ function GTBaseFormModal(modal_id, datatable_element, form_config) {
184
192
  newlink.classList.add("d-block");
185
193
  inputfield.before(newlink)
186
194
  }
187
- done=true;
188
- } else if(inputfield.attr('type') === "checkbox" ){
189
- if (inputfield.data().widget === "YesNoInput"){
190
- inputfield.prop( "checked", !value);
195
+ done = true;
196
+ } else if (inputfield.attr('type') === "checkbox") {
197
+ if (inputfield.data().widget === "YesNoInput") {
198
+ inputfield.prop("checked", !value);
191
199
  inputfield.trigger("click");
192
- done=true;
193
- }else{
194
- inputfield.prop( "checked", value);
200
+ done = true;
201
+ } else {
202
+ inputfield.prop("checked", value);
195
203
  }
196
- done=true;
197
- } else if(inputfield.attr('type') === "radio"){
204
+ done = true;
205
+ } else if (inputfield.attr('type') === "radio") {
198
206
  var is_icheck = inputfield.closest('.gtradio').length > 0;
199
- var sel = inputfield.filter(function() { return this.value === value.toString() });
200
- if(sel.length>0){
201
- sel.prop( "checked", true);
202
- if(is_icheck){
207
+ var sel = inputfield.filter(function () {
208
+ return this.value === value.toString()
209
+ });
210
+ if (sel.length > 0) {
211
+ sel.prop("checked", true);
212
+ if (is_icheck) {
203
213
  sel.iCheck('update');
204
214
  sel.iCheck('check');
205
215
  }
206
216
 
207
- }else{
208
- inputfield.prop( "checked", false);
209
- if(is_icheck){
217
+ } else {
218
+ inputfield.prop("checked", false);
219
+ if (is_icheck) {
210
220
  inputfield.iCheck('update');
211
221
  inputfield.iCheck('uncheck');
212
222
  }
213
223
  }
214
- done=true;
224
+ done = true;
215
225
  }
216
- if (inputfield.data().widget === "EditorTinymce" || inputfield.data().widget === "TextareaWysiwyg"){
217
- tinymce.get(inputfield.attr('id')).setContent(value);
218
- done=true;
226
+ if (inputfield.data().widget === "EditorTinymce" || inputfield.data().widget === "TextareaWysiwyg") {
227
+ tinymce.get(inputfield.attr('id')).setContent(value);
228
+ done = true;
219
229
  }
220
- if (inputfield.data().widget === "TaggingInput" || inputfield.data().widget === "EmailTaggingInput"){
221
- var tagifyelement=inputfield.data().tagify;
222
- tagifyelement.removeAllTags();
223
- tagifyelement.loadOriginalValues(value);
224
- done=true;
230
+ if (inputfield.data().widget === "TaggingInput" || inputfield.data().widget === "EmailTaggingInput") {
231
+ var tagifyelement = inputfield.data().tagify;
232
+ if (tagifyelement != undefined){
233
+ tagifyelement.removeAllTags();
234
+ tagifyelement.loadOriginalValues(value);
235
+ }
236
+ done = false;
237
+ }
238
+ if (!done) {
239
+ inputfield.val(value);
225
240
  }
226
- if(!done) { inputfield.val(value); }
227
241
  });
228
- }
242
+ }
229
243
  }
230
244
  }
245
+
231
246
  /**
232
- **/
247
+ **/
233
248
 
234
- function BaseDetailModal(modalid, base_detail_url, template_url, form_config={}){
249
+ function BaseDetailModal(modalid, base_detail_url, template_url, form_config = {}) {
235
250
  const default_config = {
236
251
  "base_template": "<% it.display_text %>",
237
252
  "title": "<% it.title %>",
@@ -240,20 +255,28 @@ function BaseDetailModal(modalid, base_detail_url, template_url, form_config={})
240
255
  "headers": {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type': 'application/json'},
241
256
  "method": "get",
242
257
  "events": {
243
- 'update_detail_event': function(data){ return data},
244
- 'form_submit_template': function(data){ return data},
245
- 'form_submit_instance': function(data){ return data},
246
- 'form_error_instance': function(errors){},
247
- 'form_error_template': function(errors){}
258
+ 'update_detail_event': function (data) {
259
+ return data
260
+ },
261
+ 'form_submit_template': function (data) {
262
+ return data
263
+ },
264
+ 'form_submit_instance': function (data) {
265
+ return data
266
+ },
267
+ 'form_error_instance': function (errors) {
268
+ },
269
+ 'form_error_template': function (errors) {
270
+ }
248
271
  }
249
- }
272
+ }
250
273
 
251
274
 
252
- const config = Object.assign({}, default_config, form_config);
275
+ const config = Object.assign({}, default_config, form_config);
253
276
  return {
254
277
  "modal": $(modalid),
255
278
  "modalid": modalid,
256
- "config" : config,
279
+ "config": config,
257
280
  "instanceid": null,
258
281
  "template_url": template_url,
259
282
  "base_detail_url": base_detail_url,
@@ -264,96 +287,98 @@ function BaseDetailModal(modalid, base_detail_url, template_url, form_config={})
264
287
  "template_tries": 0,
265
288
  "detail_tries": 0,
266
289
  "title": config.title,
267
- "init": function(){
290
+ "init": function () {
268
291
  this.get_template();
269
292
  },
270
- "show": function(){
293
+ "show": function () {
271
294
  this.modal.modal('show');
272
295
  },
273
- "hide": function(){
296
+ "hide": function () {
274
297
  this.modal.modal('hide');
275
298
  },
276
- "update_template": function(instance){
277
- return function(data){
278
- instance.template_tries=0;
279
- instance.template= 'template' in data ? data['template'] : instance.template;
299
+ "update_template": function (instance) {
300
+ return function (data) {
301
+ instance.template_tries = 0;
302
+ instance.template = 'template' in data ? data['template'] : instance.template;
280
303
  instance.title = 'title' in data ? data['title'] : instance.title;
281
304
  }
282
305
  },
283
- "update_detail": function(instance){
284
- return function(data){
285
- data = instance.config.events.update_detail_event(data);
286
- instance.detail_tries=0;
306
+ "update_detail": function (instance) {
307
+ return function (data) {
308
+ data = instance.config.events.update_detail_event(data);
309
+ instance.detail_tries = 0;
287
310
 
288
- var result = Sqrl.render(instance.template, data, Sqrl.getConfig({ tags: ["<%", "%>"] }));
289
- instance.modal.find(".modal-body").html(result);
290
- var result = Sqrl.render(instance.title, data, Sqrl.getConfig({ tags: ["<%", "%>"] }));
291
- instance.modal.find(".modal-title").html(result);
292
- instance.show();
311
+ var result = Sqrl.render(instance.template, data, Sqrl.getConfig({tags: ["<%", "%>"]}));
312
+ instance.modal.find(".modal-body").html(result);
313
+ var result = Sqrl.render(instance.title, data, Sqrl.getConfig({tags: ["<%", "%>"]}));
314
+ instance.modal.find(".modal-title").html(result);
315
+ instance.show();
293
316
  }
294
317
  },
295
- "recall_get_template": function(instance){
296
- return function(response) {
297
- if(instance.template_tries<instance.template_max_tries){
298
- instance.template_tries = instance.template_tries+ 1;
318
+ "recall_get_template": function (instance) {
319
+ return function (response) {
320
+ if (instance.template_tries < instance.template_max_tries) {
321
+ instance.template_tries = instance.template_tries + 1;
299
322
  instance.get_template();
300
- }else{
323
+ } else {
301
324
  instance.config.events.form_error_template(response);
302
325
  }
303
326
  }
304
327
  },
305
- "recall_get_detail": function(instance){
306
- return function(response) {
307
- if(instance.detail_tries<instance.detail_max_tries){
308
- instance.detail_tries = instance.detail_tries+1;
328
+ "recall_get_detail": function (instance) {
329
+ return function (response) {
330
+ if (instance.detail_tries < instance.detail_max_tries) {
331
+ instance.detail_tries = instance.detail_tries + 1;
309
332
  instance.show_instance(instance.instanceid);
310
- }else{
333
+ } else {
311
334
  instance.config.events.form_error_instance(response);
312
335
  }
313
336
  }
314
337
 
315
338
  },
316
- "get_template": function(){
339
+ "get_template": function () {
317
340
  var instance = this;
318
341
  let params = {
319
- method: instance.config.method,
320
- headers: instance.config.headers
321
- }
342
+ method: instance.config.method,
343
+ headers: instance.config.headers
344
+ }
322
345
  params = instance.config.events.form_submit_template(params);
323
346
 
324
347
  fetch(instance.template_url, params
325
- ).then(response_manage_type_data(instance, instance.error, instance.handle_error))
348
+ ).then(response_manage_type_data(instance, instance.error, instance.handle_error))
326
349
  .then(instance.update_template(instance))
327
350
  .catch(instance.recall_get_template(instance));
328
351
  },
329
- "show_instance": function(instanceid){
352
+ "show_instance": function (instanceid) {
330
353
  var instance = this;
331
- if(this.instanceid != instanceid){ instance.detail_tries = 0; }
354
+ if (this.instanceid != instanceid) {
355
+ instance.detail_tries = 0;
356
+ }
332
357
  this.instanceid = instanceid
333
- var url = this.base_detail_url.replace('/0/', '/'+instanceid+'/');
358
+ var url = this.base_detail_url.replace('/0/', '/' + instanceid + '/');
334
359
 
335
360
  let params = {
336
- method: instance.config.method,
337
- headers: instance.config.headers
338
- }
361
+ method: instance.config.method,
362
+ headers: instance.config.headers
363
+ }
339
364
  params = instance.config.events.form_submit_instance(params);
340
365
  fetch(url, params
341
- ).then(response_manage_type_data(instance, instance.error, instance.handle_error))
366
+ ).then(response_manage_type_data(instance, instance.error, instance.handle_error))
342
367
  .then(instance.update_detail(instance))
343
368
  .catch(instance.recall_get_detail(instance));
344
369
 
345
370
  },
346
- "error": function(instance, errors){
347
- Swal.fire({ icon: 'error', title: gettext('Error'), text: errors.detail });
371
+ "error": function (instance, errors) {
372
+ Swal.fire({icon: 'error', title: gettext('Error'), text: errors.detail});
348
373
  },
349
- "handle_error": function(instance, error){
350
- Swal.fire({ icon: 'error', title: gettext('Error'), text: error.message });
374
+ "handle_error": function (instance, error) {
375
+ Swal.fire({icon: 'error', title: gettext('Error'), text: error.message});
351
376
  },
352
377
 
353
378
  }
354
379
  }
355
380
 
356
- function ObjectCRUD(uniqueid, objconfig={}){
381
+ function ObjectCRUD(uniqueid, objconfig = {}) {
357
382
 
358
383
  var default_config = {
359
384
  uls: null,
@@ -361,14 +386,17 @@ function ObjectCRUD(uniqueid, objconfig={}){
361
386
  modal_ids: null,
362
387
  checkable: false,
363
388
  events: {
364
- 'update_data': function(data){ return data; }
389
+ 'update_data': function (data) {
390
+ return data;
391
+ }
392
+ },
393
+ actions: {
394
+ table_actions: [], object_actions: [],
395
+ title: gettext('Actions'),
396
+ className: "no-export-col"
365
397
  },
366
- actions: { table_actions: [], object_actions: [],
367
- title: gettext('Actions'),
368
- className: "no-export-col"
369
- },
370
398
  datatable_inits: {},
371
- replace_as_detail: {create: false, update: true, destroy: true, list: false },
399
+ replace_as_detail: {create: false, update: true, destroy: true, list: false},
372
400
  relation_render: {},
373
401
  headers: {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type': 'application/json'},
374
402
  btn_class: {
@@ -382,7 +410,9 @@ function ObjectCRUD(uniqueid, objconfig={}){
382
410
  update: 'fa fa-edit',
383
411
  destroy: 'fa fa-trash'
384
412
  },
385
- delete_display: function(data){ return gettext("This Object"); },
413
+ delete_display: function (data) {
414
+ return gettext("This Object");
415
+ },
386
416
  gt_form_modals: {
387
417
  'create': {},
388
418
  'detail': {},
@@ -392,25 +422,25 @@ function ObjectCRUD(uniqueid, objconfig={}){
392
422
 
393
423
  }
394
424
 
395
- const config = Object.assign({}, default_config, objconfig);
425
+ const config = Object.assign({}, default_config, objconfig);
396
426
 
397
427
  per_table_actions = []
398
428
  per_object_actions = []
399
- if( "table_actions" in objconfig.actions){
400
- per_table_actions=objconfig.actions.table_actions;
429
+ if ("table_actions" in objconfig.actions) {
430
+ per_table_actions = objconfig.actions.table_actions;
401
431
  }
402
- if( "object_actions" in objconfig.actions){
432
+ if ("object_actions" in objconfig.actions) {
403
433
  per_object_actions = objconfig.actions.object_actions;
404
434
  }
405
- obj={
435
+ obj = {
406
436
  "uniqueid": uniqueid,
407
437
  "config": config,
408
438
  "relation_render": config.relation_render,
409
439
  "can_create": config.modal_ids.hasOwnProperty("create"),
410
- "can_destroy": config.urls.hasOwnProperty("destroy_url") && config.modal_ids.hasOwnProperty("destroy") ,
440
+ "can_destroy": config.urls.hasOwnProperty("destroy_url") && config.modal_ids.hasOwnProperty("destroy"),
411
441
  "can_list": config.urls.hasOwnProperty("list_url"),
412
442
  "can_detail": objconfig.urls.hasOwnProperty("detail_url") && config.modal_ids.hasOwnProperty("detail")
413
- && config.urls.hasOwnProperty("detail_template_url"),
443
+ && config.urls.hasOwnProperty("detail_template_url"),
414
444
  "can_update": config.modal_ids.hasOwnProperty("update"),
415
445
  "use_get_values_for_update": config.urls.hasOwnProperty("get_values_for_update_url"),
416
446
  "create_btn_class": config.btn_class.create,
@@ -421,33 +451,33 @@ function ObjectCRUD(uniqueid, objconfig={}){
421
451
  "delete_form": null,
422
452
  "data_extras": config.data_extras,
423
453
  "detail_modal": null,
424
- "base_update_url":null,
454
+ "base_update_url": null,
425
455
  "table_actions": per_table_actions,
426
456
  "object_actions": per_object_actions,
427
- "init": function(){
428
- if(this.can_list) this.list();
429
- if(this.can_create){
457
+ "init": function () {
458
+ if (this.can_list) this.list();
459
+ if (this.can_create) {
430
460
  let create_conf = Object.assign({}, {}, this.config.gt_form_modals.create);
431
461
  this.create_form = GTBaseFormModal(this.config.modal_ids.create, this.datatable, create_conf);
432
462
  this.create_form.init();
433
463
  }
434
- if(this.can_update){
464
+ if (this.can_update) {
435
465
  let update_conf = Object.assign({}, {
436
- type: "PUT", relation_render: this.relation_render
466
+ type: "PUT", relation_render: this.relation_render
437
467
  }, this.config.gt_form_modals.update);
438
468
  this.update_form = GTBaseFormModal(this.config.modal_ids.update, this.datatable, update_conf);
439
469
  this.base_update_url = this.update_form.url;
440
470
  this.update_form.init();
441
471
  }
442
- if(this.can_detail){
472
+ if (this.can_detail) {
443
473
  let detail_conf = Object.assign({}, {}, this.config.gt_form_modals.detail);
444
474
  this.detail_modal = BaseDetailModal(this.config.modal_ids.detail,
445
- this.config.urls.detail_url,
446
- this.config.urls.detail_template_url,
447
- detail_conf)
475
+ this.config.urls.detail_url,
476
+ this.config.urls.detail_template_url,
477
+ detail_conf)
448
478
  this.detail_modal.init()
449
479
  }
450
- if(this.can_destroy){
480
+ if (this.can_destroy) {
451
481
  let destroy_conf = Object.assign({}, {
452
482
  type: "DELETE", relation_render: this.relation_render, btn_class: ".delbtn"
453
483
  }, this.config.gt_form_modals.destroy);
@@ -455,13 +485,13 @@ function ObjectCRUD(uniqueid, objconfig={}){
455
485
  this.destroy_form.init();
456
486
  }
457
487
  },
458
- "create": function(instance){
459
- return function(e, dt, node, config){
488
+ "create": function (instance) {
489
+ return function (e, dt, node, config) {
460
490
  instance.create_form.show_modal();
461
491
  }
462
492
  },
463
- "success": function(instance){
464
- return function(data){
493
+ "success": function (instance) {
494
+ return function (data) {
465
495
  Swal.fire({
466
496
  title: gettext('Success'),
467
497
  text: data['detail'],
@@ -472,20 +502,20 @@ function ObjectCRUD(uniqueid, objconfig={}){
472
502
  }
473
503
 
474
504
  },
475
- "destroy": function(data, action) {
476
- let url = this.config.urls.destroy_url.replace('/0/', '/'+data.id+'/');
505
+ "destroy": function (data, action) {
506
+ let url = this.config.urls.destroy_url.replace('/0/', '/' + data.id + '/');
477
507
  let text = this.config.delete_display(data)
478
508
  this.destroy_form.url = url;
479
509
  this.destroy_form.instance.find(".objtext").html(text)
480
510
  this.destroy_form.show_modal();
481
511
  },
482
- "list": function(){
512
+ "list": function () {
483
513
  /**
484
- This function initialize datatable
485
- */
514
+ This function initialize datatable
515
+ */
486
516
  var instance = this;
487
517
 
488
- if(this.can_create){
518
+ if (this.can_create) {
489
519
  this.table_actions.push({
490
520
  action: this.create(this),
491
521
  text: this.config.icons.create,
@@ -493,203 +523,218 @@ function ObjectCRUD(uniqueid, objconfig={}){
493
523
  className: this.config.btn_class.create
494
524
  })
495
525
  }
496
- if(this.can_list){
497
- this.table_actions.unshift({
498
- action: function ( e, dt, node, config ) {clearDataTableFilters(dt, instance.config.datatable_element)},
499
- text: this.config.icons.clear,
500
- titleAttr: gettext('Clear Filters'),
501
- className: this.config.btn_class.clear_filters
502
- })
526
+ if (this.can_list) {
527
+ this.table_actions.unshift({
528
+ action: function (e, dt, node, config) {
529
+ clearDataTableFilters(dt, instance.config.datatable_element)
530
+ },
531
+ text: this.config.icons.clear,
532
+ titleAttr: gettext('Clear Filters'),
533
+ className: this.config.btn_class.clear_filters
534
+ })
503
535
  }
504
- if(!config.datatable_inits.hasOwnProperty("buttons")){
536
+ if (!config.datatable_inits.hasOwnProperty("buttons")) {
505
537
  config.datatable_inits['buttons'] = this.table_actions;
506
538
  }
507
- if(this.can_detail){
539
+ if (this.can_detail) {
508
540
  instance.object_actions.push(
509
541
  {
510
- 'name': "detail",
511
- 'action': 'detail',
512
- 'title': gettext('Detail'),
513
- 'url': null,
514
- 'i_class': this.config.icons.detail,
542
+ 'name': "detail",
543
+ 'action': 'detail',
544
+ 'title': gettext('Detail'),
545
+ 'url': null,
546
+ 'i_class': this.config.icons.detail,
515
547
  }
516
548
  )
517
549
  }
518
- if(this.can_update){
550
+ if (this.can_update) {
519
551
  instance.object_actions.push(
520
552
  {
521
- 'name': "update",
522
- 'action': 'update',
523
- 'title': gettext("Update"),
524
- 'url': null,
525
- 'i_class': this.config.icons.update,
553
+ 'name': "update",
554
+ 'action': 'update',
555
+ 'title': gettext("Update"),
556
+ 'url': null,
557
+ 'i_class': this.config.icons.update,
526
558
  }
527
559
  )
528
560
  }
529
- if(this.can_destroy){
561
+ if (this.can_destroy) {
530
562
  instance.object_actions.push(
531
563
  {
532
- 'name': 'destroy',
533
- 'action': 'destroy',
534
- 'title': gettext('Delete'),
535
- 'url': null,
536
- 'i_class': this.config.icons.destroy,
564
+ 'name': 'destroy',
565
+ 'action': 'destroy',
566
+ 'title': gettext('Delete'),
567
+ 'url': null,
568
+ 'i_class': this.config.icons.destroy,
537
569
  }
538
570
  )
539
571
  }
540
- if(!config.datatable_inits.hasOwnProperty("columns")){
541
- config.datatable_inits.columns=[];
572
+ if (!config.datatable_inits.hasOwnProperty("columns")) {
573
+ config.datatable_inits.columns = [];
542
574
  }
543
- if(!config.datatable_inits.hasOwnProperty("columnDefs")){
575
+ if (!config.datatable_inits.hasOwnProperty("columnDefs")) {
544
576
  config.datatable_inits['columnDefs'] = [
545
577
  {
546
- targets: -1,
547
- title: this.config.actions.title,
548
- type: 'actions',
549
- className: this.config.actions.className,
550
- orderable: false,
551
- render: function(data, type, full, meta){
578
+ targets: -1,
579
+ title: this.config.actions.title,
580
+ type: 'actions',
581
+ className: this.config.actions.className,
582
+ orderable: false,
583
+ render: function (data, type, full, meta) {
552
584
  var edittext = '<div class="d-flex mt-1">';
553
- let do_action=true;
554
- for(var x=0; x<instance.object_actions.length; x++){
555
- let action = instance.object_actions[x];
556
- let display_in_column = true;
557
- do_action=true
558
- if(action.name in data ){
559
- do_action=data[action.name];
560
- }
561
- if(do_action){
562
- if('in_action_column' in action ){
563
- display_in_column=action.in_action_column;
564
- }
565
- if(display_in_column){
566
- let params = "'"+instance.uniqueid+"', '"+action.name+"', "+meta.row;
567
- edittext += '<i onclick="javascript:call_obj_crud_event('+params+');"';
568
- edittext += 'title="'+action.title+'"';
569
- edittext += ' class="'+instance.object_actions[x].i_class+'" ></i>';
570
- }
571
- }
585
+ let do_action = true;
586
+ for (var x = 0; x < instance.object_actions.length; x++) {
587
+ let action = instance.object_actions[x];
588
+ let display_in_column = true;
589
+ do_action = true
590
+ if (action.name in data) {
591
+ do_action = data[action.name];
592
+ }
593
+ if (do_action) {
594
+ if ('in_action_column' in action) {
595
+ display_in_column = action.in_action_column;
596
+ }
597
+ if (display_in_column) {
598
+ let params = "'" + instance.uniqueid + "', '" + action.name + "', " + meta.row;
599
+ edittext += '<i onclick="javascript:call_obj_crud_event(' + params + ');"';
600
+ edittext += 'title="' + action.title + '"';
601
+ edittext += ' class="' + instance.object_actions[x].i_class + '" ></i>';
602
+ }
603
+ }
572
604
  }
573
- edittext += '</div>';
574
- return edittext;
575
- }
576
- }
605
+ edittext += '</div>';
606
+ return edittext;
607
+ }
608
+ }
577
609
  ]
578
- if(this.checkable){
610
+ if (this.checkable) {
579
611
  config.datatable_inits['columnDefs'].push(
580
- {
581
- targets: 0,
582
- title: "Checkable",
583
- type: 'checkable',
584
- className: "no-export-col",
585
- orderable: false,
586
- render: function(data, type, full, meta){
587
- return '<input type="checkbox" class="gtcheckable" name="checkable" value="'+full.id+'" title="'+full.name+'"/>'
588
- }
589
- })
612
+ {
613
+ targets: 0,
614
+ title: "Checkable",
615
+ type: 'checkable',
616
+ className: "no-export-col",
617
+ orderable: false,
618
+ render: function (data, type, full, meta) {
619
+ return '<input type="checkbox" class="gtcheckable" name="checkable" value="' + full.id + '" title="' + full.name + '"/>'
620
+ }
621
+ })
590
622
 
591
623
  config.datatable_inits.columns.unshift(
592
- {data: "id", name: "checkable", title: '<input type="checkbox" class="checkableall"> ', type: "checkable", visible: true}
624
+ {
625
+ data: "id",
626
+ name: "checkable",
627
+ title: '<input type="checkbox" class="checkableall"> ',
628
+ type: "checkable",
629
+ visible: true
630
+ }
593
631
  )
594
632
  }
595
633
  }
596
- this.datatable = gtCreateDataTable(this.config.datatable_element, this.config.urls.list_url,
597
- this.config.datatable_inits);
634
+ this.datatable = gtCreateDataTable(this.config.datatable_element, this.config.urls.list_url,
635
+ this.config.datatable_inits);
598
636
  },
599
- "detail": function(instance, action){
600
- this.detail_modal.show_instance(instance.id);
637
+ "detail": function (instance, action) {
638
+ this.detail_modal.show_instance(instance.id);
601
639
  },
602
- "update": function(instance, action){
603
- if(this.use_get_values_for_update){
604
- let url = this.config.urls.get_values_for_update_url.replace('/0/', '/'+instance.id+'/');
640
+ "update": function (instance, action) {
641
+ if (this.use_get_values_for_update) {
642
+ let url = this.config.urls.get_values_for_update_url.replace('/0/', '/' + instance.id + '/');
605
643
  this.retrieve_data(url, 'GET', this.update_value_success(this, instance));
606
- }else{
644
+ } else {
607
645
  this.update_value_success(this, instance)(instance);
608
646
  }
609
647
  },
610
- "update_value_success": function(instance, element){
611
- return function(data){
648
+ "update_value_success": function (instance, element) {
649
+ return function (data) {
612
650
  data = instance.config.events.update_data(data);
613
651
  instance.update_form.fill_form(data);
614
- instance.update_form.url = instance.base_update_url.replace('/0/', '/'+data.id+'/');
652
+ instance.update_form.url = instance.base_update_url.replace('/0/', '/' + data.id + '/');
615
653
  instance.update_form.show_modal();
616
654
  }
617
655
  },
618
- "action_update": function(action, data){},
619
- "action_destroy": function(action, data){},
620
- 'do_table_actions': function(action_position){
621
- var instance = this;
622
- if(action_position>=0 && action_position<instance.table_actions.length){
623
- let action=instance.table_actions[action_position];
624
- if(action.name in this){
656
+ "action_update": function (action, data) {
657
+ },
658
+ "action_destroy": function (action, data) {
659
+ },
660
+ 'do_table_actions': function (action_position) {
661
+ var instance = this;
662
+ if (action_position >= 0 && action_position < instance.table_actions.length) {
663
+ let action = instance.table_actions[action_position];
664
+ if (action.name in this) {
625
665
  this[action.name]({}, action);
626
- }else{
666
+ } else {
627
667
  this.do_action({}, action);
628
668
  }
629
- }
630
- },
631
- 'do_object_actions': function(action_position, instance_id){
632
- var instance = this;
633
- var data = this.datatable.row(instance_id).data(); ;
634
- if(action_position>=0 && action_position<instance.object_actions.length){
635
- let action=instance.object_actions[action_position];
636
- if(action.name in this){
669
+ }
670
+ },
671
+ 'do_object_actions': function (action_position, instance_id) {
672
+ var instance = this;
673
+ var data = this.datatable.row(instance_id).data();
674
+ ;
675
+ if (action_position >= 0 && action_position < instance.object_actions.length) {
676
+ let action = instance.object_actions[action_position];
677
+ if (action.name in this) {
637
678
  this[action.name](data, action);
638
- }else{
679
+ } else {
639
680
  this.do_action(data, action);
640
681
  }
641
- }
682
+ }
642
683
  },
643
- 'do_action': function(data, action){
684
+ 'do_action': function (data, action) {
644
685
  var instance = this;
645
686
  let method = 'method' in action ? action.method : 'POST';
646
687
  let body = 'data_fn' in action ? JSON.stringify(action.data_fn(data)) : '';
688
+ let url = 'url_fn' in action ? action.url_fn(data) : null;
647
689
  let error_fn = 'error_fn' in action ? action.error_fn : instance.error;
648
- if( 'url' in action && action.url !== null){
649
- fetch(action.url, {
650
- method: method,
651
- body: body,
652
- headers: this.config.headers
690
+ if (url == null && 'url' in action && action.url !== null) {
691
+ url = action.url;
692
+ }
693
+ if (url !== null) {
694
+ fetch(url, {
695
+ method: method,
696
+ body: body,
697
+ headers: this.config.headers
653
698
  }
654
699
  ).then(response_manage_type_data(instance, error_fn, instance.error_text))
655
- .then(instance.success(instance))
656
- .catch(error => instance.handle_error(instance, error));
700
+ .then(instance.success(instance))
701
+ .catch(error => instance.handle_error(instance, error));
657
702
  }
658
703
  },
659
- 'retrieve_data': function(url, method, success){
704
+ 'retrieve_data': function (url, method, success) {
660
705
  var instance = this;
661
706
  fetch(url, {
662
- method: method,
663
- headers:this.config.headers
664
- }).then(response_manage_type_data(instance, instance.error, instance.error_text))
707
+ method: method,
708
+ headers: this.config.headers
709
+ }).then(response_manage_type_data(instance, instance.error, instance.error_text))
665
710
  .then(success)
666
711
  .catch(error => instance.handle_error(instance, error));
667
712
  },
668
- "error_text": function(instance, message){
669
- Swal.fire({icon: 'error', title: gettext('Error'), text: message });
713
+ "error_text": function (instance, message) {
714
+ Swal.fire({icon: 'error', title: gettext('Error'), text: message});
670
715
  },
671
- "error": function(instance, errors){
672
- if(errors.hasOwnProperty('detail') && Object.keys(errors).length == 1){
673
- Swal.fire({ icon: 'error', title: gettext('Error'), text: errors.detail });
716
+ "error": function (instance, errors) {
717
+ if (errors.hasOwnProperty('detail') && Object.keys(errors).length == 1) {
718
+ Swal.fire({icon: 'error', title: gettext('Error'), text: errors.detail});
674
719
  }
675
720
  //instance.form.find('ul.form_errors').remove();
676
721
  //form_field_errors(instance.form, errors, instance.prefix);
677
722
  },
678
- "handle_error": function(instance, error){
723
+ "handle_error": function (instance, error) {
679
724
  let error_msg = gettext('There was a problem performing your request. Please try again later or contact the administrator.');
680
- Swal.fire({ icon: 'error', title: error_msg, text: error.message });
725
+ Swal.fire({icon: 'error', title: error_msg, text: error.message});
681
726
  },
682
- 'find_table_action_by_name': function(name){
683
- for(var x=0; x<this.table_actions.length; x++){
684
- if(this.table_actions[x].name === name){
727
+ 'find_table_action_by_name': function (name) {
728
+ for (var x = 0; x < this.table_actions.length; x++) {
729
+ if (this.table_actions[x].name === name) {
685
730
  return x;
686
731
  }
687
732
  }
688
733
  return undefined;
689
734
  },
690
- 'find_object_action_by_name': function(name){
691
- for(var x=0; x<this.object_actions.length; x++){
692
- if(this.object_actions[x].name === name){
735
+ 'find_object_action_by_name': function (name) {
736
+ for (var x = 0; x < this.object_actions.length; x++) {
737
+ if (this.object_actions[x].name === name) {
693
738
  return x;
694
739
  }
695
740
  }
@@ -701,21 +746,35 @@ function ObjectCRUD(uniqueid, objconfig={}){
701
746
  return obj;
702
747
  }
703
748
 
704
- function call_obj_crud_event(uniqueid, action_name, row_id){
705
- if(uniqueid in gt_crud_objs){
749
+ function call_obj_crud_event(uniqueid, action_name, row_id) {
750
+ if (uniqueid in gt_crud_objs) {
706
751
  let position = gt_crud_objs[uniqueid].find_object_action_by_name(action_name);
707
- if(position != undefined){
752
+ if (position != undefined) {
708
753
  gt_crud_objs[uniqueid].do_object_actions(position, row_id);
709
754
  }
710
755
  }
711
756
  }
712
757
 
713
- function call_table_crud_event(uniqueid, action_name){
714
- if(uniqueid in gt_crud_objs){
715
- let position = gt_crud_objs[uniqueid].find_table_action_by_name(action_name);
716
- if(position != undefined){
758
+ function call_table_crud_event(uniqueid, action_name) {
759
+ if (uniqueid in gt_crud_objs) {
760
+ let position = gt_crud_objs[uniqueid].find_table_action_by_name(action_name);
761
+ if (position != undefined) {
717
762
  gt_crud_objs[uniqueid].do_table_actions(position, 0);
718
- }
763
+ }
764
+ }
765
+ }
766
+
767
+ function truncateText(data, maxChars = 100) {
768
+
769
+ if (typeof data === 'string') {
770
+ const text = data.trim();
771
+ if (text.length > maxChars) {
772
+ return `<span title="${text.replace(/"/g, '&quot;')}" style="display:inline; line-height:1; margin:0; padding:0;">${text.substring(0, maxChars)}...</span>`;
773
+ }
774
+ return text
719
775
  }
776
+
777
+ return data;
720
778
  }
721
779
 
780
+