Alejandro Rosales 2 年之前
父节点
当前提交
6c15e330c4
共有 8 个文件被更改,包括 164 次插入360 次删除
  1. 16 17
      action/action_periodos_update.php
  2. 55 63
      auditoria.php
  3. 1 0
      import/html_header.php
  4. 5 3
      import/periodo.php
  5. 14 9
      js/auditoría.js
  6. 39 260
      js/datalist.js
  7. 21 0
      log/asistencias_2023_08.log
  8. 13 8
      ts/auditoría.ts

+ 16 - 17
action/action_periodos_update.php

@@ -1,18 +1,17 @@
 <?php
-    $ruta = "../";
-    require_once "../include/bd_pdo.php";
-    global $pdo;
-    print_r($_POST);
-    $sql = "SELECT fu_update_periodo(:periodo_id, :fecha_inicio, :fecha_final, :estado, :nombre, :nivel)";
-    $params = [
-        ':periodo_id' => $_POST['idP'],
-        ':fecha_inicio' => $_POST['fecha_inicial'],
-        ':fecha_final' => $_POST['fecha_final'],
-        ':estado' => $_POST['estadoP'],
-        ':nombre' => mb_strtoupper($_POST['nombreP']),
-        ':nivel' => $_POST['nivelP']
-    ];
-    echo json_encode(query($sql, $params, true));
-    header("Location: ../carreras.php?facultad=".$_POST['facultadP']);
-    exit();
-?>
+$ruta = "../";
+require_once "../include/bd_pdo.php";
+global $pdo;
+print_r($_POST);
+$sql = "SELECT fu_update_periodo(:periodo_id, :fecha_inicio, :fecha_final, :estado, :nombre, :nivel)";
+$params = [
+    ':periodo_id' => $_POST['idP'],
+    ':fecha_inicio' => $_POST['fecha_inicial'],
+    ':fecha_final' => $_POST['fecha_final'],
+    ':estado' => $_POST['estadoP'],
+    ':nombre' => mb_strtoupper($_POST['nombreP']),
+    ':nivel' => $_POST['nivelP']
+];
+echo json_encode(query($sql, $params, true));
+header("Location: ../carreras.php?facultad=" . $_POST['facultadP']);
+exit();

+ 55 - 63
auditoria.php

@@ -55,7 +55,7 @@
     } ?>
 
     <main class="container-fluid px-4 mt-4" id="app" v-cloak @vue:mounted="mounted">
-        <!-- {{ store }} -->
+        <!-- {{ store.current }} -->
         <?php include "import/periodo.php" ?>
         <div class="form-box">
             <div class="form-group row">
@@ -63,8 +63,10 @@
                     <label for="dlFacultad" class="col-4 col-form-label">Facultad</label>
                     <div class="col-6">
                         <div id="dlFacultad" class="datalist datalist-select mb-1 w-100">
-                            <div class="datalist-input">Selecciona una facultad</div>
-                            <span class="ing-buscar icono"></span>
+                            <div class="datalist-input">
+                                Selecciona una facultad
+                            </div>
+                            <span class="icono ing-buscar"></span>
                             <ul style="display:none">
                                 <li class="datalist-option" data-id="0"
                                     @click="store.filters.facultad_id = null; store.current.page = 1;">
@@ -81,38 +83,7 @@
                     </div>
                 <? } ?>
             </div>
-            <div class="form-group row align-items-center">
-                <label for="switchFecha" class="col-4 col-form-label">
-                    {{store.filters.switchFecha ? 'Rango de fechas' : 'Fecha'}}
-                    <!-- switch -->
-                    <div class="custom-control custom-switch">
-                        <input type="checkbox" class="custom-control-input" id="switchFecha"
-                            v-model="store.filters.switchFecha" @input="store.filters.switchFechas">
-                        <label class="custom-control-label" for="switchFecha"></label>
-                    </div>
-                </label>
-
-                <div class="col-6" v-if="store.filters.switchFecha">
-                    <div class="form-row justify-content-around align-items-center">
-                        <input id="fecha_inicio" name="fecha_inicio" class="form-control date-picker col-5 mr-4"
-                            placeholder="Seleccione una fecha de inicio" readonly v-model="store.filters.fecha_inicio">
-                        <input id="fecha_fin" name="fecha_fin" class="form-control date-picker col-5"
-                            placeholder="Seleccione una fecha final" readonly v-model="store.filters.fecha_fin">
-                        <button type="button" class="btn btn-info btn-sm form-control col-1 ml-auto"
-                            @click="store.filters.fetchByDate"
-                            :disabled="store.filters.fecha_inicio == null || store.filters.fecha_fin == null">
-                            <i class="ing-aceptar"></i>
-                        </button>
-                    </div>
-                </div>
 
