Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 17337 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
15333 stevensc 1
<?php
2
 
1 www 3
use LeadersLinked\Model\CompanyUser;
4
 
5
$acl            = $this->viewModel()->getRoot()->getVariable('acl');
6
$currentUser    = $this->currentUserHelper();
7
 
8
$roleName = $currentUser->getUserTypeId();
9
 
10
//$routeAdd       = $this->url('users/add');
11
$routeDatatable = $this->url('users');
12
$routeInvite    = $this->url('users/invite');
13
$routeUpload    = $this->url('users/upload');
14
 
15
$allowInvite            = $acl->isAllowed($roleName, 'users/invite') ? 1 : 0;
16
$allowAccept            = $acl->isAllowed($roleName, 'users/accept') ? 1 : 0;
17
$allowCancel            = $acl->isAllowed($roleName, 'users/cancel') ? 1 : 0;
18
$allowReject            = $acl->isAllowed($roleName, 'users/reject') ? 1 : 0;
19
$allowEdit              = $acl->isAllowed($roleName, 'users/edit') ? 1 : 0;
20
$allowUpload            = $acl->isAllowed($roleName, 'users/upload') ? 1 : 0;
21
$allowChangePassword    = $acl->isAllowed($roleName, 'users/change-password') ? 1 : 0;
22
$allowUnblock           = $acl->isAllowed($roleName, 'users/unblock') ? 1 : 0;
23
 
24
 
17333 stevensc 25
// Popper
16822 efrain 26
$this->inlineScript()->appendFile($this->basePath('assets/vendors/popper/umd/popper.js'));
17333 stevensc 27
 
28
// NProgress
16822 efrain 29
$this->headLink()->appendStylesheet($this->basePath('assets/vendors/nprogress/nprogress.css'));
30
$this->inlineScript()->appendFile($this->basePath('assets/vendors/nprogress/nprogress.js'));
1 www 31
 
17333 stevensc 32
// CKEditor
16822 efrain 33
$this->inlineScript()->appendFile($this->basePath('assets/vendors/ckeditor/ckeditor.js'));
1 www 34
 
17333 stevensc 35
// Datatables
16822 efrain 36
$this->headLink()->appendStylesheet($this->basePath('assets/vendors/datatables.net-bs5/dataTables.bootstrap5.css'));
16912 efrain 37
$this->headLink()->appendStylesheet($this->basePath('assets/vendors/datatables.net-bs5-responsive/responsive.bootstrap5.css'));
16822 efrain 38
$this->inlineScript()->appendFile($this->basePath('assets/vendors/datatables.net/jquery.dataTables.js'));
39
$this->inlineScript()->appendFile($this->basePath('assets/vendors/datatables.net-bs5/dataTables.bootstrap5.js'));
16912 efrain 40
$this->inlineScript()->appendFile($this->basePath('assets/vendors/datatables.net-bs5-responsive/dataTables.responsive.min.js'));
41
$this->inlineScript()->appendFile($this->basePath('assets/vendors/datatables.net-bs5-responsive/responsive.bootstrap5.min.js'));
1 www 42
 
17333 stevensc 43
// Toggle
16822 efrain 44
$this->headLink()->appendStylesheet($this->basePath('assets/vendors/bootstrap4-toggle/css/bootstrap4-toggle.min.css'));
45
$this->inlineScript()->appendFile($this->basePath('assets/vendors/bootstrap4-toggle/js/bootstrap4-toggle.min.js'));
1 www 46
 
17333 stevensc 47
// Autocomplete
48
$this->inlineScript()->appendFile($this->basePath('assets/vendors/bootstrap-autocomplete/bootstrap-autocomplete.min.js'));
1 www 49
 
17333 stevensc 50
// File input
16822 efrain 51
$this->headLink()->appendStylesheet($this->basePath('assets/vendors/bootstrap-fileinput/css/fileinput.min.css'));
52
$this->headLink()->appendStylesheet($this->basePath('assets/vendors/bootstrap-fileinput/themes/explorer-fa/theme.css'));
16843 efrain 53
$this->inlineScript()->appendFile($this->basePath('assets/vendors/bootstrap-fileinput/js/plugins/piexif.js'));
54
$this->inlineScript()->appendFile($this->basePath('assets/vendors/bootstrap-fileinput/js/plugins/sortable.js'));
16822 efrain 55
$this->inlineScript()->appendFile($this->basePath('assets/vendors/bootstrap-fileinput/js/fileinput.js'));
56
$this->inlineScript()->appendFile($this->basePath('assets/vendors/bootstrap-fileinput/js/locales/es.js'));
57
$this->inlineScript()->appendFile($this->basePath('assets/vendors/bootstrap-fileinput/themes/fa/theme.js'));
58
$this->inlineScript()->appendFile($this->basePath('assets/vendors/bootstrap-fileinput/themes/explorer-fa/theme.js'));
59
 
16954 efrain 60
 
1 www 61
$this->headStyle()->captureStart();
16954 efrain 62
echo <<<CSS
1 www 63
 
16954 efrain 64
 
65
#gridTableUsers {
66
    display: flex;
67
    flex-flow: column;
68
    width: 100%;
69
}
70
 
71
#gridTableUsers thead {
72
    flex: 0 0 auto;
73
}
74
 
75
#gridTableUsers tbody {
76
    flex: 1 1 auto;
77
    display: block;
78
    overflow-y: auto;
79
    overflow-x: hidden;
80
}
81
 
82
#gridTableUsers tr {
83
    width: 100%;
84
    display: table;
85
    table-layout: fixed;
86
}
87
 
88
CSS;
89
$this->headStyle()->captureEnd();
90
 
1 www 91
$this->inlineScript()->captureStart();
92
echo <<<JS
93
    jQuery( document ).ready(function( $ ) {
94
        $.validator.addMethod('passwordStrengthCheck', function(value) {
95
            return /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$^x%x*-]).{6,16}$/.test(value)
96
        }, 'ERROR_PASSWORD_STRENGTH');
97
 
