/* global axios, jconfirm, jAlert, Ladda */ const getNode = node => document.querySelector(node) const getNodeAll = nodeList => document.querySelectorAll(nodeList) let dataTableVacante; let vm = new Vue({ el: '#app', data: { vacante: 0, vacanteOcupada: 0, vacanteDisponible: 0 }, methods: { sumarVacante() { this.vacante++ this.vacanteDisponible++; }, restarVacante() { if (this.vacante > 0) { if (this.vacante > this.vacanteOcupada) { this.vacante-- this.vacanteDisponible-- } else { jAlert({type: 'warning', content: 'No puede eliminar vacantes. Hay cargos ocupandolos.', buttons: {left: 'Aceptar'}}) } } else { jAlert({type: 'warning', content: 'No puede eliminar más vacantes.', buttons: {left: 'Aceptar'}}) } }, asignarVacante() { if (!vacante.validarCambios()) { jAlert({ type: 'confirm', content: '¿Seguro de asignar las vacantes seleccionadas?', buttons: {left: 'Si', right: 'No'} }).then(flag => { if (flag) { vacante.validar() .then(response => response.data) .then(data => { if (data.status) { vacante.registrar() .then(response => response.data) .then(data => { if (data.status) { $('#tblVacantes').DataTable().ajax.reload() $('#modalAsignarDisponibilidad').modal('hide') jAlert({type: 'success', content: `${data.message}`, buttons: {left: 'Aceptar'}}) jsonVacante = {} } else { jAlert({type: 'warning', content: `${data.message}`, buttons: {left: 'Aceptar'}}) } }) } else { jAlert({type: 'warning', content: `${data.message}`, buttons: {left: 'Aceptar'}}) } }) } }) } else { jAlert({type: 'warning', content: `Al parecer no ha hecho algún cambio.`, buttons: {left: 'Aceptar'}}) } }, helperVacante(e) { if (this.vacante >= this.vacanteOcupada) { this.vacanteDisponible = this.vacante - this.vacanteOcupada } else { jAlert({type: 'warning', content: 'No puede eliminar vacantes. Hay cargos ocupandolos.', buttons: {left: 'Aceptar'}}) } } } }) let jsonVacante = {}; const helpers = { defaultSelect(el) { el.innerHTML = '<option value="0">[ TODOS ]</option>' $(el).selectpicker('refresh') }, filteredSelect(el, options) { el.innerHTML = options $(el).selectpicker('refresh') }, ajaxRequest(obj) { return new Promise((resolve, reject) => { $.ajax({ url: obj.url, type: obj.type, dataType: obj.dataType, headers: obj.headers, data: obj.body, beforeSend: (xhr) => { }, success: (data, textStatus, jqXHR) => { resolve(data) }, error: (jqXHR, textStatus, errorThrown) => { reject({ status: jqXHR.status, jqXHR: jqXHR, request: obj }) } }) }) }, createSelectOptions(obj, valueName, textName) { let options = `<option value="0">[ TODOS ]</option>` obj.forEach(data => { options += `<option value="${data[valueName]}">${data[textName]}</option>` }) return options }, getRow(el, row) { return $(getNode(el)).DataTable().row($(row).parents('tr')) }, validateKeyValueFromArray(array, key, value) { let count = 0; for (let o in array) { if (array[o][key] === value) { count++; } } return count === 1 ? true : false } } const DOMComponents = { init() { this.initializePluginComponents() this.configComponents() }, initializePluginComponents() { getNodeAll('.bootstrap-select').forEach(el => $(el).selectpicker()) }, configComponents() { new Input({el: '.vacanteNumber', param: 'numbers'}).validate() } } const httpRequest = { listarSede() { return helpers.ajaxRequest({ url: '../SedeServlet', type: 'POST', dataType: 'json', body: { accion: 'listarSede' } }) }, listarArea(obj) { return helpers.ajaxRequest({ url: '../AreaServlet', type: 'POST', dataType: 'json', body: { accion: 'listarArea', codigoSede: obj.codigoSede } }) }, listarCargo(obj) { return helpers.ajaxRequest({ url: '../CargoServlet', type: 'POST', dataType: 'json', body: { accion: 'listarCargo', codigoArea: obj.codigoArea } }) }, listarVacanteSimpleTable() { return axios.post('../VacanteServlet?accion=listarVacanteSimpleTable') } } const DOMEvents = () => { // PANEL DE FILTRADO getNode('#cboSede').addEventListener('change', (e) => { // debugger let codigoSede = parseInt(e.currentTarget.value) if (codigoSede !== 0) { httpRequest.listarArea({codigoSede: codigoSede}) .then((data) => { helpers.filteredSelect(getNode('#cboArea'), helpers.createSelectOptions(data.data.areas, 'codigoArea', 'nombre')) }) } else { helpers.defaultSelect(getNode('#cboArea')) } helpers.defaultSelect(getNode('#cboCargo')) }) getNode('#cboArea').addEventListener('change', (e) => { let codigoArea = parseInt(e.currentTarget.value) if (codigoArea !== 0) { httpRequest.listarCargo({codigoArea: codigoArea}) .then((data) => { helpers.filteredSelect(getNode('#cboCargo'), helpers.createSelectOptions(data.data.cargos, 'codigoCargo', 'nombre')) }) } else { helpers.defaultSelect(getNode('#cboCargo')) } }) getNode('#btnBusquedaFichaPendiente').addEventListener('click', (e) => { $('#tblVacantes').DataTable().destroy() vacante.listar() }) // tabla $(getNode('#tblVacantes tbody')).on('click', '.asignarVacante', (e) => { let data = helpers.getRow('#tblVacantes', e.currentTarget).data() $(getNode('#modalAsignarDisponibilidad')).modal({ show: true, backdrop: 'static', keyboard: false }) jsonVacante = data getNode('#lblSede').innerText = data.nombreSede getNode('#lblArea').innerText = data.nombreArea getNode('#lblCargo').innerText = data.nombreCargo vm.vacante = data.vacanteTotal vm.vacanteOcupada = data.vacanteOcupada vm.vacanteDisponible = data.vacanteDisponible }) $(getNode('#tblVacantes tbody')).on('click', '.eliminarDisponibilidad', (e) => { let row = helpers.getRow('#tblVacantes', e.currentTarget).data() if (row.vacanteDisponible !== 0) { jAlert({ type: 'confirm', content: `Esta a punto de eliminar <mark>${row.vacanteDisponible}</mark> ${row.vacanteDisponible === 1 ? 'vacante disponible' : 'vacantes disponibles'}`, buttons: { left: 'Si', right: 'No' } }).then(flag => { if (flag) { vacante.eliminarDisponibilidad({ codigoSedeArea: row.codigoSedeArea, codigoAreaCargo: row.codigoAreaCargo, cantidad: row.vacanteOcupada }).then(response => response.data) .then(data => { if (data.status) { $('#tblVacantes').DataTable().ajax.reload() jAlert({ type: 'success', content: `${data.message}`, buttons: { left: 'Aceptar' } }) } else { jAlert({ type: 'danger', content: `${data.message}`, buttons: { left: 'Aceptar' } }) } }) .catch(err => console.log(err)) } }) } else { jAlert({ type: 'warning', content: `No tiene vacantes disponibles para eliminar`, buttons: { left: 'Aceptar' } }) } }) $(getNode('#tblVacantes tbody')).on('click', '.generarVacante', (e) => { console.log('1'); // let data = helpers.getRow('#tblVacantes', e.currentTarget).data() let data = dataTableVacante.row($(e.currentTarget).parents('tr')).data() $.confirm({ theme: 'material', closeIcon: false, animation: 'scale', draggable: false, scrollToPreviousElement: false, scrollToPreviousElementAnimate: false, icon: 'fa fa-plus fa-lg', type: 'blue', title: 'Generar vacantes', onContentReady: function () { new Input({el: '#txtCantidadVacante', param: 'numbers'}).validate() }, content: `<div class="col-xs-12"> <div class="form-group mt-5"> <label class="text-semibold">SEDE: </label> <span style="font-size: 12px;" class="pull-right-sm label border-right-primary label-striped">${data.nombreSede}</span> </div> <div class="form-group"> <label class="text-semibold">ÁREA: </label> <span style="font-size: 12px;" class="pull-right-sm label border-right-primary label-striped">${data.nombreArea}</span> </div> <div class="form-group"> <label class="text-semibold">CARGO: </label> <span style="font-size: 12px;" class="pull-right-sm label border-right-primary label-striped">${data.nombreCargo}</span> </div> <hr/> <div class="form-group"> <div class="row" style="display: flex; align-items: center;flex-direction: row"> <div class="col-md-4"> <label class="text-semibold">CANTIDAD: </label> </div> <div class="col-md-4"></div> <div class="col-md-4 pull-right"> <input id="txtCantidadVacante" style="font-size:16px; font-weight: bold;" maxlength="3" value="1" type="text" class="form-control input-xs text-right pull-right-sm"> </div> </div> </div> </div>`, buttons: { si: { btnClass: 'bg-primary', text: `<span class="text-semibold"><i class="fa fa-check"></i> Generar</span>`, action: function () { let cantidadVacante = parseInt(getNode('#txtCantidadVacante').value) jAlert({ type: 'confirm', content: `¿Seguro de generar <mark>${cantidadVacante}</mark> ${cantidadVacante === 1 ? 'vacante' : 'vacantes'}?`, buttons: {left: 'Si', right: 'No'} }).then(flag => { if (flag) { vacante.generarVacante({ codigoSedeArea: data.codigoSedeArea, codigoAreaCargo: data.codigoAreaCargo, cantidad: cantidadVacante }).then(res => res.data) .then(data => { if (data.status) { $('#tblVacantes').DataTable().ajax.reload() jAlert({ type: 'success', content: data.message, buttons: {left: 'Aceptar'} }) } else { jAlert({ type: 'warning', content: data.message || 'No se pudo generar la vacante', buttons: {left: 'Aceptar'} }) } }) .catch(err => jAlert({type: 'error', content: err || 'Error al generar vacante', buttons: {left: 'Aceptar'}})) } }) } }, no: { btnClass: 'bg-danger', text: `<span class="text-semibold"><i class="fa fa-close"></i> Cancelar</span>` } } }) }) //modal asignar disponibilidad getNode('#btnCerrarModalAsignarDisponibilidad').addEventListener('click', (e) => { $('#modalAsignarDisponibilidad').modal('hide') jsonVacante = {} }) } const initRequest = () => { return new Promise((resolve) => { httpRequest.listarSede() .then(data => { helpers.filteredSelect(getNode('#cboSede'), helpers.createSelectOptions(data.data.sedes, 'codigoSede', 'nombre')) }) .catch(err => console.error(err)) resolve(true) }) } const vacante = { listar() { return new Promise((resolve, reject) => { defaultConfigDataTable() $(getNode('#tblVacantes')).DataTable({ processing: true, serverSide: true, iDisplayLength: 10, ajax: { url: '../VacanteServlet', type: 'POST', data: { accion: 'listarVacanteDT', json: JSON.stringify({ codigoSede: parseInt(getNode('#cboSede').value), codigoArea: parseInt(getNode('#cboArea').value), codigoCargo: parseInt(getNode('#cboCargo').value) }) } }, columnDefs: [ {targets: 0, orderable: false, width: '1%', className: 'text-center'}, // # {targets: 1, orderable: false, width: '12%'}, // sede {targets: 2, orderable: false, width: '12%'}, // area {targets: 3, orderable: false, width: '12%'}, // cargo {targets: 4, orderable: false, width: '5%', className: 'text-center'}, // vacantesTotal {targets: 5, orderable: false, width: '5%', className: 'text-center'}, // vacantesOcupadas {targets: 6, orderable: false, width: '5%', className: 'text-center'}, // vacantesDisponibles {targets: 7, orderable: false, width: '5%', className: 'text-center'} // acciones ], columns: [ { data: 'item' }, { data: 'nombreSede' }, { data: 'nombreArea' }, { data: 'nombreCargo' }, { data: null, render: (data, type, row) => `<span style="font-size:13px; width:40px;" class="label bg-primary">${data.vacanteTotal}</span>` }, { data: 'vacanteOcupada', render: (data, type, row) => `<span style="font-size:13px; width:40px;" class="label bg-orange">${data}</span>` }, { data: 'vacanteDisponible', render: (data, type, row) => data === 0 ? '<span class="label bg-warning">SIN DISPONIBILIDAD</span>' : `<span class="label bg-success">${data} ${data === 1 ? 'DISPONIBLE' : 'DISPONIBLES'}</span>` }, { data: null, render: (data, type, row) => { let actions = `` if (data.vacanteDisponible === 0) { actions = `<ul class="icons-list"> <li title="Asignar vacante" class="text-primary"> <a href="#" onclick="return false" class="asignarVacante"><i style="font-size:22px;" class=" fa fa-pencil fa-lg"></i></a> </li> </ul>`; } else { actions = `<ul class="icons-list"> <li title="Asignar vacante" class="text-primary"> <a href="#" onclick="return false" class="asignarVacante"><i style="font-size:22px;" class=" fa fa-pencil fa-lg"></i></a> </li> <li title="Eliminar disponibilidad" class="text-danger"> <a href="#" onclick="return false" class="eliminarDisponibilidad"><i style="font-size:22px;" class="fa fa-trash-o fa-lg"></i></a> </li> </ul>`; } return actions } } ], fnInitComplete: function (oSettings, data) { resolve(data) } }) }) }, listarSimpleTable() { return new Promise((resolve, reject) => { httpRequest.listarVacanteSimpleTable() .then(data => data.data.data.vacantes) .then(vacantes => { defaultConfigDataTable() dataTableVacante = $(getNode('#tblVacantes')).DataTable({ processing: true, iDisplayLength: 20, data: vacantes, columnDefs: [ {targets: 0, orderable: false, width: '1%', className: 'text-center'}, // # {targets: 1, orderable: false, width: '12%'}, // sede {targets: 2, orderable: false, width: '12%'}, // area {targets: 3, orderable: false, width: '12%'}, // cargo {targets: 4, orderable: false, width: '5%', className: 'text-center'}, // vacantesTotal {targets: 5, orderable: false, width: '5%', className: 'text-center'}, // vacantesOcupadas {targets: 6, orderable: false, width: '5%', className: 'text-center'}, // vacantesDisponibles {targets: 7, orderable: false, width: '5%', className: 'text-center'} // acciones ], columns: [ { data: 'item' }, { data: 'nombreSede' }, { data: 'nombreArea' }, { data: 'nombreCargo' }, { data: 'vacanteTotal', render: (data, type, row) => { let label = '' if (data === '') { label = '<span class="label bg-danger tp-sin-asignar">SIN ASIGNAR</span' } else { label = `<span style="font-size:13px; width:40px;" class="label bg-primary">${data}</span>` } return label } }, { data: 'vacanteOcupada', render: (data, type, row) => { let label = '' if (data === '') { label = '<span class="label bg-danger tp-sin-asignar">SIN ASIGNAR</span' } else { label = `<span style="font-size:13px; width:40px;" class="label bg-orange">${data}</span>` } return label } }, { data: 'vacanteDisponible', render: (data, type, row) => { let label = '' if (data === '') { label = '<span class="label bg-danger tp-sin-asignar">SIN ASIGNAR</span' } else { label = data === 0 ? '<span class="label bg-warning">SIN DISPONIBILIDAD</span>' : `<span class="label bg-success">${data} ${data === 1 ? 'DISPONIBLE' : 'DISPONIBLES'}</span>` } return label } }, { data: null, render: (data, type, row) => { let actions = `` if (data.codigoVacante === '') { actions = `<ul class="icons-list"> <li title="Generar vacantes" class="text-success"> <a href="#" onclick="return false" class="generarVacante"><i style="font-size:22px;" class=" fa fa-plus fa-lg"></i></a> </li> </ul>`; } else { if (data.vacanteDisponible === 0) { actions = `<ul class="icons-list"> <li title="Asignar vacante" class="text-primary"> <a href="#" onclick="return false" class="asignarVacante"><i style="font-size:22px;" class=" fa fa-pencil fa-lg"></i></a> </li> </ul>`; } else { actions = `<ul class="icons-list"> <li title="Asignar vacante" class="text-primary"> <a href="#" onclick="return false" class="asignarVacante"><i style="font-size:22px;" class=" fa fa-pencil fa-lg"></i></a> </li> <li title="Eliminar disponibilidad" class="text-danger"> <a href="#" onclick="return false" class="eliminarDisponibilidad"><i style="font-size:22px;" class="fa fa-trash-o fa-lg"></i></a> </li> </ul>`; } } return actions } } ], initComplete: function () { this.api().columns().every(function () { var column = this; var select = $('<select class="filter-select" data-placeholder="Filtrar"><option value=""></option></select>') .appendTo($(column.footer()).not(':nth-last-child(1), :nth-last-child(2), :nth-last-child(3), :nth-last-child(4), :first-child').empty()) .on('change', function () { var val = $.fn.dataTable.util.escapeRegex( $(this).val() ); column .search(val ? '^' + val + '$' : '', true, false) .draw(); }); column.data().unique().sort().each(function (d, j) { select.append('<option value="' + d + '">' + d + '</option>') }); }); }, createdRow: function (row, data, index) { // console.log(data) // if (data.codigoVacante === '' && data.vacanteTotal === '' && data.vacanteOcupada === '' && data.vacanteDisponible === '') { // $($(row).find('.tp-sin-asignar').parent()[1]).addClass('hide') // $($(row).find('.tp-sin-asignar').parent()[2]).addClass('hide') // $($(row).find('.tp-sin-asignar').parent()[0]).attr('colspan', '3') // } } }) resolve(true) }) .catch(err => reject(false)) }) }, registrar() { return axios.post('../VacanteServlet?accion=registrarVacante', { json: { codigoSedeArea: jsonVacante.codigoSedeArea, codigoAreaCargo: jsonVacante.codigoAreaCargo, cantidad: vm.vacante } }) }, generarVacante(obj) { return axios.post('../VacanteServlet?accion=generarVacante', { json: { codigoSedeArea: obj.codigoSedeArea, codigoAreaCargo: obj.codigoAreaCargo, cantidad: obj.cantidad } }) }, validar() { return axios.post('../VacanteServlet?accion=validarVacante', { json: { codigoSedeArea: jsonVacante.codigoSedeArea, codigoAreaCargo: jsonVacante.codigoAreaCargo, cantidad: vm.vacante, vacantesOcupadas: vm.vacanteOcupada } }) }, eliminarDisponibilidad(obj) { return axios.post('../VacanteServlet?accion=registrarVacante', { json: { codigoSedeArea: obj.codigoSedeArea, codigoAreaCargo: obj.codigoAreaCargo, cantidad: obj.cantidad } }) }, limpiarFiltro() { Ladda.bind('#btnLimpiarFiltro', { callback: function (instance) { let progress = 0; let interval = setInterval(function () { progress = Math.min(progress + Math.random(), 100); instance.setProgress(progress); if (progress === 100) { instance.stop(); clearInterval(interval); $('#cboSede').val(0).change() $('#cboSede').selectpicker('refresh') getNodeAll('#cboArea, #cboCargo').forEach(el => helpers.defaultSelect(el)) $('#tblVacantes').DataTable().destroy() vacante.listar() } }); } }); }, validarCambios() { let flag = false let newVacante = vm.vacante let oldVacante = jsonVacante.vacanteTotal if (newVacante === oldVacante) { flag = true } return flag } } printLeyend({ el: '#leyenda', data: [ { icon: 'pencil', color: 'primary', title: 'Asignar vacantes', description: 'Sirve para asignar las vacantes al cargo.' }, { icon: 'trash-o', color: 'danger', title: 'Eliminar disponibilidad', description: 'Sirve para eliminar la disponibilidad del cargo.' } // { // icon: 'plus', // color: 'success', // title: 'Generar vacante', // description: 'Sirve para generar vacantes al cargo.' // } ] }) DOMComponents.init() initRequest() vacante.listar() //vacante.listarSimpleTable() // .then(() => { // DOMEvents(); //// $('.filter-select').select2(); // }) vacante.limpiarFiltro() DOMEvents()