This commit is contained in:
David Itehua Xalamihua 2025-04-25 17:51:34 -06:00
parent 3ee8689b74
commit 34b3840d15
19 changed files with 356 additions and 5284 deletions

View File

@ -5,6 +5,10 @@ https://htmlstream.com/preview/front-v3.2/documentation/aos.html
psql -h 127.0.0.1 -U postgres -d formha -a -f forma_backup_24_04_2025.sql
psql -h 127.0.0.1 -U postgres -d formha -a -f formha_backup.sql
BACKUP
n_file="db_formha_backup_$(date +"%d_%m_%Y-%H_%M_%S").sql"
pg_dump -h 127.0.0.1 -U postgres -d formha -f "$n_file"
psql -h 127.0.0.1 -U postgres -d formha -a -f db_formha_backup_25_04_2025-17_41_55.sql

View File

@ -38,12 +38,15 @@ CREATE TABLE users(
email VARCHAR(150),
pswd VARCHAR(100),
lst_conn TIMESTAMP WITH TIME ZONE,
is_admin boolean
is_admin boolean,
is_pswd_reseted boolean,
is_contact_noti boolean
);
INSERT INTO users (id, nombre, apellido, genero, email, pswd, is_admin) VALUES
('4HlOjqJ6jLISxNQIbs2Hzz', 'David', 'Itehua Xalamihua', 'M', 'davidix1991@gmail.com', '$2b$12$dbJWK5mv89PszxPeXlql5Otd8vv7kz6M44JnKZcrwJdKoovayiqEm', false),
('4FyJhu54R6ARH2FlmroTxl', 'David', 'Itehua Xalamihua', 'M', 'davicho1991@live.com', '$2b$12$dbJWK5mv89PszxPeXlql5Otd8vv7kz6M44JnKZcrwJdKoovayiqEm', true );
INSERT INTO users (id, nombre, apellido, genero, email, pswd, is_admin, is_contact_noti) VALUES
('4HlOjqJ6jLISxNQIbs2Hzz', 'David', 'Itehua Xalamihua', 'M', 'davidix1991@gmail.com', '$2b$12$dbJWK5mv89PszxPeXlql5Otd8vv7kz6M44JnKZcrwJdKoovayiqEm', false, true),
('4FyJhu54R6ARH2FlmroTxl', 'David', 'Itehua Xalamihua', 'M', 'davicho1991@live.com', '$2b$12$dbJWK5mv89PszxPeXlql5Otd8vv7kz6M44JnKZcrwJdKoovayiqEm', true, true);
CREATE TABLE posts (

File diff suppressed because it is too large Load Diff

View File

@ -44,13 +44,12 @@ export forma_db='{
#/////////////////////////////////////
```
# Movemos el archivo de configuración a Apache (solo se hace 1 vez)
## SI TE DA ERROR PRIMERO DESACTIVA APACHE EL PROBLEMA ES LAS VARIABLES DE ENTORNO
sudo systemctl stop apache2
sudo mv formha.conf /etc/apache2/sites-available/
cd /etc/apache2/sites-available/
sudo a2ensite formha.conf
```bash
sudo systemctl reload apache2

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,5 @@
# sudo apachectl configtest
Listen 8085
<VirtualHost *:8085>
ServerAdmin davidix1991@gmail.com
ServerName formha.temporal.work

View File

@ -121,7 +121,7 @@ class DBForma:
Raises:
RuntimeError: Si ocurre un error durante la operación
"""
query = "UPDATE users SET pswd = %s WHERE email = %s;"
query = "UPDATE users SET pswd = %s, is_pswd_reseted = true WHERE email = %s;"
try:
with self._get_connection() as conn:
with conn.cursor() as cursor:

View File

@ -30,3 +30,8 @@ class AddUser(FlaskForm):
("false", "No")
], validators=[DataRequired(message="Debes seleccionar el rol.")],)
isContactNoti = SelectField( "Notificaciones de nuevos contactos", choices=[
("", ""),
("true", ""),
("false", "No")
], validators=[DataRequired(message="Debes seleccionar una respuesta.")],)

47
main.py
View File

@ -26,7 +26,7 @@ bcrypt = Bcrypt(app)
email_sender = os.getenv("email_sender")
email_pswd = os.getenv("pswd_formha")
lst_email_to = ["davidix1991@gmail.com", "davicho1991@live.com"]
# lst_email_to = ["davidix1991@gmail.com", "davicho1991@live.com"]
# \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
# INICIO CONFIGURACIÓN JWT
@ -83,6 +83,11 @@ dbContact = DBContact(jsonDbContact)
dbUsers = DBForma(jsonDbContact)
def lst_email_to() -> list:
data = dbUsers.get_all_data('SELECT email FROM users WHERE is_contact_noti = true;')
re = [ele[0] for ele in data]
return re
# decorador para rutas protegidas en caso de que borres al vuelo a un usuario.
def validate_user_exists(f):
@wraps(f)
@ -258,7 +263,7 @@ def contact():
dbContact.carga_contact(data)
# Configurar y enviar email asíncrono
msg = Message( "Subject, una persona busca asesoria", sender=email_sender, recipients=lst_email_to )
msg = Message( "Subject, una persona busca asesoria", sender=email_sender, recipients=lst_email_to() )
msg.html ="""
<h1>Nuevo contacto recibido</h1>
@ -290,6 +295,8 @@ def login():
if bcrypt.check_password_hash(res_pswd_server, f_pswd):
id_user = dbUsers.get_id(f_email)[0]
is_admin = dbUsers.get_data('SELECT is_admin FROM users WHERE id = %s;', (id_user,))[0]
# Crear token JWT: access_token = create_access_token(identity=id_user)
@ -407,10 +414,14 @@ def user_home():
exp = token_data['exp']
# id del usuario activo:
usr_id = token_data['sub']
is_pswd_reseted = dbUsers.get_data('SELECT is_pswd_reseted FROM users WHERE id = %s;', (usr_id,))[0]
update_pswd = l_flash_msj('Recomendación', 'Cambia tu contraseña por una que recuerdes.', 'warning') if is_pswd_reseted else None
q = "SELECT nombre, genero, lst_conn FROM users WHERE id = %s;"
data_saludo = dbUsers.get_data(q, (usr_id,))
nombre, gender, lst_conn = data_saludo
@ -428,6 +439,9 @@ def user_home():
# dbUsers.update_data(q, d)
flash(f_mnsj)
flash(update_pswd)
q = "UPDATE users SET lst_conn = %s WHERE id = %s;"
d = (cur_date(), usr_id)
dbUsers.update_data(q, d)
@ -631,7 +645,7 @@ def change_pswd():
if bcrypt.check_password_hash(data, f_old_pswd):
new_hash_pswd = hash_password(f_new_pswd)
q = "UPDATE users SET pswd = %s WHERE id = %s;"
q = "UPDATE users SET pswd = %s, is_pswd_reseted = false WHERE id = %s;"
t = (new_hash_pswd, usr_id)
dbUsers.update_data(q, t)
@ -750,7 +764,11 @@ def manage_profiles():
WHEN u.is_admin = true THEN ''
WHEN u.is_admin = false THEN 'No'
END AS admin,
COALESCE(p.conteo, 0) AS conteo
COALESCE(p.conteo, 0) AS conteo,
CASE
WHEN u.is_contact_noti = true THEN ''
WHEN u.is_contact_noti = false THEN 'No'
END AS isNotificated
FROM users u
LEFT JOIN (
SELECT id_usr, COUNT(*) AS conteo
@ -766,7 +784,8 @@ def manage_profiles():
f_apellido = f'{form.apellido.data}'.title().strip()
f_genero = form.genero.data
f_email = f'{form.email.data}'.lower().strip()
f_isAdmin = form.isAdmin.data.strip().upper()
f_isAdmin = f'{form.isAdmin.data}'.upper().strip()
f_isContactNoti = f'{form.isContactNoti.data}'.upper().strip()
f_id = form.id.data.strip()
f_mnsj = None
q = None
@ -774,10 +793,10 @@ def manage_profiles():
subject = None
html_content = None
# si el f_id no es igual a '' entonces es una actualización de datos
if f_id != '':
q = "UPDATE users SET nombre = %s, apellido = %s, genero = %s, email = %s, is_admin = %s WHERE id = %s;"
t = (f_nombre, f_apellido, f_genero, f_email, f_isAdmin, f_id)
q = "UPDATE users SET nombre = %s, apellido = %s, genero = %s, email = %s, is_admin = %s, is_contact_noti = %s WHERE id = %s;"
t = (f_nombre, f_apellido, f_genero, f_email, f_isAdmin, f_isContactNoti, f_id)
f_mnsj = l_flash_msj('Éxito', f'Usuario actualizado: {f_nombre}', 'success')
subject = "Usuario actualizado"
html_content = """
@ -789,12 +808,14 @@ def manage_profiles():
<p><strong>Email:</strong> {}</p>
""".format(f_nombre, f_apellido, f_genero, f_email)
# en caso de que el f_id = '' quiere decir que es un nuevo registro y debo checar que no sea un registro preexiste a partir del email
else:
q_isDuplicated = "SELECT email FROM users WHERE email = %s;"
t_isDuplicated = (f_email,)
isDuplicated = dbUsers.get_data(q_isDuplicated, t_isDuplicated)
if isDuplicated is not None:
f_mnsj = l_flash_msj('Error', 'El correo electrónico ya existe.', 'error')
f_mnsj = l_flash_msj('Error', 'El correo electrónico ya existe, NO SE SOBREESCRIBE EL USUARIO EXISTENTE.', 'error')
flash(f_mnsj)
return redirect(url_for('manage_profiles'))
@ -802,8 +823,8 @@ def manage_profiles():
random_id = getRandomId()
tmp_pswd = generar_contrasena()
hashed_pswd = hash_password(tmp_pswd)
q = "INSERT INTO users (id, nombre, apellido, genero, email, pswd, is_admin ) values (%s, %s, %s, %s, %s, %s, %s);"
t = (random_id, f_nombre, f_apellido, f_genero, f_email, hashed_pswd, f_isAdmin)
q = "INSERT INTO users (id, nombre, apellido, genero, email, pswd, is_admin, is_pswd_reseted ) values (%s, %s, %s, %s, %s, %s, %s, %s);"
t = (random_id, f_nombre, f_apellido, f_genero, f_email, hashed_pswd, f_isAdmin, True)
f_mnsj = l_flash_msj('Éxito', f'Usuario creado: {f_nombre}', 'success')
subject = "Nueva cuenta creada"
html_content = """
@ -859,7 +880,7 @@ def delete_user():
def get_user():
data = request.get_json()
id_usr = data['id']
q = "SELECT id, nombre, apellido, genero, email, is_admin FROM users WHERE id = %s;"
q = "SELECT id, nombre, apellido, genero, email, is_admin, is_contact_noti FROM users WHERE id = %s;"
t = (id_usr,)
dbData = dbUsers.get_data(q, t)
return jsonify({"data": dbData})

View File

@ -1,4 +1,7 @@
import {simpleNotification} from '../z_comps/notify.js';
simpleNotification(data.title, data.body, data.typeAlert);
for (let data of dataList) {
simpleNotification(data.title, data.body, data.typeAlert);
}

View File

@ -49,10 +49,11 @@
</nav>
<!-- {# f pagination #} -->
<div class="row">
<div class="row" data-aos="fade-up" data-aos-delay="0" data-aos-duration="800">
{% for post in data %}
<div class="col-12 col-sm-8 col-md-6 col-lg-4">
<div class="card" data-aos="fade-up" data-aos-delay="0" data-aos-duration="800">
<div class="col-12 col-sm-8 col-md-6 col-lg-4" >
<div class="card">
<img class="card-img" src="{{ post[7] if post[7] else url_for('static', filename='y_img/other/no_img.png') }}" alt="">

View File

@ -16,16 +16,16 @@
{% block body %}
<h1>Solicitudes de Contacto</h1>
{% if is_admin %}
{% include 'z_comps/download_xlsx.html' %}
{% endif %}
<div>
<h1>Solicitudes de Contacto</h1>
{% if is_admin %}
{% include 'z_comps/download_xlsx.html' %}
{% endif %}
<table id="dbContact" class="table table-striped" style="width:100%" data-aos="fade-right" data-aos-delay="0" data-aos-duration="800" data-aos-easing="ease-in-out">
<table id="dbContact" class="table table-striped" style="width:100%" data-aos="fade-right" data-aos-delay="0"
data-aos-duration="800" data-aos-easing="ease-in-out">
<thead>
<tr>
<th>Fecha</th>
@ -41,7 +41,8 @@
{% for item in data_contact %}
<tr data-id="{{item[0]}}">
<td>
<button data-id="{{item[0]}}" type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalContactData">
<button data-id="{{item[0]}}" type="button" class="btn btn-primary" data-bs-toggle="modal"
data-bs-target="#modalContactData">
{{item[1]}}
</button>
</td>
@ -55,20 +56,21 @@
<td>
<select class="form-select" data-id="{{ item[0] }}">
<option value="Null" {% if item[8] is none %}selected{% endif %}></option>
<option value="Opción 1" {% if item[8] == 'Opción 1' %}selected{% endif %}>Opción 1</option>
<option value="Opción 2" {% if item[8] == 'Opción 2' %}selected{% endif %}>Opción 2</option>
<option value="Opción 3" {% if item[8] == 'Opción 3' %}selected{% endif %}>Opción 3</option>
<option value="Opción 4" {% if item[8] == 'Opción 4' %}selected{% endif %}>Opción 4</option>
<option value="Opción 5" {% if item[8] == 'Opción 5' %}selected{% endif %}>Opción 5</option>
<option value="Opción 6" {% if item[8] == 'Opción 6' %}selected{% endif %}>Opción 6</option>
<option value="Opción 7" {% if item[8] == 'Opción 7' %}selected{% endif %}>Opción 7</option>
<option value="Archivado" >Archivar</option>
<option value="Opción 1" {% if item[8]=='Opción 1' %}selected{% endif %}>Opción 1</option>
<option value="Opción 2" {% if item[8]=='Opción 2' %}selected{% endif %}>Opción 2</option>
<option value="Opción 3" {% if item[8]=='Opción 3' %}selected{% endif %}>Opción 3</option>
<option value="Opción 4" {% if item[8]=='Opción 4' %}selected{% endif %}>Opción 4</option>
<option value="Opción 5" {% if item[8]=='Opción 5' %}selected{% endif %}>Opción 5</option>
<option value="Opción 6" {% if item[8]=='Opción 6' %}selected{% endif %}>Opción 6</option>
<option value="Opción 7" {% if item[8]=='Opción 7' %}selected{% endif %}>Opción 7</option>
<option value="Archivado">Archivar</option>
</select>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</table>
</div>
<!-- Modal -->
<div class="modal fade" id="modalContactData" tabindex="-1" aria-labelledby="modalContactDataLabel" aria-hidden="true">
@ -93,8 +95,6 @@
{% block js %}
<!-- {# if flash #} -->
{% include 'z_comps/if_flash.html' %}

View File

@ -12,13 +12,16 @@
{% endblock css %}
{% block body %}
<h1>Crear una publicación</h1>
<div>
<h1>Crear una publicación</h1>
<form id="post-form" data-aos="fade-right" data-aos-delay="0" data-aos-duration="800">
<form id="post-form" data-aos="fade-right" data-aos-delay="0" data-aos-duration="800">
<input type="text" name="title" class="form-control" placeholder="Título de la publicación" maxlength="100">
<div id="summernote"></div>
<button id="btn-submit" type="submit" class="btn btn-success"><i class="bi bi-file-earmark-richtext-fill"></i> Publicar Documento</button>
</form>
<button id="btn-submit" type="submit" class="btn btn-success"><i class="bi bi-file-earmark-richtext-fill"></i>
Publicar Documento</button>
</form>
</div>
{% endblock body %}

View File

@ -11,19 +11,22 @@
{% block body %}
<h2 class="display-5 mb-4">Mis Publicaciones</h2>
<!-- https://codepen.io/componentity/embed/RwajNdW?height=500&theme-id=dark&default-tab=result&user=componentity&slug-hash=RwajNdW&pen-title=Blog%20Card%20Section%20Bootstrap%20-%202nd&name=cp_embed_1 -->
<!-- https://codepen.io/anon/embed/dgmjKK?height=602&theme-id=dark&slug-hash=dgmjKK&default-tab=result&animations=run&editable=&embed-version=2&user=anon&name=cp_embed_23 -->
<!-- https://bootstrapbrain.com/component/bootstrap-5-blog-card/#code -->
<!-- <div class="col-md-12"> -->
<style>
<style>
.fade-out {
opacity: 0;
transition: opacity 0.3s ease;
}
</style>
</style>
<div>
<h2 class="display-5 mb-4">Mis Publicaciones</h2>
<div class="container">
<div class="container">
<!-- {# i pagination #} -->
{% if total_pages > 1 %}
<nav aria-label="Page navigation">
@ -54,7 +57,8 @@
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4 g-4" id="card-container">
{% for ele in data %}
<div class="col card-wrapper" data-id="{{ele[0]}}" data-aos="zoom-out-left" data-aos-delay="{{loop.index * 100 }}" data-aos-duration="800" data-aos-easing="ease-in-out">
<div class="col card-wrapper" data-id="{{ele[0]}}" data-aos="zoom-out-left" data-aos-delay="{{loop.index * 100 }}"
data-aos-duration="800" data-aos-easing="ease-in-out">
<div class="card h-100">
<img src="{{ (ele[5] if ele[5] is not none else url_for('static', filename='y_img/other/no_img.png'))|safe }}"
@ -114,24 +118,10 @@
{% endif %}
<!-- {# f pagination #} -->
</div>
</div>
</div>
<!-- <script>
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', () => {
const wrapper = btn.closest('.card-wrapper');
wrapper.classList.add('fade-out');
setTimeout(() => {
wrapper.remove();
}, 300);
});
});
</script> -->
{% endblock body %}
{% block js %}

View File

@ -18,45 +18,43 @@
}
</style>
<div>
<h1>Métricas del Sitio</h1>
<h2>Métricas del Sitio</h2>
<div class="container-fluid">
<div class="row g-4">
<div class="col-12 col-sm-6" data-aos="fade-right" data-aos-delay="0" data-aos-duration="800" data-aos-easing="ease-in-out" >
<div class="container-fluid">
<div class="row g-4" data-aos="fade-right" data-aos-delay="0" data-aos-duration="800" data-aos-easing="ease-in-out">
<div class="col-12 col-sm-6" >
<div class="p-3 bg-light rounded shadow-sm">
<canvas id="dbContacts"></canvas>
</div>
</div>
<div class="col-12 col-sm-6" data-aos="fade-right" data-aos-delay="100" data-aos-duration="800" data-aos-easing="ease-in-out">
<div class="col-12 col-sm-6">
<div class="p-3 bg-light rounded shadow-sm">
<canvas id="dbEdos"></canvas>
</div>
</div>
<div class="col-12 col-sm-6" data-aos="fade-right" data-aos-delay="200" data-aos-duration="800" data-aos-easing="ease-in-out">
<div class="col-12 col-sm-6">
<div class="p-3 bg-light rounded shadow-sm">
<canvas id="dbSize"></canvas>
</div>
</div>
<div class="col-12 col-sm-6" data-aos="fade-right" data-aos-delay="300" data-aos-duration="800" data-aos-easing="ease-in-out">
<div class="col-12 col-sm-6">
<div class="p-3 bg-light rounded shadow-sm">
<canvas id="dbRol"></canvas>
</div>
</div>
<div class="col-12 col-sm-6" data-aos="fade-right" data-aos-delay="400" data-aos-duration="800" data-aos-easing="ease-in-out">
<div class="col-12 col-sm-6">
<div class="p-3 bg-light rounded shadow-sm">
<canvas id="dbIndustry"></canvas>
</div>
</div>
<div class="col-12 col-sm-6" data-aos="fade-right" data-aos-delay="500" data-aos-duration="800" data-aos-easing="ease-in-out">
<div class="col-12 col-sm-6">
<div class="p-3 bg-light rounded shadow-sm">
<canvas id="dbStatus"></canvas>
</div>
</div>
</div>
</div>
</div>

View File

@ -11,16 +11,61 @@
{% endblock css %}
{% block body %}
<h2>Administrar Perfiles</h2>
<!-- Botón para abrir el modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalFormAddUsr">
<div>
<h1>Administrar Perfiles</h1>
<!-- Botón para abrir el modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalFormAddUsr">
<i class="bi bi-person-fill-add"></i> Añadir Usuario
</button>
</button>
<table id="tblUsers" class="table table-striped" style="width:100%" data-aos="fade-up" data-aos-delay="0"
data-aos-duration="800">
<thead>
<tr>
<th>Nombre</th>
<th>Apellidos</th>
<th>Email</th>
<th>Última Conexión</th>
<th>Admin</th>
<th>Posts</th>
<th>Notificiones Contactos</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
{% for ele in data_all_users %}
<tr data-id="{{ele[0]}}">
<td>{{ ele[1] }}</td>
<td>{{ ele[2] }}</td>
<td>{{ ele[3] }}</td>
<td>{{ ele[4] }}</td>
<td>{{ ele[5] }}</td>
<td>{{ ele[6] }}</td>
<td>{{ ele[7] }}</td>
<td>
<a href="" class="btn btn-primary" data-bs-toggle="modal" data-id="{{ele[0]}}"
data-bs-target="#modalFormAddUsr">
<i class="bi bi-pencil-square"></i>
</a>
{% if id_usr != ele[0] %}
<a href="" class="btn btn-danger delete-btn" data-id="{{ele[0]}}">
<i class="bi bi-trash"></i>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Modal Bootstrap 5 -->
<div class="modal fade" id="modalFormAddUsr" tabindex="-1" aria-labelledby="modalFormAddUsrLabel" aria-hidden="true">
<div class="modal fade" id="modalFormAddUsr" tabindex="-1" aria-labelledby="modalFormAddUsrLabel" aria-hidden="true" >
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
@ -63,61 +108,30 @@
{{ form.isAdmin(class_="form-select", maxlength="35", id="fe_isadmin") }}
</div>
<!-- {# recibe notificaciones de nuevos contactos #} -->
<div>
{{ form.isContactNoti.label(class_='form-label') }}
{{ form.isContactNoti(class_="form-select", maxlength="35", id="isContactNoti") }}
</div>
<button type="submit" class="btn btn-primary" id="btnSubmit"></button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
</form>
<!-- {# f form add user #} -->
</div>
<!-- <div class="modal-footer">
<button type="button" class="btn btn-primary">Save changes</button>
</div> -->
<!-- <div class="modal-footer"> <button type="button" class="btn btn-primary">Save changes</button> </div> -->
</div>
</div>
</div>
<table id="tblUsers" class="table table-striped" style="width:100%">
<thead>
<tr>
<th>Nombre</th>
<th>Apellidos</th>
<th>Email</th>
<th>Última Conexión</th>
<th>Admin</th>
<th>Posts</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
{% for ele in data_all_users %}
<tr data-id="{{ele[0]}}">
<td>{{ ele[1] }}</td>
<td>{{ ele[2] }}</td>
<td>{{ ele[3] }}</td>
<td>{{ ele[4] }}</td>
<td>{{ ele[5] }}</td>
<td>{{ ele[6] }}</td>
<td>
<a href="" class="btn btn-primary" data-bs-toggle="modal" data-id="{{ele[0]}}" data-bs-target="#modalFormAddUsr">
<i class="bi bi-pencil-square"></i>
</a>
{% if id_usr != ele[0] %}
<a href="" class="btn btn-danger delete-btn" data-id="{{ele[0]}}">
<i class="bi bi-trash"></i>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock body %}
{% block js %}
<!-- {# aos script #} -->
{% include 'z_comps/aos_script.html' %}
<script>
let btnAddUsr = document.querySelector('button[data-bs-target="#modalFormAddUsr"]');
@ -128,6 +142,7 @@
let fe_genero = document.getElementById('fe_genero');
let fe_email = document.getElementById('fe_email');
let fe_isadmin = document.getElementById('fe_isadmin');
let fe_isContactNoti = document.getElementById("isContactNoti");
let form_id = document.querySelector('input[name="id"]');
let titleForm = document.getElementById("modalFormAddUsrLabel");
let btnSubmit = document.getElementById("btnSubmit");
@ -139,6 +154,7 @@
fe_email.value = '';
fe_isadmin.value = '';
form_id.value = '';
fe_isContactNoti.value = '';
});
</script>
@ -164,6 +180,7 @@ async function get_user_data(btn) {
let fe_genero = document.getElementById('fe_genero');
let fe_email = document.getElementById('fe_email');
let fe_isadmin = document.getElementById('fe_isadmin');
let fe_isContactNoti = document.getElementById("isContactNoti");
let btn_submit = document.querySelector('#formEditUser button[type="submit"]');
let titleForm = document.getElementById("modalFormAddUsrLabel");
let btnSubmit = document.getElementById("btnSubmit");
@ -176,8 +193,11 @@ async function get_user_data(btn) {
fe_genero.value = data[3];
fe_email.value = data[4];
fe_isadmin.value = data[5];
fe_isContactNoti.value = data[6];
form_id.value = data[0]; // Asignamos el ID recibido
console.log(data)
} catch (error) {
@ -287,7 +307,34 @@ document.getElementById('tblUsers').addEventListener('click', (event) => {
</script>
<script>
new DataTable('#tblUsers');
// new DataTable('#tblUsers');
new DataTable('#tblUsers', {
initComplete: function() {
// Agrega campos de filtro para cada columna
this.api().columns().every(function() {
let column = this;
let header = $(column.header());
let title = header.text().trim();
// Excluir la columna "Estatus" del filtro
if (title !== 'Acciones') {
// Crea input de filtro
header.append('<div class="filter"><input type="text" class="form-control" placeholder="'+title+'" /></div>');
// Aplica el filtro al escribir
$('input', header)
.on('keyup change', function() {
if (column.search() !== this.value) {
column.search(this.value).draw();
}
});
}
});
}
});
</script>
<!-- {# if flash #} -->

View File

@ -1,7 +1,7 @@
{% with messages = get_flashed_messages() %}
{% if messages %}
<script>
let data = JSON.parse(`{{ messages | tojson | safe }}`)[0];
let dataList = JSON.parse(`{{ messages | tojson | safe }}`);
</script>
<script type="module" src="{{url_for('static', filename='f_contact/contact.js')}}"></script>
{% endif %}