98
        $.validator.setDefaults({
99
            debug: true,
100
            highlight: function(element) {
101
                $(element).closest('.sn-field').addClass('sn-field-has-error');
102
            },
103
            unhighlight: function(element) {
104
                $(element).closest('.sn-field').removeClass('sn-field-has-error');
105
            },
106
            errorElement: 'div',
107
            errorClass: 'sn-field-invalid-feedback',
108
            errorPlacement: function(error, element) {
109
 
110
                if(element.parent('.sn-field').length) {
111
                    error.insertAfter(element.parent());
112
                } else if (element.parent('.fgt-sec').length) {
113
                    error.insertAfter(element.parent());
114
                } else {
115
                    error.insertAfter(element);
116
                }
117
            }
118
        });
119
 
120
 
121
        var allowInvite = $allowInvite;
122
        var allowAccept = $allowAccept;
123
        var allowCancel = $allowCancel;
124
        var allowReject = $allowReject;
125
        var allowEdit  = $allowEdit;
126
        var allowUpload = $allowUpload;
127
        var allowChangePassword = $allowChangePassword;
128
        var allowUnblock = $allowUnblock;
129
 
130
        var gridTable = $('#gridTable').dataTable( {
131
            'processing': true,
132
            'serverSide': true,
133
            'searching': true,
134
            'order': [[ 0, 'asc' ]],
135
            'ordering':  true,
136
            'ordenable' : true,
137
            'responsive': true,
138
            'select' : false,
139
        	'paging': true,
140
            'pagingType': 'simple_numbers',
141
    		'ajax': {
142
    			'url' : '$routeDatatable',
143
    			'type' : 'get',
144
                'data' : function(data) {
145
                    data.status = $('#form-filter #status').val();
146
                } ,
147
                'beforeSend': function (request) {
148
                  NProgress.start();
149
                },
150
                'dataFilter': function(response) {
151
                    var response = jQuery.parseJSON( response );
152
 
153
                    var json                = {};
154
                    json.recordsTotal       = 0;
155
                    json.recordsFiltered    = 0;
156
                    json.data               = [];
157
 
158
 
159
                    if(response.success) {
160
                        json.recordsTotal       = response.data.total;
161
                        json.recordsFiltered    = response.data.total;
162
                        json.data               = response.data.items;
163
                    } else {
164
                        $.fn.showError(response.data)
165
                    }
166
 
167
                    return JSON.stringify( json );
168
                }
169
    		},
170
            'language' : {
171
                'sProcessing':     'LABEL_DATATABLE_SPROCESSING',
172
                'sLengthMenu':     'LABEL_DATATABLE_SLENGTHMENU',
173
                'sZeroRecords':    'LABEL_DATATABLE_SZERORECORDS',
174
                'sEmptyTable':     'LABEL_DATATABLE_SEMPTYTABLE',
175
                'sInfo':           'LABEL_DATATABLE_SINFO',
176
                'sInfoEmpty':      'LABEL_DATATABLE_SINFOEMPTY',
177
                'sInfoFiltered':   'LABEL_DATATABLE_SINFOFILTERED',
178
                'sInfoPostFix':    '',
179
                'sSearch':         'LABEL_DATATABLE_SSEARCH',
180
                'sUrl':            '',
181
                'sInfoThousands':  ',',
182
                'sLoadingRecords': 'LABEL_DATATABLE_SLOADINGRECORDS',
183
                'oPaginate': {
184
                    'sFirst':    'LABEL_DATATABLE_SFIRST',
185
                    'sLast':     'LABEL_DATATABLE_SLAST',
186
                    'sNext':     'LABEL_DATATABLE_SNEXT',
187
                    'sPrevious': 'LABEL_DATATABLE_SPREVIOUS'
188
                },
189
                'oAria': {
190
                    'sSortAscending':  ': LABEL_DATATABLE_SSORTASCENDING',
191
                    'sSortDescending': ':LABEL_DATATABLE_SSORTDESCENDING'
192
                },
193
            },
194
            'drawCallback': function( settings ) {
195
                NProgress.done();
16822 efrain 196
 
1 www 197
            },
198
            'aoColumns': [
199
                { 'mDataProp': 'first_name' },
200
                { 'mDataProp': 'last_name' },
201
                { 'mDataProp': 'email' },
202
                { 'mDataProp': 'details' },
203
                { 'mDataProp': 'actions' },
204
    	    ],
205
            'columnDefs': [
206
                {
207
                    'targets': 0,
208
                    'className' : 'text-vertical-middle',
209
                },
210
                {
211
                    'targets': 1,
212
                    'className' : 'text-vertical-middle',
213
                },
214
                {
215
                    'targets': 2,
216
                    'className' : 'text-vertical-middle',
217
                },
218
                {
219
                    'targets': -2,
220
                    'orderable': false,
221
                    'render' : function ( data, type, row ) {
222
                        var s =  '';
223
                        s = s + 'LABEL_STATUS : <br>' + data['status'] + '<br>';
224
                        s = s + 'LABEL_ACCESS_BACKEND : ' + data['backend'] + '<br>';
225
                        s = s + 'LABEL_CREATOR : ' + data['creator'] + '<br>';
226
 
227
                        s = s + 'LABEL_EDIT : <br>';
228
 
229
                        $.each(data['roles'], function(i, role) {
230
                            s = s + role + '<br>';
231
                        });
232
 
233
                        s = s + 'LABEL_BLOCKED : ' + data['blocked'] + '<br>';
234
                        s = s + 'LABEL_EMAIL_VERIFIED : ' + data['email_verified'] + '<br>';
235
                        s = s + 'LABEL_LOGIN_ATTEMP : ' + data['login_attempt'] + '<br>';
236
                        return s;
237
                    }
238
                },
239
                {
240
                    'targets': -1,
241
                    'orderable': false,
242
                    'render' : function ( data, type, row ) {
243
                        s = '';
15333 stevensc 244
 
245
                        $('#gridTable_wrapper .row:nth-child(2) .col-sm-12').addClass( "table table-responsive" );
1 www 246
 
247
                        if(allowAccept && data['link_accept']) {
16822 efrain 248
                            s = s + '<button class="btn btn-sm btn-accept btn-primary" style="margin-top: 5px" data-href="' + data['link_accept']+ '" data-toggle="tooltip" title="LABEL_ACCEPT"><i class="fa fa-check"></i> LABEL_ACCEPT </button><br>';
1 www 249
                        }
15261 stevensc 250
                        if(allowEdit && data['link_edit']) {
16906 efrain 251
                            s = s + '<button class="btn btn-sm btn-edit btn-primary" style="margin-top: 5px" data-href="' + data['link_edit']+ '" data-toggle="tooltip" title="LABEL_EDIT"><i class="fa fa-pen"></i> LABEL_EDIT </button><br>';
15261 stevensc 252
                        }
1 www 253
                        if(allowCancel && data['link_cancel']) {
16822 efrain 254
                            s = s + '<button class="btn btn-sm btn-cancel btn-danger" style="margin-top: 5px" data-href="' + data['link_cancel']+ '" data-toggle="tooltip" data-singleton="true" title="LABEL_CANCEL"><i class="fa fa-times"></i> LABEL_CANCEL </button><br>';
1 www 255
                        }
256
                        if(allowReject && data['link_reject']) {
16822 efrain 257
                            s = s + '<button class="btn btn-sm btn-reject btn-danger" style="margin-top: 5px" data-href="' + data['link_reject']+ '" data-toggle="tooltip" title="LABEL_REJECT"><i class="fa fa-times"></i> LABEL_REJECT </button><br>';
1 www 258
                        }
259
 
260
                        if(allowChangePassword && data['link_change_password']) {
16822 efrain 261
                            s = s + '<button class="btn btn-sm btn-primary btn-change-password" style="margin-top: 5px" data-href="' + data['link_change_password']+ '" data-toggle="tooltip" title="LABEL_CHANGE_PASSWORD"><i class="fa fa-key"></i> LABEL_PASSWORD </button><br>';
1 www 262
                        }
263
                        if(allowUnblock && data['link_unblock']) {
16822 efrain 264
                            s = s + '<button class="btn btn-sm btn-info btn-unblock" style="margin-top: 5px" data-href="' + data['link_unblock']+ '" data-toggle="tooltip" title="LABEL_UNBLOCK"><i class="fa fa-unlock"></i> LABEL_UNBLOCK </button><br>';
1 www 265
                        }
266
 
267
 
268
                        return s;
269
                    }
270
                }
271
 
272
            ],
273
        });