-                <div class="col-6" v-if="!store.filters.switchFecha">
-                    <div class="form-row">
-                        <input id="fecha" name="fecha" class="form-control date-picker"
-                            placeholder="Seleccione una fecha" readonly v-model="store.filters.fecha">
-                    </div>
-                </div>
-            </div>
             <div class="form-group row" v-if="store.bloques_horario.data.length > 0">
                 <label for="dlBloqueHorarios" class="col-4 col-form-label">Bloque horarios</label>
                 <div class="col-6">
@@ -120,13 +91,12 @@
                         <div class="datalist-input">
                             Seleccione un bloque horario
                         </div>
-                        <span class="ing-buscar icono"></span>
+                        <span class="icono ing-buscar"></span>
                         <ul style="display:none">
                             <li class="datalist-option" data-id="0"
                                 @click="store.filters.bloque_horario = null; store.current.page = 1;">
                                 Todos los bloques horarios
                             </li>
-                            </li>
                             <li class="datalist-option not-selectable">
                                 Mañana
                             </li>
@@ -171,23 +141,17 @@
                 </div>
             </div>
             <div class="form-group row align-items-center">
-                <label for="sin_registro" class="col-4 col-form-label">
-                    {{store.filters.sin_registro ? 'Sin registro' : 'Asistencia'}}
-                    <!-- switch -->
-                    <div class="custom-control custom-switch">
-                        <input type="checkbox" class="custom-control-input" id="sin_registro"
-                            v-model="store.filters.sin_registro"
-                            @input="disableDatalist('#estado_id', !store.filters.sin_registro)">
-                        <label class="custom-control-label" for="sin_registro"></label>
-                    </div>
+                <label for="dlAsistencia" class="col-4 col-form-label">
+                    Asistencia
                 </label>
                 <div class="col-6">
                     <div class="form-row justify-content-around align-items-center">
-                        <div id="dlAsistencia" :class="{'d-none': store.filters.sin_registro}"
-                            class="datalist datalist-select mb-1 w-100">
-                            <div class="datalist-input" id="estados">Selecciona un estado de asistencia</div>
-                            <span class="ing-buscar icono"></span>
-                            <ul style="display:none">
+                        <div id="dlAsistencia" class="datalist datalist-select mb-1 w-100">
+                            <div class="datalist-input" id="estados">
+                                Selecciona un estado de asistencia
+                            </div>
+                            <span class="icono ing-buscar"></span>
+                            <ul style=" display:none">
                                 <li class="datalist-option" data-id="0"
                                     @click="store.filters.estados = []; store.current.page = 1;">
                                     Todos los registros
@@ -196,29 +160,57 @@
                                     :key="estado.estado_supervisor_id" :data-id="estado.estado_supervisor_id"
                                     @click="store.filters.estados = store.toggle(store.filters.estados, estado.estado_supervisor_id); setTimeout(store.estados.printEstados, 0); store.current.page = 1;"
                                     :class="{'selected': store.filters.estados.includes(estado.estado_supervisor_id)}">
-                                    <span class="badge"
-                                        :class="`badge-${store.filters.estados.includes(estado.estado_supervisor_id) ? 'dark' : estado.estado_color}`">
+                                    <span class="badge" :class="`badge-${estado.estado_color}`">
                                         <i :class="estado.estado_icon"></i> {{estado.nombre}}
                                     </span>
                                 </li>
-                            </ul>
-                            <input type="hidden" id="estado_id" name="estado_id">
-                        </div>
 
