djgentelella 0.3.18__py3-none-any.whl → 0.3.20__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.
- djgentelella/__init__.py +1 -1
- djgentelella/blog/forms.py +3 -3
- djgentelella/fields/files.py +125 -0
- djgentelella/forms/decorators.py +3 -3
- djgentelella/forms/forms.py +153 -33
- djgentelella/forms/models.py +2 -2
- djgentelella/serializers/selects.py +32 -0
- djgentelella/settings.py +1 -1
- djgentelella/static/djgentelella.flags.vendors.min.css +1 -1
- djgentelella/static/djgentelella.readonly.vendors.min.js +1 -1
- djgentelella/static/djgentelella.vendors.header.min.js +1 -1
- djgentelella/static/djgentelella.vendors.min.js +3 -2
- djgentelella/static/gentelella/css/custom.css +42 -2
- djgentelella/static/gentelella/js/base/dateranges_gridslider.js +1 -2
- djgentelella/static/gentelella/js/base/fileupload.widget.js +175 -72
- djgentelella/static/gentelella/js/base.js +178 -75
- djgentelella/static/gentelella/js/datatables.js +20 -3
- djgentelella/static/gentelella/js/obj_api_management.js +150 -51
- djgentelella/static/gentelella/js/widgets.js +2 -1
- djgentelella/static/vendors/flags/1x1/cp.svg +2 -2
- djgentelella/static/vendors/flags/1x1/dg.svg +2 -2
- djgentelella/static/vendors/flags/1x1/es-ga.svg +2 -2
- djgentelella/static/vendors/flags/4x3/ac.svg +2 -2
- djgentelella/static/vendors/flags/4x3/ea.svg +2 -2
- djgentelella/static/vendors/flags/4x3/es-ct.svg +2 -2
- djgentelella/static/vendors/friconix/friconix.js +1 -1
- djgentelella/static/vendors/interact/interact.min.js +3 -2
- djgentelella/static/vendors/storymapjs/storymap.js +1 -1
- djgentelella/templates/forms/as_grid.html +39 -0
- djgentelella/templates/forms/as_horizontal.html +36 -0
- djgentelella/templates/forms/as_inline.html +38 -0
- djgentelella/templates/forms/as_plain.html +33 -0
- djgentelella/templates/gentelella/index.html +14 -14
- djgentelella/templates/gentelella/widgets/chunkedupload.html +9 -14
- djgentelella/templates/gentelella/widgets/file.html +4 -9
- djgentelella/tests/__init__.py +2 -1
- djgentelella/tests/fields/__init__.py +0 -0
- djgentelella/tests/fields/files.py +39 -0
- djgentelella/views/select2autocomplete.py +8 -2
- djgentelella/widgets/core.py +33 -0
- djgentelella/widgets/files.py +37 -8
- {djgentelella-0.3.18.dist-info → djgentelella-0.3.20.dist-info}/METADATA +30 -15
- {djgentelella-0.3.18.dist-info → djgentelella-0.3.20.dist-info}/RECORD +47 -39
- {djgentelella-0.3.18.dist-info → djgentelella-0.3.20.dist-info}/WHEEL +1 -1
- {djgentelella-0.3.18.dist-info → djgentelella-0.3.20.dist-info}/AUTHORS +0 -0
- {djgentelella-0.3.18.dist-info → djgentelella-0.3.20.dist-info}/LICENSE.txt +0 -0
- {djgentelella-0.3.18.dist-info → djgentelella-0.3.20.dist-info}/top_level.txt +0 -0
|
@@ -86,11 +86,21 @@ function addSearchInputsAndFooterDataTable(dataTable, tableId, columns) {
|
|
|
86
86
|
$(this).html(select);
|
|
87
87
|
}else if(columnType === 'select2'){
|
|
88
88
|
var s2url = dataTable.settings()[0].aoColumns[i].url;
|
|
89
|
-
|
|
89
|
+
let multiple = '';
|
|
90
|
+
if ('multiple' in dataTable.settings()[0].aoColumns[i]){
|
|
91
|
+
if(dataTable.settings()[0].aoColumns[i].multiple) multiple='multiple=True';
|
|
92
|
+
}
|
|
93
|
+
var select = '<select class="tableselect form-control form-control-sm" '+multiple+'><option value="">--</option>';
|
|
90
94
|
select += '</select>';
|
|
91
95
|
$(this).html(select);
|
|
92
96
|
let s2instance = $(this).find('select');
|
|
93
97
|
let s2context={
|
|
98
|
+
allowClear: true,
|
|
99
|
+
placeholder: {
|
|
100
|
+
id: "none",
|
|
101
|
+
text:"------",
|
|
102
|
+
selected:'selected'
|
|
103
|
+
},
|
|
94
104
|
ajax: { url: s2url, dataType: 'json'}
|
|
95
105
|
}
|
|
96
106
|
extract_select2_context(s2context, s2instance);
|
|
@@ -102,8 +112,14 @@ function addSearchInputsAndFooterDataTable(dataTable, tableId, columns) {
|
|
|
102
112
|
}
|
|
103
113
|
|
|
104
114
|
$('input, select', this).on('keyup change', function () {
|
|
105
|
-
|
|
106
|
-
|
|
115
|
+
let current_value=this.value;
|
|
116
|
+
if('multiple' in this && this.multiple){
|
|
117
|
+
let values=[];
|
|
118
|
+
$(this).find('option:selected').each(function(i,e){ values.push(e.value)});
|
|
119
|
+
current_value=values.toString();
|
|
120
|
+
}
|
|
121
|
+
if (currentColumn.search() !== current_value) {
|
|
122
|
+
currentColumn.search(current_value).draw();
|
|
107
123
|
}
|
|
108
124
|
});
|
|
109
125
|
}
|
|
@@ -120,6 +136,7 @@ function addSearchInputsAndFooterDataTable(dataTable, tableId, columns) {
|
|
|
120
136
|
function clearDataTableFilters(dataTable, tableId){
|
|
121
137
|
dataTable.search('').columns().search('').draw();
|
|
122
138
|
$(tableId).find('input, select').val('');
|
|
139
|
+
$(tableId).find('.tableselect').val(null).trigger('change');
|
|
123
140
|
}
|
|
124
141
|
function yesnoprint(data, type, row, meta){ return data ? "<i class=\"fa fa-check-circle\"></i> "+gettext("Yes") : "<i class=\"fa fa-times-circle\"></i>"+gettext("No"); };
|
|
125
142
|
function emptyprint(data, type, row, meta){ return data ? data : "--"; };
|
|
@@ -1,39 +1,76 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
function convertFileToBase64(file) {
|
|
2
|
+
return new Promise((resolve, reject) => {
|
|
3
|
+
const reader = new FileReader();
|
|
4
|
+
|
|
5
|
+
reader.onload = () => {
|
|
6
|
+
const base64String = reader.result.split(',')[1];
|
|
7
|
+
resolve(base64String);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
reader.onerror = (error) => {
|
|
11
|
+
reject(error);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
reader.readAsDataURL(file);
|
|
8
15
|
});
|
|
16
|
+
}
|
|
9
17
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
async function obtainFormAsJSON(form, prefix = '', extras={}) {
|
|
19
|
+
const fields = form.elements;
|
|
20
|
+
const formData = {};
|
|
21
|
+
// typeof variable === 'function'
|
|
22
|
+
for( let key in extras){
|
|
23
|
+
if(typeof extras[key] === 'function'){
|
|
24
|
+
formData[key]=extras[key](form, key, prefix);
|
|
25
|
+
}else{
|
|
26
|
+
formData[key]=extras[key];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
for (let i = 0; i < fields.length; i++) {
|
|
31
|
+
const field = fields[i];
|
|
32
|
+
|
|
33
|
+
if (field.type !== 'submit' && field.type !== 'button') {
|
|
34
|
+
const fieldName = field.name.replace(prefix, '');
|
|
35
|
+
if(field.type === 'textarea'){
|
|
36
|
+
formData[fieldName] = $(field).val();
|
|
37
|
+
}else if(field.type === 'checkbox'){
|
|
38
|
+
formData[fieldName] = field.checked;
|
|
39
|
+
}else if (field.type === 'radio') {
|
|
40
|
+
if(field.checked){
|
|
41
|
+
formData[fieldName] = $(field).val();
|
|
42
|
+
}
|
|
43
|
+
}else if (field.type === 'file') {
|
|
44
|
+
const files = Array.from(field.files);
|
|
45
|
+
const filesBase64 = [];
|
|
46
|
+
|
|
47
|
+
for (let j = 0; j < files.length; j++) {
|
|
48
|
+
const file = files[j];
|
|
49
|
+
try {
|
|
50
|
+
const base64String = await convertFileToBase64(file);
|
|
51
|
+
filesBase64.push({ name: file.name, value: base64String });
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error('Error converting file:', error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
formData[fieldName] = filesBase64;
|
|
58
|
+
} else if (field.multiple) {
|
|
59
|
+
const selectedOptions = Array.from(field.selectedOptions);
|
|
60
|
+
const selectedValues = selectedOptions.map((option) => option.value);
|
|
61
|
+
formData[fieldName] = selectedValues;
|
|
62
|
+
} else {
|
|
63
|
+
formData[fieldName] = field.value;
|
|
28
64
|
}
|
|
29
|
-
|
|
30
|
-
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return JSON.stringify(formData);
|
|
31
69
|
}
|
|
32
70
|
|
|
33
71
|
function convertToStringJson(form, prefix="", extras={}){
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return JSON.stringify(formjson);
|
|
72
|
+
result=obtainFormAsJSON(form[0], prefix=prefix, extras={});
|
|
73
|
+
return result;
|
|
37
74
|
}
|
|
38
75
|
|
|
39
76
|
function load_errors(error_list, obj){
|
|
@@ -85,11 +122,19 @@ function clear_action_form(form){
|
|
|
85
122
|
$(this).trigger("click").prop("checked", false);
|
|
86
123
|
}
|
|
87
124
|
});
|
|
88
|
-
|
|
125
|
+
$(form).find('[data-widget="TaggingInput"],[data-widget="EmailTaggingInput"]').each(function(i, e) {
|
|
126
|
+
var tg=$(e).data().tagify;
|
|
127
|
+
tg.removeAllTags();
|
|
128
|
+
});
|
|
129
|
+
$(form).find('[data-widget="FileChunkedUpload"],[data-widget="FileInput"]').each(function(i, e) {
|
|
130
|
+
var tg=$(e).data().fileUploadWidget;
|
|
131
|
+
tg.resetEmpty();
|
|
132
|
+
});
|
|
89
133
|
$(form).trigger('reset');
|
|
90
134
|
$(form).find("select option:selected").prop("selected", false);
|
|
91
135
|
$(form).find("select").val(null).trigger('change');
|
|
92
136
|
$(form).find("ul.form_errors").remove();
|
|
137
|
+
$(form).find(".file-link").remove();
|
|
93
138
|
}
|
|
94
139
|
|
|
95
140
|
var gt_form_modals = {}
|
|
@@ -148,19 +193,21 @@ function GTBaseFormModal(modal_id, datatable_element, form_config) {
|
|
|
148
193
|
var myModalEl = this.instance[0];
|
|
149
194
|
myModalEl.addEventListener('hidden.bs.modal', this.hide_modalevent(this))
|
|
150
195
|
this.instance.find(this.btn_class).on('click', this.add_btn_form(this));
|
|
151
|
-
|
|
196
|
+
$(this.form).on('submit', (e)=>{e.preventDefault();})
|
|
152
197
|
},
|
|
153
198
|
"add_btn_form": function(instance){
|
|
154
199
|
return function(event){
|
|
155
|
-
|
|
200
|
+
convertToStringJson(instance.form, prefix=instance.prefix,
|
|
201
|
+
extras=instance.config.events.form_submit(instance)).then((result) => {
|
|
202
|
+
fetch(instance.url, {
|
|
156
203
|
method: instance.type,
|
|
157
|
-
body:
|
|
158
|
-
extras=instance.config.events.form_submit(instance)),
|
|
204
|
+
body: result,
|
|
159
205
|
headers: {'X-CSRFToken': getCookie('csrftoken'), 'Content-Type': 'application/json'}
|
|
160
206
|
}
|
|
161
207
|
).then(response_manage_type_data(instance, instance.error, instance.error_text))
|
|
162
208
|
.then(instance.fn_success(instance))
|
|
163
209
|
.catch(error => instance.handle_error(instance, error));
|
|
210
|
+
});
|
|
164
211
|
}
|
|
165
212
|
},
|
|
166
213
|
"success": function(instance, data){
|
|
@@ -223,7 +270,7 @@ function GTBaseFormModal(modal_id, datatable_element, form_config) {
|
|
|
223
270
|
});
|
|
224
271
|
// do select 2 items
|
|
225
272
|
$.each(select2Items, function(i, e){
|
|
226
|
-
var display_name_key = '
|
|
273
|
+
var display_name_key = 'text';
|
|
227
274
|
if(instance.relation_render.hasOwnProperty(e)){
|
|
228
275
|
display_name_key=instance.relation_render[e];
|
|
229
276
|
}
|
|
@@ -231,6 +278,7 @@ function GTBaseFormModal(modal_id, datatable_element, form_config) {
|
|
|
231
278
|
if(datainstance[e]){
|
|
232
279
|
if(Array.isArray(datainstance[e])){
|
|
233
280
|
for(var x=0; x<datainstance[e].length; x++){
|
|
281
|
+
$('#id_'+instance.prefix+e+' option[value="'+datainstance[e][x]['id']+'"]').remove();
|
|
234
282
|
var newOption = new Option(datainstance[e][x][display_name_key], datainstance[e][x]['id'], true, true);
|
|
235
283
|
$('#id_'+instance.prefix+e).append(newOption);
|
|
236
284
|
}
|
|
@@ -248,22 +296,67 @@ function GTBaseFormModal(modal_id, datatable_element, form_config) {
|
|
|
248
296
|
},
|
|
249
297
|
"updateInstanceForm": function (name, value){
|
|
250
298
|
var item = this.form.find('input[name="'+name+'"], textarea[name="'+name+'"]');
|
|
251
|
-
|
|
299
|
+
var parent=this;
|
|
252
300
|
item.each(function(i, inputfield){
|
|
253
301
|
let done=false;
|
|
254
302
|
inputfield=$(inputfield);
|
|
255
|
-
|
|
256
|
-
|
|
303
|
+
|
|
304
|
+
if(inputfield.attr('class') === "chunkedvalue"){
|
|
305
|
+
if(value){
|
|
306
|
+
var chunked=parent.form.find('input[name="'+name+'_widget"]').data('fileUploadWidget');
|
|
307
|
+
chunked.addRemote(value);
|
|
308
|
+
}
|
|
309
|
+
done=true;
|
|
310
|
+
} else if(inputfield.attr('type') === 'file'){
|
|
311
|
+
if(value){
|
|
312
|
+
var newlink = document.createElement('a');
|
|
313
|
+
newlink.href = value.url;
|
|
314
|
+
newlink.textContent = value.name;
|
|
315
|
+
newlink.target = "_blank";
|
|
316
|
+
newlink.classList.add("link-primary");
|
|
317
|
+
newlink.classList.add("file-link");
|
|
318
|
+
newlink.classList.add("d-block");
|
|
319
|
+
inputfield.before(newlink)
|
|
320
|
+
}
|
|
321
|
+
done=true;
|
|
322
|
+
} else if(inputfield.attr('type') === "checkbox" ){
|
|
323
|
+
if (inputfield.data().widget === "YesNoInput"){
|
|
324
|
+
inputfield.prop( "checked", !value);
|
|
325
|
+
inputfield.trigger("click");
|
|
326
|
+
done=true;
|
|
327
|
+
}else{
|
|
328
|
+
inputfield.prop( "checked", value);
|
|
329
|
+
}
|
|
257
330
|
done=true;
|
|
258
331
|
} else if(inputfield.attr('type') === "radio"){
|
|
259
|
-
var
|
|
260
|
-
sel.
|
|
332
|
+
var is_icheck = inputfield.closest('.gtradio').length > 0;
|
|
333
|
+
var sel = inputfield.filter(function() { return this.value === value.toString() });
|
|
334
|
+
if(sel.length>0){
|
|
335
|
+
sel.prop( "checked", true);
|
|
336
|
+
if(is_icheck){
|
|
337
|
+
sel.iCheck('update');
|
|
338
|
+
sel.iCheck('check');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
}else{
|
|
342
|
+
inputfield.prop( "checked", false);
|
|
343
|
+
if(is_icheck){
|
|
344
|
+
inputfield.iCheck('update');
|
|
345
|
+
inputfield.iCheck('uncheck');
|
|
346
|
+
}
|
|
347
|
+
}
|
|
261
348
|
done=true;
|
|
262
349
|
}
|
|
263
|
-
if (inputfield.data().widget === "EditorTinymce"){
|
|
350
|
+
if (inputfield.data().widget === "EditorTinymce" || inputfield.data().widget === "TextareaWysiwyg"){
|
|
264
351
|
tinymce.get(inputfield.attr('id')).setContent(value);
|
|
265
352
|
done=true;
|
|
266
353
|
}
|
|
354
|
+
if (inputfield.data().widget === "TaggingInput" || inputfield.data().widget === "EmailTaggingInput"){
|
|
355
|
+
var tagifyelement=inputfield.data().tagify;
|
|
356
|
+
tagifyelement.removeAllTags();
|
|
357
|
+
tagifyelement.loadOriginalValues(value);
|
|
358
|
+
done=true;
|
|
359
|
+
}
|
|
267
360
|
if(!done) { inputfield.val(value); }
|
|
268
361
|
});
|
|
269
362
|
}
|
|
@@ -583,19 +676,25 @@ function ObjectCRUD(uniqueid, objconfig={}){
|
|
|
583
676
|
className: this.config.actions.className,
|
|
584
677
|
orderable: false,
|
|
585
678
|
render: function(data, type, full, meta){
|
|
586
|
-
|
|
679
|
+
var edittext = '<div class="d-flex mt-1">';
|
|
680
|
+
let do_action=true;
|
|
587
681
|
for(var x=0; x<instance.object_actions.length; x++){
|
|
588
682
|
let action = instance.object_actions[x];
|
|
589
683
|
let display_in_column = true;
|
|
590
|
-
|
|
591
|
-
|
|
684
|
+
do_action=true
|
|
685
|
+
if(action.name in data ){
|
|
686
|
+
do_action=data[action.name];
|
|
687
|
+
}
|
|
688
|
+
if(do_action){
|
|
689
|
+
if('in_action_column' in action ){
|
|
690
|
+
display_in_column=action.in_action_column;
|
|
691
|
+
}
|
|
692
|
+
if(display_in_column){
|
|
693
|
+
let params = "'"+instance.uniqueid+"', '"+action.name+"', "+meta.row;
|
|
694
|
+
edittext += '<i onclick="javascript:call_obj_crud_event('+params+');"';
|
|
695
|
+
edittext += ' class="'+instance.object_actions[x].i_class+'" ></i>';
|
|
696
|
+
}
|
|
592
697
|
}
|
|
593
|
-
if(display_in_column){
|
|
594
|
-
let params = "'"+instance.uniqueid+"', '"+action.name+"', "+meta.row;
|
|
595
|
-
edittext += '<i onclick="javascript:call_obj_crud_event('+params+');"';
|
|
596
|
-
edittext += ' class="'+instance.object_actions[x].i_class+'" ></i>';
|
|
597
|
-
}
|
|
598
|
-
|
|
599
698
|
}
|
|
600
699
|
edittext += '</div>';
|
|
601
700
|
return edittext;
|
|
@@ -52,6 +52,7 @@ document.gtwidgets = {
|
|
|
52
52
|
YesNoInput: function (instance) {
|
|
53
53
|
instance.each(function (index, element) {
|
|
54
54
|
switchery = new Switchery(element, { color: '#26B99A' });
|
|
55
|
+
instance.data('switchery', switchery);
|
|
55
56
|
showHideRelatedFormFields($(element));
|
|
56
57
|
});
|
|
57
58
|
},
|
|
@@ -138,7 +139,7 @@ document.gtwidgets = {
|
|
|
138
139
|
},
|
|
139
140
|
EmailMaskInput: function (instance) {
|
|
140
141
|
instance.inputmask({
|
|
141
|
-
|
|
142
|
+
regex: "[a-zA-Z0-9._%-]+@[a-zA-Z0-9-]+(\.[a-zA-Z]+)+",
|
|
142
143
|
greedy: false,
|
|
143
144
|
onBeforePaste: function (pastedValue, opts) {
|
|
144
145
|
pastedValue = pastedValue.toLowerCase();
|