274
 
275
 
276
        $('#form-filter #status').change(function(e) {
277
            e.preventDefault();
278
            gridTable.api().ajax.reload(null, false);
279
        });
280
 
281
 
282
        $('body').on('click', 'button.btn-refresh', function(e) {
283
            e.preventDefault();
284
            gridTable.api().ajax.reload(null, false);
285
        });
286
 
16822 efrain 287
    $('body').on('click', 'button.btn-unblock', function(e) {
288
        e.preventDefault();
289
        var action = $(this).data('href');
1 www 290
 
291
 
16822 efrain 292
          swal.fire({
293
            title: 'LABEL_ARE_YOU_SURE',
294
            icon: 'question',
295
            cancelButtonText: 'LABEL_NO',
296
            showCancelButton: true,
297
            confirmButtonText: 'LABEL_YES'
298
          }).then((result) => {
299
            if (result.isConfirmed) {
1 www 300
 
16822 efrain 301
                    NProgress.start();
302
                    $.ajax({
303
                        'dataType'  : 'json',
304
                        'accept'    : 'application/json',
305
                        'method'    : 'post',
306
                        'url'       :  action,
307
                    }).done(function(response) {
308
                        if(response['success']) {
309
                            $.fn.showSuccess(response['data']);
310
                            gridTable.api().ajax.reload(null, false);
311
                        } else {
312
                            $.fn.showError(response['data']);
313
                        }
314
                    }).fail(function( jqXHR, textStatus, errorThrown) {
315
                        $.fn.showError(textStatus);
316
                    }).always(function() {
317
                        NProgress.done();
318
                    });
319
            }
320
       });
321
    });
1 www 322
 
16822 efrain 323
 $('body').on('click', 'button.btn-reject', function(e) {
324
        e.preventDefault();
325
        var action = $(this).data('href');
326
 
327
 
328
          swal.fire({
329
            title: 'LABEL_ARE_YOU_SURE',
330
            icon: 'question',
331
            cancelButtonText: 'LABEL_NO',
332
            showCancelButton: true,
333
            confirmButtonText: 'LABEL_YES'
334
          }).then((result) => {
335
            if (result.isConfirmed) {
336
 
337
                    NProgress.start();
338
                    $.ajax({
339
                        'dataType'  : 'json',
340
                        'accept'    : 'application/json',
341
                        'method'    : 'post',
342
                        'url'       :  action,
343
                    }).done(function(response) {
344
                        if(response['success']) {
345
                            $.fn.showSuccess(response['data']);
346
                            gridTable.api().ajax.reload(null, false);
347
                        } else {
348
                            $.fn.showError(response['data']);
349
                        }
350
                    }).fail(function( jqXHR, textStatus, errorThrown) {
351
                        $.fn.showError(textStatus);
352
                    }).always(function() {
353
                        NProgress.done();
354
                    });
355
            }
356
       });
357
    });
358
 
359
 $('body').on('click', 'button.btn-cancel', function(e) {
360
        e.preventDefault();
361
        var action = $(this).data('href');
362
 
363
 
364
          swal.fire({
365
            title: 'LABEL_ARE_YOU_SURE',
366
            icon: 'question',
367
            cancelButtonText: 'LABEL_NO',
368
            showCancelButton: true,
369
            confirmButtonText: 'LABEL_YES'
370
          }).then((result) => {
371
            if (result.isConfirmed) {
372
 
373
                    NProgress.start();
374
                    $.ajax({
375
                        'dataType'  : 'json',
376
                        'accept'    : 'application/json',
377
                        'method'    : 'post',
378
                        'url'       :  action,
379
                    }).done(function(response) {
380
                        if(response['success']) {
381
                            $.fn.showSuccess(response['data']);
382
                            gridTable.api().ajax.reload(null, false);
383
                        } else {
384
                            $.fn.showError(response['data']);
385
                        }
386
                    }).fail(function( jqXHR, textStatus, errorThrown) {
387
                        $.fn.showError(textStatus);
388
                    }).always(function() {
389
                        NProgress.done();
390
                    });
391
            }
392
       });
393
    });
394
 
395
 
1 www 396
        $('body').on('click', 'button.btn-invite', function(e) {
397
            e.preventDefault();
16926 efrain 398
 
17330 ariadna 399
            // Limpiar el campo antes de abrir el modal
400
            $('#form-invite #user_uuid').val('');
1 www 401
            $('#form-invite #user_uuid_selected').val('');
17330 ariadna 402
 
403
            // Abrir el modal
1 www 404
            $('#modalInvite').modal('show');
405
        });