-                        <div id="dlAsistencia" :class="{'d-none': !store.filters.sin_registro}"
-                            class="datalist datalist-select mb-1 w-100">
-                            <div id="estados" class="datalist-input text-center">
-                                <span class="badge badge-dark px-5">
-                                    <i class="ing-cancelar mr-3"></i>
-                                    <span class="text-uppercase">
+                                <li class="datalist-option" data-id="-1"
+                                    @click="store.filters.estados = store.toggle(store.filters.estados, -1); setTimeout(store.estados.printEstados, 0); store.current.page = 1;">
+                                    <span class="badge badge-dark">
+                                        <i class="ing-cancelar"></i>
                                         Sin registro
                                     </span>
-                                </span>
-                            </div>
+                                </li>
+                            </ul>
+                            <input type="hidden" id="estado_id" name="estado_id">
                         </div>
                     </div>
                 </div>
             </div>
+            <div class="form-group row align-items-center">
+                <label for="switchFecha" class="col-4 col-form-label">
+                    {{store.filters.switchFecha ? 'Rango de fechas' : 'Fecha'}}
+                    <!-- switch -->
+                    <div class="custom-control custom-switch">
+                        <input type="checkbox" class="custom-control-input" id="switchFecha"
+                            v-model="store.filters.switchFecha" @input="store.filters.switchFechas">
+                        <label class="custom-control-label" for="switchFecha"></label>
+                    </div>
+                </label>
+
+                <div class="col-6" v-if="store.filters.switchFecha">
+                    <div class="form-row justify-content-around align-items-center">
+                        <input id="fecha_inicio" name="fecha_inicio" class="form-control date-picker col-5 mr-4"
+                            placeholder="Seleccione una fecha de inicio" readonly v-model="store.filters.fecha_inicio">
+                        <input id="fecha_fin" name="fecha_fin" class="form-control date-picker col-5"
+                            placeholder="Seleccione una fecha final" readonly v-model="store.filters.fecha_fin">
+                        <button type="button" class="btn btn-sm form-control col-1 ml-auto"
+                            :class="store.filters.fecha_inicio == null || store.filters.fecha_fin == null || store.current.fechas_clicked ? 'btn-info' : 'btn-success'"
+                            :disabled="store.filters.fecha_inicio == null || store.filters.fecha_fin == null || store.current.fechas_clicked"
+                            @click="store.filters.fetchByDate">
+                            <i class="ing-aceptar"></i>
+                        </button>
+                    </div>
+                </div>
+
+                <div class="col-6" v-if="!store.filters.switchFecha">
+                    <div class="form-row">
+                        <input id="fecha" name="fecha" class="form-control date-picker"
+                            placeholder="Seleccione una fecha" readonly v-model="store.filters.fecha">
+                    </div>
+                </div>
+            </div>
         </div>
 
         <div class="mt-3 d-flex justify-content-center flex-wrap">

+ 1 - 0
import/html_header.php

@@ -14,6 +14,7 @@ if (!isset($_SESSION['user'])) {
 }
 
 $user = unserialize($_SESSION['user']);
+$user->access();
 $grupos = $user->admin ? queryAll("SELECT * FROM GRUPO ORDER BY grupo_nombre") : $db->query("SELECT * FROM GRUPO WHERE grupo_id IN (SELECT grupo_id FROM PERMISO_VIEW WHERE id = :id) ORDER BY grupo_nombre", array(":id" => $user->user['id']));
 
 function html_header($title, $header = null)

+ 5 - 3
import/periodo.php

@@ -17,8 +17,10 @@ $user or die("Error: no se pudo cargar el usuario");
                     <label for="periodo" class="col-4 col-form-label">Cambiar de periodo</label>
                     <div class="col-6">
                         <div id="dlPeriodo" class="datalist datalist-select mb-1 w-100">