406
 
407
        $('body').on('click', 'button.btn-accept', function(e) {
408
            e.preventDefault();
409
            action = $(this).data('href');
410
            NProgress.start();
411
            $.ajax({
412
                'dataType'  : 'json',
413
                'accept'    : 'application/json',
414
                'method'    : 'post',
415
                'url'       :  action
416
            }).done(function(response) {
417
                if(response['success']) {
418
                    $.fn.showSuccess(response['data']);
419
                    gridTable.api().ajax.reload(null, false);
420
                } else {
421
                    $.fn.showError(response['data']);
422
                }
423
            }).fail(function( jqXHR, textStatus, errorThrown) {
424
                $.fn.showError(textStatus);
425
            }).always(function() {
426
                NProgress.done();
427
            });
428
        });
429
 
17330 ariadna 430
        // Inicializar autoComplete para el campo de búsqueda de usuarios
17335 stevensc 431
        function initializeAutoComplete() {
17330 ariadna 432
            if (typeof $.fn.autoComplete === 'undefined') {
433
                console.error('autoComplete library not loaded!');
434
                return;
435
            }
436
 
17336 stevensc 437
            // Destruir instancia anterior si existe
438
            if ($('#form-invite #user_uuid').data('autoComplete')) {
439
                $('#form-invite #user_uuid').autoComplete('clear');
440
            }
441
 
17330 ariadna 442
            $('#form-invite #user_uuid').autoComplete({
443
                resolver: 'custom',
444
                minLength: 3,
445
                noResultsText: 'LABEL_AUTOCOMPLETE_USERS_NOT_FOUND',
446
                events: {
447
                    search: function (qry, callback) {
448
                        console.log('Searching for:', qry); // Debug
449
                        NProgress.start();
450
                        $.ajax({
451
                            'url' : '$routeInvite',
452
                            'method': 'get',
453
                            'data': { 'search': qry },
454
                            'dataType': 'json'
455
                        }).done(function (response) {
456
                            console.log('Response:', response); // Debug
457
                            if(response.success) {
17338 stevensc 458
                                $(".bootstrap-autocomplete.dropdown-menu").toggleClass('show');
17330 ariadna 459
                                callback(response.data);
460
                            } else {
461
                                console.error('Search error:', response.data); // Debug
462
                                $.fn.showError(response.data);
17329 ariadna 463
                                callback([]);
17330 ariadna 464
                            }
465
                        }).fail(function( jqXHR, textStatus, errorThrown) {
466
                            console.error('AJAX error:', textStatus, errorThrown); // Debug
467
                            $.fn.showError(textStatus);
468
                            callback([]);
469
                        }).always(function() {
470
                            NProgress.done();
471
                        });
17329 ariadna 472
                    }
17330 ariadna 473
                }
474
            });
475
            console.log('autoComplete initialized successfully'); // Debug
476
        }
477
 
478
        // Inicializar cuando el documento esté listo
479
        initializeAutoComplete();
1 www 480
 
481
	    $('#form-invite #user_uuid').on('autocomplete.select', function (evt, item) {
17330 ariadna 482
            console.log('Item selected:', item); // Debug
483
            $('#form-invite #user_uuid_selected').val(item.value);
484
            console.log('Hidden field value set to:', item.value); // Debug
1 www 485
        });
486
 
487
        var validatorFormInvite = $('#form-invite').validate({
488
            debug: true,
489
            onclick: false,
490
            onkeyup: false,
491
            ignore: [':hidden'],
492
            rules: {
493
 
494
                'user_uuid': {
495
                    required: true,
496
                },
497
            },
498
            submitHandler: function(form)
499
            {
500
                NProgress.start();
501
                $.ajax({
502
                    'dataType'  : 'json',
503
                    'accept'    : 'application/json',
504
                    'method'    : 'post',
505
                    'url'       : '$routeInvite',
506
                    'data'      : {
507
                        'id' : $('#form-invite #user_uuid_selected').val(),
508
                    }
509
                 }).done(function(response) {
510
                    if(response.success) {
511
                        $.fn.showSuccess(response.data);
512
 
513
                        $('#modalInvite').modal('hide');
514
                         gridTable.api().ajax.reload(null, false);
515
                    } else {
516
                        if(jQuery.type(response.data) == 'string') {
517
                            $.fn.showError(response.data)
518
                        } else  {
519
                            $.each(response.data, function( fieldname, errors ) {
520
                                $.fn.showFormErrorValidator('#form-invite #' + fieldname, errors);
521
                            });
522
                        }
523
                    }
524
                }).fail(function( jqXHR, textStatus, errorThrown) {
525
                    $.fn.showError(textStatus)
526
 
527
                }).always(function() {
528
                    NProgress.done();
529
                })
530
            },
531
            invalidHandler: function(form, validator) {
532
            }
533
        });
534
 
15460 efrain 535
    var validatorUploadUsers = $('#form-upload-users').validate({
1 www 536
        debug: true,
537
        onclick: false,
538
        onkeyup: false,
539
        onfocusout: false,
540
        ignore: [],
541
        rules: {
542
            'file' : {
543
                required: true,
544
                extension: 'xls|xlsx',
545
                accept: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel'
546
            },
547
        },
548
 
549
        submitHandler: function(form)
550
        {
551
            NProgress.start();
552
            var formdata = false;
553
            if (window.FormData){
554
                formdata = new FormData(form);
555
            }
556
            formdata.append('step','validation');
557
 
558
 
559
            $.ajax({
560
                'dataType'  : 'json',
561
                'accept'    : 'application/json',
562
                'method'    : 'post',
563
                'url'       : '$routeUpload',
564
                'data'      :  formdata,
565
                'processData': false,
566
                'contentType': false,
567
            }).done(function(response) {
568
                if(response['success']) {
569
 
570
                    $('#table-upload-users-key').val(response['data']['key']);
571
 
572
                    $('#gridTableUploadUsers tbody').empty();
573
 
574
                    $.each(response['data']['items'], function(index, item) {
575
 
576
 
577
                        var s = '<tr>';
578
                        s = s + '<td>' + item['first_name'] + '</td>';
579
                        s = s + '<td>' + item['last_name'] + '</td>';
580
                        s = s + '<td>' + item['email'] + '</td>';
581
                        s = s + '<td>' + item['password'] + '</td>';
15460 efrain 582
                        s = s + '<td>' + item['is_adult'] + '</td>';
1 www 583
                        s = s + '</tr>';
584
 
585
                        $('#gridTableUploadUsers tbody').append(s);
586
 
587
 
588
                    });
589
 
590
                    $('#modalFormUploadUsers').modal('hide');
591
                    $('#modalUploadUsers').modal('show');
592
 
593
 
594
 
595
                } else {
15460 efrain 596
                    validatorUploadUsers.resetForm();
1 www 597
                    if(jQuery.type(response['data']) == 'string') {
598
                        $.fn.showError(response['data']);
599
                    } else  {
600
                        $.each(response['data'], function( fieldname, errors ) {
601
                            $.fn.showFormErrorValidator('#form-upload-users #' + fieldname, errors);
602
                        });
603
                    }
604
                }
605
            }).fail(function( jqXHR, textStatus, errorThrown) {
606
                $.fn.showError(textStatus);
607
            }).always(function() {
608
 
609
                NProgress.done();
610
            });
611
            return false;
612
        },
613
        invalidHandler: function(form, validator) {
614
 
615
        }
616
    });
617
 
618
 
619
    $('#form-upload-users #file').fileinput({
15460 efrain 620
        theme: 'fa',
1 www 621
        language: 'es',
622
        showUpload: false,
623
        dropZoneEnabled: false,
624
        maxFileCount: 1,
625
        allowedFileExtensions: ['xls', 'xlsx'],
626
    });
627
 
628
    $('body').on('click', 'button.btn-upload', function(e) {
629
        e.preventDefault();
630
 
631
        $('#form-upload-users #file').fileinput('reset');
632
        $('#form-upload-users #file').val('');
633
 
634
        $('#modalFormUploadUsers').modal('show');
635
    });
636
 
637
    $('body').on('click', 'button.btn-upload-users-step2', function(e) {
638
        e.preventDefault();
639
        NProgress.start();
640
 
641
        $.ajax({
642
            'dataType'  : 'json',
643
            'accept'    : 'application/json',
644
            'method'    : 'post',
645
            'url'       : '$routeUpload',
646
            'data'      :  {
647
                'step' : 'process',
648
                'key' : $('#table-upload-users-key').val(),
649
            }
650
        }).done(function(response) {
651
            if(response['success']) {
15460 efrain 652
                if(response['data']['users_created'] == 1) {
653
                    $.fn.showSuccess(response['data']['users_created'] + ' LABEL_USER_CREATED');
1 www 654
                } else {
15460 efrain 655
                    $.fn.showSuccess(response['data']['users_created'] + ' LABEL_USERS_CREATED');
1 www 656
                }
657
                 gridTable.api().ajax.reload(null, false);
658
                $('#modalUploadUsers').modal('hide');
659
            } else {
660
                $.fn.showError(response['data']);
661
            }
662
        }).fail(function( jqXHR, textStatus, errorThrown) {
663
            $.fn.showError(textStatus);
664
        }).always(function() {
665
            NProgress.done();
666
        });
667
        return false;
668
    });
669
 
670
    $('body').on('click', 'button.btn-edit', function(e) {
671
        e.preventDefault();
672
 
673
        var href = $(this).data('href');
674
        $('#form-edit').attr('action', href);
675
 
676
        NProgress.start();
677
        $.ajax({
678
            'dataType'  : 'json',
679
            'accept'    : 'application/json',
680
            'method'    : 'get',
681
            'url'       :  href,
682
        }).done(function(response) {
683
            if(response['success']) {
684
                $('#form-edit #backend').prop('checked', response['data']['backend'] );
685
                $('#table-roles tbody').empty();
686
 
687
                $.each(response['data']['roles'], function(index, role) {
688
 
689
                    var checked = role['checked'] ? ' checked="checked" ' : '';
690
                    var s = '<tr>';
691
                    s = s + '<td>' + role['name'] + '</td>';
16927 efrain 692
                    s = s + '<td><div class="form-check mb-3">';
16943 efrain 693
                    s = s + '<input type="checkbox" value="1" class="form-check-input" id="checked' + role['id'] + '" name="checked' + role['id'] + '" ' + checked + '> ';
16927 efrain 694
					s = s + '<label class="form-check-label" >&nbsp;</label>';
695
			        s = s + '</div></td>';
1 www 696
                    s = s + '</tr>';
697
 
698
                    $('#table-roles tbody').append(s);
699
 
700
                });
701
 
702
                $('#modalEdit').modal('show');
703
 
16926 efrain 704
 
16927 efrain 705
 
1 www 706
            } else {
707
                $.fn.showError(response['data']);
708
            }
709
        }).fail(function( jqXHR, textStatus, errorThrown) {
710
            $.fn.showError(textStatus);
711
        }).always(function() {
712
            NProgress.done();
713
        });
714
 
715
    });
716
 
717
    $('#form-edit').submit(function (e) {
718
        e.preventDefault();
719
        NProgress.start();
720
        $.ajax({
721
            'dataType'  : 'json',
722
            'accept'    : 'application/json',
723
            'method'    : 'post',
724
            'url'       : $('#form-edit').attr('action'),
725
            'data'      : $('#form-edit').serialize(),
726
        }).done(function(response) {
727
            if(response['success']) {
728
 
729
                $.fn.showSuccess(response['data']);
730
                $('#modalEdit').modal('hide');
731
                gridTable.api().ajax.reload(null, false);
732
 
733
            } else {
734
                $.fn.showError(response['data']);
735
            }
736
        }).fail(function( jqXHR, textStatus, errorThrown) {
737
            $.fn.showError(textStatus);
738
        }).always(function() {
739
            NProgress.done();
740
        });
741
        return false;
742
 
743
    });
744
 
745
    $('body').on('click', 'button.btn-cancel-modal', function(e) {
746
        e.preventDefault();
747
        $('#modalInvite').modal('hide');
748
        $('#modalFormUploadUsers').modal('hide');
749
        $('#modalEdit').modal('hide');
750
        $('#modalChangePassword').modal('hide');
751
    });
752
 