-                            <div class="datalist-input">Selecciona un periodo</div>
-                            <span class="ing-buscar icono"></span>
+                            <div class="datalist-input">
+                                Selecciona un periodo
+                            </div>
+                            <span class="icono ing-buscar"></span>
                             <ul style="display:none">
                                 <?php
                                 foreach ($niveles as $nivel) {
@@ -63,6 +65,6 @@ $user or die("Error: no se pudo cargar el usuario");
     makeRequiredDatalist("#periodo", true);
 
     $(document).on('click', '#dlPeriodo ul li:not(.not-selectable)', function () {
-        $('form#formaPeriodo').submit();
+        setTimeout(() => $('form#formaPeriodo').submit(), 0);
     });
 </script>

+ 14 - 9
js/auditoría.js

@@ -15,6 +15,7 @@ const store = reactive({
         perPage: 10,
         modal_state: "Cargando datos...",
         justificada: null,
+        fechas_clicked: false,
     },
     facultades: {
         data: [],
@@ -32,7 +33,6 @@ const store = reactive({
         profesor: null,
         periodo_id: null,
         bloque_horario: null,
-        sin_registro: false,
         estados: [],
         switchFecha: false,
         async switchFechas() {
@@ -54,10 +54,12 @@ const store = reactive({
                 const fecha = $("#fecha"), inicio = $("#fecha_inicio"), fin = $("#fecha_fin");
                 fecha.datepicker("setDate", new Date(`${periodo_data.fecha_final}:00:00:00`));
                 inicio.on("change", function () {
+                    store.current.fechas_clicked = false;
                     store.filters.fecha_inicio = inicio.val();
                     fin.datepicker("option", "minDate", inicio.val());
                 });
                 fin.on("change", function () {
+                    store.current.fechas_clicked = false;
                     store.filters.fecha_fin = fin.val();
                     inicio.datepicker("option", "maxDate", fin.val());
                 });
@@ -70,6 +72,7 @@ const store = reactive({
             });
         },
         async fetchByDate() {
+            store.current.fechas_clicked = true;
             $('div.modal#cargando').modal('show');
             await store.registros.fetch(undefined, store.filters.fecha_inicio, store.filters.fecha_fin);
             store.current.page = 1;
@@ -84,7 +87,12 @@ const store = reactive({
             this.data = await res.json();
         },
         getEstado(id) {
-            return this.data.find((estado) => estado.estado_supervisor_id === id);
+            return this.data.find((estado) => estado.estado_supervisor_id === id) ?? {
+                estado_color: 'dark',
+                estado_icon: 'ing-cancelar',
+                nombre: 'Sin registro',
+                estado_supervisor_id: -1,
+            };
         },
         printEstados() {
             if (store.filters.estados.length > 0)
@@ -108,7 +116,7 @@ const store = reactive({
     toggle(arr, element) {
         const newArray = arr.includes(element) ? arr.filter((item) => item !== element) : [...arr, element];
         // if all are selected, then unselect all
-        if (newArray.length === this.estados.data.length) {
+        if (newArray.length === (this.estados.data.length + 1)) {
             setTimeout(() => {
                 document.querySelectorAll('#dlAsistencia>ul>li.selected').forEach(element => element.classList.remove('selected'));
             }, 100);
@@ -213,16 +221,13 @@ const store = reactive({
                         case 'estados':
                             if (store.filters[filtro].length === 0)
                                 return true;
+                            else if (store.filters[filtro].includes(-1) && registro.estado_supervisor_id === null)
+                                return true;
                             return store.filters[filtro].includes(registro.estado_supervisor_id);
                         case 'bloque_horario':
                             const bloque = store.bloques_horario.data.find((bloque) => bloque.id === store.filters[filtro]);
                             return registro.horario_hora < bloque.hora_fin && registro.horario_fin > bloque.hora_inicio;
-                        default: {
-                            if (store.filters.sin_registro)
-                                return !registro.registro_fecha_supervisor;
-                            else
-                                return registro.registro_fecha_supervisor;
-                        }
+                        default: return true;
                     }
                 });
             });

+ 39 - 260
js/datalist.js

@@ -1,264 +1,43 @@
-/* 
- * Selects con datalist
- */
-var click_in_process = false;
-var visible = false;
-
-$('.datalist-text .datalist-input').on('focusin', function () {
-    var elementRoot = $(this).parents('.datalist');
-
-    elementRoot.find(".icono").show();
-    elementRoot.find("ul").show();
-    elementRoot.find(".datalist-input").trigger("keyup");
-});
-
-
-
-function ocultaList(e) {
-    (e.data.padre).find('.icono').removeClass('ing-cancelar iconoAzul pointer').addClass('ing-buscar');
-    (e.data.padre).find('ul').hide();
-    // $('.datalist .icono').removeClass('ing-cancelar iconoAzul pointer').addClass('ing-buscar');
-    // $('.datalist ul').hide();
-}
-
-function ocultaTodos() {
-    $('.datalist .icono').removeClass('ing-cancelar iconoAzul pointer').addClass('ing-buscar');
-    $('.datalist ul').hide();
-}
-
-//$('.datalist-input').click(function(){
-$(document).on('click', '.datalist-input', function () {
-    var elementRoot = $(this).parent();
-    limpiaInput({ "data": { "padre": elementRoot } });
-
-    const alreadyOpen = elementRoot.find('ul').is(':visible');
-    if (alreadyOpen) {
-        setTimeout(() => {
-            ocultaTodos();
-        }, 0);
-        // stop all jquery animations
-        return;
-    }
-
-
-    if (!elementRoot.hasClass("disabled")) {
-        elementRoot.find('ul').show();
-        elementRoot.find('.datalist-input').focus();
-        elementRoot.find('ul').show();
-        elementRoot.find('.icono').removeClass('ing-buscar').addClass('ing-cancelar iconoAzul pointer');
-        elementRoot.find('.icono').on('click', { "padre": elementRoot }, limpiaInput);
-        elementRoot.find('.icono').on('click', { "padre": elementRoot }, ocultaList);
-    }
-
-    // if other datalist is open, close it
-    $('.datalist').each(function () {
-        // get the input hidden from the datalist
-        var inputHidden = $(this).find('input[type="hidden"]').attr('id');
-        // get the input hidden from the datalist that was clicked
-        var inputHiddenClicked = elementRoot.find('input[type="hidden"]').attr('id');
-        if ($(this).find('ul').is(':visible') && inputHidden != inputHiddenClicked) {
-            $(this).find('ul').hide();
-            $(this).find('.icono').removeClass('ing-cancelar iconoAzul pointer').addClass('ing-buscar');
-        }
-    });
-
-
-});
-
-//usar class="selected" para marcar seleccioando por default
 $(function () {
-    $.each($(".datalist").find('ul li:not(.not-selectable)'), function () {
-        if ($(this).hasClass("selected")) {
-            var elementRoot = $(this).parents('.datalist');
-            elementRoot.find('.datalist-input').html($(this).html().replace(/[\t\n]+/g, ' ').trim());
-            var cid = $(this).data('id');
-            elementRoot.find("input[type=hidden]").val(cid);
-        }
-    });
-
-    // add not-selectable class to all li elements and the .datalist-input element
-    $('.datalist-input ul li, .datalist-input').addClass('user-select-none');
-});
-
-$(document).on('click', '.datalist-select > ul li:not(.not-selectable)', function () {
-    var elementRoot = $(this).parents('.datalist');
-    elementRoot.find('.datalist-input').html($(this).html().replace(/[\t\n]+/g, ' ').trim());
-    // $(this).parent('ul').siblings('input[type="text"]').blur();
-    ocultaList({ "data": { "padre": elementRoot } });
-    var cid = $(this).data('id');
-    elementRoot.find("input[type=hidden]").val(cid);
-    elementRoot.find("li").removeClass("selected");
-    $(this).addClass("selected");
-    elementRoot.removeClass("datalist-invalid");
-});
-
-$('.modal').on('hide.bs.modal', function (e) {
-    $('.datalist .icono').removeClass('ing-cancelar iconoAzul pointer').addClass('ing-buscar');
-    $('.datalist ul').hide();
-});
-
-function setDatalist(selector, value = -1) {
-    var elementRoot = $(selector).parents('.datalist');
-    $.each(elementRoot.find('ul li:not(.not-selectable)'), function () {
-        if ($(this).data("id") == value) {
-            elementRoot.find('.datalist-input').text($(this).html().replace(/[\t\n]+/g, ' ').trim());
-            $(selector).val(value);
-            elementRoot.find("li").removeClass("selected");
+    const toggleIcon = (el, fromClass, toClass) => $(el).removeClass(fromClass).addClass(toClass);
+
+    const ocultaTodos = () => {
+        toggleIcon('.datalist .icono', 'ing-cancelar iconoAzul pointer', 'ing-buscar');
+        $('.datalist ul').hide();
+    };
+
+    $(document)
+        .on('click', '.datalist-input,.icono', function () {
+            const parent = $(this).parent();
+            $(".datalist ul:visible").not(parent.find('ul')).siblings('.datalist-input').trigger('click');
+            if (parent.find('ul').is(':visible') || parent.hasClass("disabled")) return ocultaTodos();
+
+            parent.find('ul, .datalist-input').show();
+            toggleIcon(parent.find('.icono'), 'ing-buscar', 'ing-cancelar iconoAzul pointer');
+        })
+        .on('click', '.datalist-select > ul li:not(.not-selectable)', function () {
+            const parent = $(this).closest('.datalist');
+            parent.find('.datalist-input').text($(this).text().trim());
+            parent.find("input[type=hidden]").val($(this).data('id'));
+            $('.datalist li').removeClass("selected");
             $(this).addClass("selected");
-        }
-    });
-}
-
-function setDatalistFirst(selector) {
-    var index = 1;
-    var elementRoot = $(selector).parents('.datalist');
-    var num = elementRoot.find('ul li:not(.not-selectable)').length;
-    if (index <= num) {
-        while (elementRoot.find('ul li:nth-child(' + index + ')').hasClass("not-selectable") && index <= num) {
-            index++;
-        }
-        var element = elementRoot.find('ul li:nth-child(' + index + ')');
-        elementRoot.find('.datalist-input').text(element.html().replace(/[\t\n]+/g, ' ').trim());
-        $(selector).val(element.data("id"));
-        elementRoot.find("li").removeClass("selected");
-        element.addClass("selected");
-    }
-}
-
-function disableDatalist(selector, disabled = true) {
-    var elementRoot = $(selector).parents('.datalist');
-    if (disabled) {
-        elementRoot.addClass("disabled");
-        ocultaList({ "data": { "padre": elementRoot } });
-    } else
-        elementRoot.removeClass("disabled");
-}
-
-function invalidDatalist(selector, invalid = true) {
-    var elementRoot = $(selector).parents('.datalist');
-    if (invalid) {
-        elementRoot.addClass("datalist-invalid");
-    } else
-        elementRoot.removeClass("datalist-invalid");
-}
-
-function buscaDatalist(selector, valor) {
-    selector.find('ul li').each(function () {
-        var elem = $(this);
-        if ($(this).parent().is('li'))
-            elem = $(this).parent();
-        if (!$(this).html().toUpperCase().includes(valor.toUpperCase())) {
-            $(elem).hide();
-            selector.find('.datalist-input').val("");
-            selector.find("input[type=hidden]").val("");
-        } else
-            $(elem).show();
-    });
-}
-function getDatalistText(selector, valor) {
-    var elementRoot = $(selector).parents('.datalist');
-    var text = "";
-    $.each(elementRoot.find('ul li:not(.not-selectable)'), function () {
-        if ($(this).data("id") == valor) {
-            text = $(this).html();
-        }
-    });
-    return text;
-}
-//---
-$('.datalist-text .datalist-input').keyup(function () {
-    var elementRoot = $(this).parents('.datalist');
-    var input = $(this);
-    elementRoot.find('ul li').each(function () {
-        var elem = $(this);
-        if ($(this).parent().is('li'))
-            elem = $(this).parent();
-        if (!$(this).html().toUpperCase().includes(input.val().toUpperCase()))
-            $(elem).hide();
-        else
-            $(elem).show();
+            parent.removeClass("datalist-invalid");
+            ocultaTodos();
+        })
+        .on('click', (e) => {
+            if (!$(e.target).closest('.datalist').length) ocultaTodos();
+        });
+
+    $('.modal').on('hide.bs.modal', ocultaTodos);
+});
+const setDatalist = (selector, value = -1) => {
+    const parent = $(selector).closest('.datalist');
+    parent.find('ul li:not(.not-selectable)').each(function () {
+        if ($(this).data("id") !== value) return;
+        parent.find('.datalist-input').text($(this).text().trim());
+        $(selector).val(value);
+        $('.datalist li').removeClass("selected");
+        $(this).addClass("selected");
     });
-});
-
-/*
-$('.datalist-text input').blur(function() {
-    var elementRoot = $(this).parents('.datalist');
-    console.log("Click? "+click_in_process);
-    if(!click_in_process) {
-        buscaDatalist(elementRoot, elementRoot.find('.datalist-input').val());
-        
-        elementRoot.find('.icono').removeClass('ing-cancelar iconoAzul pointer').addClass('ing-buscar');
-        elementRoot.find('ul').children('li').show();
-        elementRoot.find('ul').hide();
-    }
-    click_in_process = false;
-});
-*/
-
-$('.datalist-text > ul li:not(.not-selectable)').click(function () {
-    console.log("Li click!" + $(this).html());
-    var elementRoot = $(this).parents('.datalist');
-    elementRoot.find('.datalist-input').val($(this).html().replace(/[\t\n]+/g, ' ').trim());
-
-    //$(this).parent('ul').siblings('input[type="text"]').blur();
-
-    var cid = $(this).data('id');
-    elementRoot.find("input[type=hidden]").val(cid);
-    elementRoot.find("li").removeClass("selected");
-    $(this).addClass("selected");
-    click_in_process = true;
-    //elementRoot.find('.datalist-input').blur();
-    ocultaList({ "data": { "padre": elementRoot } });
-});
-
-/* $('.datalist-text .datalist-input').click(function () {
-    var elementRoot = $(this).parents('.datalist');
-    limpiaInput({ "data": { "padre": elementRoot } });
-    const alreadyOpen = elementRoot.find('ul').is(':visible');
-    console.log("Click! " + alreadyOpen);
-    elementRoot.find('ul').show();
-    elementRoot.find('input').focus();
-    elementRoot.find('ul').show();
-    elementRoot.find('.icono').removeClass('ing-buscar').addClass('ing-cancelar iconoAzul pointer');
-    elementRoot.find('.icono').on('click', { "padre": elementRoot }, limpiaInput);
-}); */
-
-$(document).on('click', function (e) {
-    var target = $(e.target);
-    // or if you click in the .datalist-input and the datalist is visible
-    let isDatalist = target.parents().addBack().is('.datalist');
-    // alert(isDatalist);
-
-    if (!isDatalist)
-        ocultaList({ "data": { "padre": $('.datalist') } });
-    // if the data list is visible and you click in the input, hide the list
-});
-
-
-function limpiaInput(e) {
-    (e.data.padre).find('.datalist-input').val('');
-    (e.data.padre).find('.datalist-input').parent().children('ul').children('li').show();
-    (e.data.padre).find('li:first').focus();
-    (e.data.padre).find('.datalist-input').focus();
-
-}
-
-// function make required
-function makeRequiredDatalist(selector, required = true) {
-    var elementRoot = $(selector).parents('.datalist');
-    if (required)
-        elementRoot.addClass("required");
-    else
-        elementRoot.removeClass("required");
-}
-
-// function validate
-function validateDatalist(selector) {
-    var elementRoot = $(selector).parents('.datalist');
-    if (elementRoot.hasClass("required") && $(selector).val() == "") {
-        invalidDatalist(selector, true);
-        return false;
-    }
-    invalidDatalist(selector, false);
-    return true;
 }
+const makeRequiredDatalist = (selector, required = true) => $(selector).closest('.datalist').toggleClass("required", required);

+ 21 - 0
log/asistencias_2023_08.log

@@ -1 +1,22 @@
 2023-08-18 10:17:06||1||Materias||Alejandro Rosales
+2023-08-21 10:56:04||1||Consultar horario||Alejandro Rosales
+2023-08-21 10:56:07||1||Consultar horario||Alejandro Rosales
+2023-08-21 10:56:08||1||Consultar horario||Alejandro Rosales
+2023-08-21 10:56:11||1||Consultar asistencia||Alejandro Rosales
+2023-08-21 10:56:49||1||Consultar asistencia||Alejandro Rosales
+2023-08-21 10:56:51||1||Consultar horario||Alejandro Rosales
+2023-08-21 10:56:53||1||Consultar horario||Alejandro Rosales
+2023-08-21 12:08:55||2||Avisos||Alejandro Lara
+2023-08-21 12:09:00||2||Avisos Crear||Alejandro Lara
+2023-08-21 12:10:10||2||Avisos||Alejandro Lara
+2023-08-21 12:10:18||2||Avisos Crear||Alejandro Lara
+2023-08-21 12:10:41||2||Avisos||Alejandro Lara
+2023-08-21 12:11:09||2||Avisos Crear||Alejandro Lara
+2023-08-21 12:12:19||2||Profesores||Alejandro Lara
+2023-08-21 12:12:24||2||Profesores||Alejandro Lara
+2023-08-21 12:12:30||2||Profesores||Alejandro Lara
+2023-08-21 12:54:01||1||Permisos||Alejandro Rosales
+2023-08-21 12:54:30||1||Permisos||Alejandro Rosales
+2023-08-21 12:55:04||1||Permisos||Alejandro Rosales
+2023-08-21 12:57:17||1||Permisos||Alejandro Rosales
+2023-08-21 13:03:47||1||Permisos||Alejandro Rosales

+ 13 - 8
ts/auditoría.ts

@@ -1,4 +1,3 @@
-import { Alert } from 'bootstrap';
 import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
 
 type Registro = {
@@ -87,6 +86,7 @@ const store = reactive({
         perPage: 10,
         modal_state: "Cargando datos...",
         justificada: null,
+        fechas_clicked: false,
     },
     facultades: {
         data: [] as Facultad[],
@@ -104,7 +104,6 @@ const store = reactive({
         profesor: null,
         periodo_id: null,
         bloque_horario: null,
-        sin_registro: false,
         estados: [],
 
         switchFecha: false,
@@ -129,10 +128,12 @@ const store = reactive({
                 const fecha = $("#fecha"), inicio = $("#fecha_inicio"), fin = $("#fecha_fin")
                 fecha.datepicker("setDate", new Date(`${periodo_data.fecha_final}:00:00:00`));
                 inicio.on("change", function () {
+                    store.current.fechas_clicked = false;
                     store.filters.fecha_inicio = inicio.val()
                     fin.datepicker("option", "minDate", inicio.val());
                 });
                 fin.on("change", function () {
+                    store.current.fechas_clicked = false;
                     store.filters.fecha_fin = fin.val()
                     inicio.datepicker("option", "maxDate", fin.val());
                 });
@@ -147,6 +148,7 @@ const store = reactive({
             });
         },
         async fetchByDate() {
+            store.current.fechas_clicked = true;
             $('div.modal#cargando').modal('show');
             await store.registros.fetch(undefined, store.filters.fecha_inicio, store.filters.fecha_fin);
             store.current.page = 1;
@@ -161,7 +163,12 @@ const store = reactive({
             this.data = await res.json()
         },
         getEstado(id: number): Estado {
-            return this.data.find((estado: Estado) => estado.estado_supervisor_id === id)
+            return this.data.find((estado: Estado) => estado.estado_supervisor_id === id) ?? {
+                estado_color: 'dark',
+                estado_icon: 'ing-cancelar',
+                nombre: 'Sin registro',
+                estado_supervisor_id: -1,
+            }
         },
         printEstados() {
             if (store.filters.estados.length > 0)
@@ -188,7 +195,7 @@ const store = reactive({
     toggle(arr: any, element: any) {
         const newArray = arr.includes(element) ? arr.filter((item: any) => item !== element) : [...arr, element]
         // if all are selected, then unselect all
-        if (newArray.length === this.estados.data.length) {
+        if (newArray.length === (this.estados.data.length + 1)) {
             setTimeout(() => {
                 document.querySelectorAll('#dlAsistencia>ul>li.selected')!.forEach(element => element.classList.remove('selected'));
             }, 100)
@@ -288,14 +295,12 @@ const store = reactive({
                             return registro.facultad_id === store.filters[filtro];
                         case 'estados':
                             if (store.filters[filtro].length === 0) return true;
+                            else if (store.filters[filtro].includes(-1) && registro.estado_supervisor_id === null) return true;
                             return store.filters[filtro].includes(registro.estado_supervisor_id);
                         case 'bloque_horario':
                             const bloque = store.bloques_horario.data.find((bloque: Bloque_Horario) => bloque.id === store.filters[filtro]) as Bloque_Horario;
                             return registro.horario_hora < bloque.hora_fin && registro.horario_fin > bloque.hora_inicio;
-                        default: {
-                            if (store.filters.sin_registro) return !registro.registro_fecha_supervisor
-                            else return registro.registro_fecha_supervisor
-                        }
+                        default: return true;
                     }
                 })
             })