753
    var validatorChangePassword = $('#form-change-password').validate({
754
        debug: true,
755
        onclick: false,
756
        onkeyup: false,
757
        ignore: [':hidden'],
758
            rules: {
759
 
760
                'password': {
761
                    required: true,
762
                    minlength: 6,
763
                    maxlength: 16,
764
                    passwordStrengthCheck: true,
765
                },
766
                'confirmation' : {
767
                    required: true,
768
                    minlength: 6,
769
                    maxlength: 16,
770
                    equalTo: '#form-change-password #password'
771
                },
772
            },
773
            submitHandler: function(form)
774
            {
775
                NProgress.start();
776
                $.ajax({
777
                    'dataType'  : 'json',
778
                    'accept'    : 'application/json',
779
                    'method'    : 'post',
780
                    'url'       : $('#form-change-password').attr('action'),
781
                    'data'      : $('#form-change-password').serialize()
782
                 }).done(function(response) {
783
                    if(response.success) {
784
                        $.fn.showSuccess(response.data);
785
 
786
                        $('#modalChangePassword').modal('hide');
787
                         gridTable.api().ajax.reload(null, false);
788
                    } else {
789
                        if(jQuery.type(response.data) == 'string') {
790
                            $.fn.showError(response.data)
791
                        } else  {
792
                            $.each(response.data, function( fieldname, errors ) {
793
                                $.fn.showFormErrorValidator('#form-change-password #' + fieldname, errors);
794
                            });
795
                        }
796
                    }
797
                }).fail(function( jqXHR, textStatus, errorThrown) {
798
                    $.fn.showError(textStatus)
799
 
800
                }).always(function() {
801
                    NProgress.done();
802
                })
803
            },
804
            invalidHandler: function(form, validator) {
805
            }
806
        });
807
 
808
        $('body').on('click', 'button.btn-change-password', function(e) {
809
            e.preventDefault();
810
 
811
            NProgress.start();
812
            var action = $(this).data('href');
813
 
814
            $.ajax({
815
                'dataType'  : 'json',
816
                'accept'    : 'application/json',
817
                'method'    : 'get',
818
                'url'       :  action,
819
            }).done(function(response) {
820
                if(response['success']) {
821
 
822
                    $('#form-change-password').attr('action', action);
823
                    $('#form-change-password #first_name').val(response['data']['first_name']);
824
                    $('#form-change-password #last_name').val(response['data']['last_name']);
825
                    $('#form-change-password #email').val(response['data']['email']);
826
                    $('#form-change-password #password').val('');
827
                    $('#form-change-password #confirmation').val('');
828
                    validatorChangePassword.resetForm();
829
 
830
                    $('#modalChangePassword').modal('show');
831
                } else {
832
                    $.fn.showError(response['data']);
833
                }
834
            }).fail(function( jqXHR, textStatus, errorThrown) {
835
                $.fn.showError(textStatus);
836
            }).always(function() {
837
                NProgress.done();
838
            });
839
 
840
        });
841
 
17330 ariadna 842
        // Re-inicializar autoComplete cuando el modal se muestre
843
        $('#modalInvite').on('shown.bs.modal', function() {
844
            console.log('Modal shown, re-initializing autoComplete...'); // Debug
845
            setTimeout(function() {
846
                initializeAutoComplete();
847
            }, 100);
848
        });
1 www 849
 
850
    });
851
JS;
852
$this->inlineScript()->captureEnd();
15333 stevensc 853
?>
854
 
1 www 855
 
856
 
16840 efrain 857
<div class="container">
17328 ariadna 858
    <div class="card">
859
        <div class="card-header">
860
            <h6 class="card-title">LABEL_USERS_FOR_COMPANY</h6>
861
        </div>
862
        <div class="card-body">
863
 
864
 
865
            <form name="form-filter" id="form-filter">
866
                <div class="row">
867
                    <div class="col-12  mt-3">
868
                        <label for="status">LABEL_STATUS</label>
869
                        <select id="status" name="status" class="form-control">
870
                            <option value="">LABEL_ALL</option>
871
                            <option value="<?php echo CompanyUser::STATUS_PENDING ?>">LABEL_PENDING</option>
872
                            <option value="<?php echo CompanyUser::STATUS_ACCEPTED ?>">LABEL_ACCEPTED</option>
873
                            <option value="<?php echo CompanyUser::STATUS_ADMIN_WILL_ADD ?>">LABEL_ADMIN_WILL_ADD</option>
874
                            <option value="<?php echo CompanyUser::STATUS_SENT ?>">LABEL_INVITED</option>
16912 efrain 875
                            <option value="<?php echo CompanyUser::STATUS_CANCELLED ?>">LABEL_CANCELLED</option>
17328 ariadna 876
                            <option value="<?php echo CompanyUser::STATUS_REJECTED ?>">LABEL_REJECTED</option>
877
                        </select>
878
                    </div>
879
                </div>
880
            </form>
881
            <div class="row">
882
                <div class="col-12  mt-3">
883
                    <table id="gridTable" class="table table-bordered">
16912 efrain 884
                        <thead>
17328 ariadna 885
                            <tr>
886
                                <th>LABEL_FIRST_NAME</th>
887
                                <th>LABEL_LAST_NAME</th>
888
                                <th>LABEL_EMAIL</th>
889
                                <th>LABEL_DETAILS</th>
890
                                <th>LABEL_ACTIONS</th>
891
                            </tr>
892
                        </thead>
893
                        <tbody>
894
                        </tbody>
895
                    </table>
896
                </div>
16912 efrain 897
            </div>
15333 stevensc 898
        </div>
17328 ariadna 899
        <div class="card-footer text-right">
900
            <button type="button" class="btn btn-sm btn-info btn-refresh"><i class="fa fa-sync"></i> LABEL_REFRESH</button>
901
            <?php if ($allowUpload) : ?>
902
                <button type="button" class="btn btn-sm btn-primary btn-upload"><i class="fa fa-upload"></i> LABEL_UPLOAD </button>
903
            <?php endif; ?>
904
            <?php if ($allowInvite) : ?>
905
                <button type="button" class="btn btn-sm btn-primary btn-invite"><i class="fa fa-plus"></i> LABEL_INVITE </button>
906
            <?php endif; ?>
907
        </div>
908
    </div>
16840 efrain 909
</div>
15333 stevensc 910
 
911
 
1 www 912
<!-- The Modal -->
913
<div class="modal" id="modalInvite">
15333 stevensc 914
    <div class="modal-dialog  modal-xl">
915
        <div class="modal-content">
1 www 916
 
917
            <!-- Modal Header -->
15333 stevensc 918
            <div class="modal-header">
16935 efrain 919
                <h6 class="modal-title">LABEL_INVITE</h6>
15333 stevensc 920
            </div>
1 www 921
 
922
            <!-- Modal body -->
16840 efrain 923
            <form name="form-invite" id="form-invite">
17328 ariadna 924
                <div class="modal-body">
925
 
15333 stevensc 926
                    <input type="hidden" name="user_uuid_selected" id="user_uuid_selected" />
16840 efrain 927
                    <div class="row">
17328 ariadna 928
                        <div class="col-12  mt-3">
929
                            <label for="user_uuid">LABEL_USER (LABEL_MIN_LENGTH_3)</label>
930
                            <br />
17337 stevensc 931
                            <input class="form-control" name="user_uuid" id="user_uuid" autocomplete="off" data-noresults-text="LABEL_AUTOCOMPLETE_USERS_NOT_FOUND">
17328 ariadna 932
                        </div>
933
                    </div>
1 www 934
 
935
 
17328 ariadna 936
 
937
 
938
                </div>
939
                <div class="modal-footer text-right">
940
                    <button type="submit" class="btn btn-sm btn-primary">LABEL_INVITE</button>
941
                    <button type="button" class="btn btn-sm btn-light btn-cancel-modal">LABEL_CANCEL</button>
942
                </div>
16840 efrain 943
            </form>
15333 stevensc 944
        </div>
945
    </div>
946
</div>
1 www 947
 
948
 
15333 stevensc 949
 
1 www 950
<!-- The Modal -->
951
<div class="modal" id="modalFormUploadUsers">
15333 stevensc 952
    <div class="modal-dialog  modal-xl">
953
        <div class="modal-content">
1 www 954
 
955
            <!-- Modal Header -->
15333 stevensc 956
            <div class="modal-header">
16935 efrain 957
                <h6 class="modal-title">LABEL_UPLOAD</h6>
15333 stevensc 958
            </div>
1 www 959
 
17328 ariadna 960
            <?php
961
            $form = $this->formUploadUsers;
962
            $form->setAttributes([
963
                'method'    => 'post',
964
                'name'      => 'form-upload-users',
965
                'id'        => 'form-upload-users'
966
            ]);
1 www 967
 
17328 ariadna 968
            $form->prepare();
969
            echo $this->form()->openTag($form);
970
            ?>
16840 efrain 971
            <!-- Modal body -->
972
            <div class="modal-body">
15333 stevensc 973
 
17328 ariadna 974
 
16840 efrain 975
                <div class="row">
17328 ariadna 976
                    <div class="col-12  mt-3">
15333 stevensc 977
 
978
 
979
                        <?php
17328 ariadna 980
                        $element = $form->get('file');
981
                        $element->setOptions(['label' => 'LABEL_EXCEL']);
982
                        echo $this->formLabel($element);
983
                        ?>
984
                        <div class="file-loading">
985
                            <?php
16816 stevensc 986
 
17328 ariadna 987
                            $element->setAttributes(['class' => 'form-control', 'accept' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel']);
988
                            echo $this->formFile($element);
989
                            ?>
16840 efrain 990
                        </div>
15333 stevensc 991
                    </div>
992
                </div>
1 www 993
 
994
 
995
 
17328 ariadna 996
 
16840 efrain 997
            </div>
17328 ariadna 998
            <div class="modal-footer text-right">
999
                <button type="submit" class="btn btn-sm btn-primary">LABEL_UPLOAD</button>
1000
                <button type="button" class="btn btn-sm btn-light btn-cancel-modal">LABEL_CANCEL</button>
1001
            </div>
1002
            <?php echo $this->form()->closeTag($form); ?>
15333 stevensc 1003
        </div>
1004
    </div>
1005
</div>
1 www 1006
 
1007
 
15333 stevensc 1008
 
1 www 1009
<!-- The Modal -->
1010
<div class="modal" id="modalUploadUsers">
15333 stevensc 1011
    <div class="modal-dialog modal-xl">
1012
        <div class="modal-content">
1 www 1013
 
1014
            <!-- Modal Header -->
15333 stevensc 1015
            <div class="modal-header">
16935 efrain 1016
                <h6 class="modal-title">LABEL_USERS_FOR_COMPANY</h6>
16822 efrain 1017
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="btn-close"></button>
15333 stevensc 1018
            </div>
1 www 1019
 
1020
            <!-- Modal body -->
15333 stevensc 1021
            <div class="modal-body">
1022
                <form>
1023
                    <input type="hidden" name="table-upload-users-key" id="table-upload-users-key">
1024
                </form>
16840 efrain 1025
                <div class="row">
17328 ariadna 1026
                    <div class="col-12  mt-3" style="height: 300px;overflow: scroll;">
1027
                        <table id="gridTableUploadUsers" style="width: 100%" class="table table-bordered">
16840 efrain 1028
                            <thead>
1029
                                <tr>
1030
                                    <th>LABEL_FIRST_NAME</th>
1031
                                    <th>LABEL_LAST_NAME</th>
1032
                                    <th>LABEL_EMAIL</th>
1033
                                    <th>LABEL_PASSWORD</th>
1034
                                    <th>LABEL_IS_ADULT</th>
1035
                                </tr>
1036
                            </thead>
1037
                            <tbody>
1038
                            </tbody>
1039
                        </table>
17328 ariadna 1040
 
1041
                    </div>
15333 stevensc 1042
                </div>
1 www 1043
 
16840 efrain 1044
 
15333 stevensc 1045
            </div>
1046
 
1 www 1047
            <!-- Modal footer -->
16891 efrain 1048
            <div class="modal-footer text-right">
15333 stevensc 1049
                <button type="submit" class="btn btn-sm btn-primary btn-upload-users-step2">LABEL_SAVE</button>
1050
                <button type="button" class="btn btn-sm btn-danger" data-dismiss="modal">LABEL_CLOSE</button>
1051
            </div>
1 www 1052
 
15333 stevensc 1053
        </div>
1054
    </div>
1055
</div>
1 www 1056
 
1057
 
1058
<!-- The Modal -->
1059
<div class="modal" id="modalEdit">
15333 stevensc 1060
    <div class="modal-dialog  modal-xl">
1061
        <div class="modal-content">
1 www 1062
 
1063
            <!-- Modal Header -->
15333 stevensc 1064
            <div class="modal-header">
16935 efrain 1065
                <h6 class="modal-title">LABEL_USER_FOR_COMPANY - LABEL_EDIT</h6>
15333 stevensc 1066
            </div>
1 www 1067
 
17328 ariadna 1068
            <form name="form-edit" id="form-edit">
1069
                <!-- Modal body -->
1070
                <div class="modal-body">
1071
 
15333 stevensc 1072
                    <div class="row">
16841 efrain 1073
                        <div class="col-md-12 col-sm-12  mt-3">
17328 ariadna 1074
                            <div class="form-check mb-3">
1075
                                <input type="checkbox" name="backend" id="backend" value="y" class="form-check-input" style="width: 20px; height: 20px"> <label for="backend" class="form-check-label">LABEL_ACCESS_BACKEND</label>
1076
 
15333 stevensc 1077
                            </div>
1078
                        </div>
1079
                    </div>
1080
                    <div class="row">
16841 efrain 1081
                        <div class="col-md-12 col-sm-12  mt-3">
16822 efrain 1082
                            <table id="table-roles" class="table table-bordered">
15333 stevensc 1083
                                <thead>
1084
                                    <tr>
1085
                                        <th>LABEL_NAME</th>
1086
                                        <th>LABEL_ACTIVE</th>
1087
                                    </tr>
1088
                                </thead>
1089
                                <tbody>
1090
                                </tbody>
1091
                            </table>
1 www 1092
 
15333 stevensc 1093
                        </div>
1094
                    </div>
1095
 
17328 ariadna 1096
 
1097
                </div>
1098
                <div class="modal-footer text-right">
1099
                    <button type="submit" class="btn btn-sm btn-primary">LABEL_SAVE</button>
1100
                    <button type="button" class="btn btn-sm btn-light btn-cancel-modal">LABEL_CANCEL</button>
1101
                </div>
1102
            </form>
15333 stevensc 1103
        </div>
1104
    </div>
1 www 1105
</div>
1106
 
1107
 
1108
 
1109
<!-- The Modal -->
1110
<div class="modal" id="modalChangePassword">
15333 stevensc 1111
    <div class="modal-dialog">
1112
        <div class="modal-content">
1 www 1113
 
1114
            <!-- Modal Header -->
15333 stevensc 1115
            <div class="modal-header">
16935 efrain 1116
                <h6 class="modal-title">LABEL_USERS</h6>
15333 stevensc 1117
            </div>
1 www 1118
 
17328 ariadna 1119
            <?php
1120
            $form = $this->formChangePassword;
1121
            $form->setAttributes([
1122
                'method'    => 'post',
1123
                'name'      => 'form-change-password',
1124
                'id'        => 'form-change-password'
1125
            ]);
1 www 1126
 
17328 ariadna 1127
            $form->prepare();
1128
            echo $this->form()->openTag($form);
1129
            ?>
16929 efrain 1130
            <div class="modal-body">
1 www 1131
 
17328 ariadna 1132
                <div class="row">
1133
                    <div class="col-12 mt-3">
1134
                        <?php
1135
                        $element = $form->get('first_name');
1136
                        $element->setOptions(['label' => 'LABEL_FIRST_NAME']);
1137
                        $element->setAttributes(['class' => 'form-control', 'readonly' => 'readonly']);
1138
 
1139
                        echo $this->formLabel($element);
1140
                        echo $this->formText($element);
1141
                        ?>
16929 efrain 1142
                    </div>
15333 stevensc 1143
                </div>
17328 ariadna 1144
                <div class="row">
1145
                    <div class="col-12 mt-3">
1146
                        <?php
1147
                        $element = $form->get('last_name');
1148
                        $element->setOptions(['label' => 'LABEL_LAST_NAME']);
1149
                        $element->setAttributes(['class' => 'form-control', 'readonly' => 'readonly']);
1 www 1150
 
17328 ariadna 1151
                        echo $this->formLabel($element);
1152
                        echo $this->formText($element);
1153
                        ?>
16929 efrain 1154
                    </div>
15333 stevensc 1155
                </div>
17328 ariadna 1156
                <div class="row">
1157
                    <div class="col-12 mt-3">
1158
                        <?php
1159
                        $element = $form->get('email');
1160
                        $element->setOptions(['label' => 'LABEL_EMAIL']);
1161
                        $element->setAttributes(['class' => 'form-control', 'readonly' => 'readonly']);
1 www 1162
 
17328 ariadna 1163
                        echo $this->formLabel($element);
1164
                        echo $this->formText($element);
1165
                        ?>
16929 efrain 1166
                    </div>
15333 stevensc 1167
                </div>
17328 ariadna 1168
                <div class="row">
1169
                    <div class="col-12 mt-3">
1170
                        <?php
1171
                        $element = $form->get('password');
1172
                        $element->setOptions(['label' => 'LABEL_PASSWORD']);
1173
                        $element->setAttributes(['class' => 'form-control']);
1 www 1174
 
17328 ariadna 1175
                        echo $this->formLabel($element);
1176
                        echo $this->formPassword($element);
1177
                        ?>
16929 efrain 1178
                    </div>
15333 stevensc 1179
                </div>
17328 ariadna 1180
                <div class="row">
1181
                    <div class="col-12 mt-3">
1182
                        <?php
1183
                        $element = $form->get('confirmation');
1184
                        $element->setOptions(['label' => 'LABEL_CONFIRMATION']);
1185
                        $element->setAttributes(['class' => 'form-control']);
1 www 1186
 
17328 ariadna 1187
                        echo $this->formLabel($element);
1188
                        echo $this->formPassword($element);
1189
                        ?>
16929 efrain 1190
                    </div>
15333 stevensc 1191
                </div>
1192
 
1193
 
17328 ariadna 1194
 
16929 efrain 1195
            </div>
1196
            <div class="modal-footer text-right">
17328 ariadna 1197
                <button type="submit" class="btn btn-sm btn-primary">LABEL_SAVE</button>
1198
                <button type="button" class="btn btn-sm btn-light btn-cancel-modal">LABEL_CANCEL</button>
1199
            </div>
1200
            <?php echo $this->form()->closeTag($form); ?>
15333 stevensc 1201
 
1202
        </div>
1203
    </div>
1204
</div>