ui mod
This commit is contained in:
parent
3ee8689b74
commit
34b3840d15
@ -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 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
|
@ -38,12 +38,15 @@ CREATE TABLE users(
|
|||||||
email VARCHAR(150),
|
email VARCHAR(150),
|
||||||
pswd VARCHAR(100),
|
pswd VARCHAR(100),
|
||||||
lst_conn TIMESTAMP WITH TIME ZONE,
|
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),
|
INSERT INTO users (id, nombre, apellido, genero, email, pswd, is_admin, is_contact_noti) VALUES
|
||||||
('4FyJhu54R6ARH2FlmroTxl', 'David', 'Itehua Xalamihua', 'M', 'davicho1991@live.com', '$2b$12$dbJWK5mv89PszxPeXlql5Otd8vv7kz6M44JnKZcrwJdKoovayiqEm', true );
|
('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 (
|
CREATE TABLE posts (
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -44,13 +44,12 @@ export forma_db='{
|
|||||||
#/////////////////////////////////////
|
#/////////////////////////////////////
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
# Movemos el archivo de configuración a Apache (solo se hace 1 vez)
|
# 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
|
## SI TE DA ERROR PRIMERO DESACTIVA APACHE EL PROBLEMA ES LAS VARIABLES DE ENTORNO
|
||||||
sudo systemctl stop apache2
|
sudo systemctl stop apache2
|
||||||
sudo mv formha.conf /etc/apache2/sites-available/
|
sudo mv formha.conf /etc/apache2/sites-available/
|
||||||
cd /etc/apache2/sites-available/
|
cd /etc/apache2/sites-available/
|
||||||
|
sudo a2ensite formha.conf
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo systemctl reload apache2
|
sudo systemctl reload apache2
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,3 +1,5 @@
|
|||||||
|
# sudo apachectl configtest
|
||||||
|
Listen 8085
|
||||||
<VirtualHost *:8085>
|
<VirtualHost *:8085>
|
||||||
ServerAdmin davidix1991@gmail.com
|
ServerAdmin davidix1991@gmail.com
|
||||||
ServerName formha.temporal.work
|
ServerName formha.temporal.work
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -121,7 +121,7 @@ class DBForma:
|
|||||||
Raises:
|
Raises:
|
||||||
RuntimeError: Si ocurre un error durante la operación
|
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:
|
try:
|
||||||
with self._get_connection() as conn:
|
with self._get_connection() as conn:
|
||||||
with conn.cursor() as cursor:
|
with conn.cursor() as cursor:
|
||||||
|
@ -30,3 +30,8 @@ class AddUser(FlaskForm):
|
|||||||
("false", "No")
|
("false", "No")
|
||||||
], validators=[DataRequired(message="Debes seleccionar el rol.")],)
|
], validators=[DataRequired(message="Debes seleccionar el rol.")],)
|
||||||
|
|
||||||
|
isContactNoti = SelectField( "Notificaciones de nuevos contactos", choices=[
|
||||||
|
("", ""),
|
||||||
|
("true", "Sí"),
|
||||||
|
("false", "No")
|
||||||
|
], validators=[DataRequired(message="Debes seleccionar una respuesta.")],)
|
||||||
|
47
main.py
47
main.py
@ -26,7 +26,7 @@ bcrypt = Bcrypt(app)
|
|||||||
|
|
||||||
email_sender = os.getenv("email_sender")
|
email_sender = os.getenv("email_sender")
|
||||||
email_pswd = os.getenv("pswd_formha")
|
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
|
# INICIO CONFIGURACIÓN JWT
|
||||||
@ -83,6 +83,11 @@ dbContact = DBContact(jsonDbContact)
|
|||||||
dbUsers = DBForma(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.
|
# decorador para rutas protegidas en caso de que borres al vuelo a un usuario.
|
||||||
def validate_user_exists(f):
|
def validate_user_exists(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
@ -258,7 +263,7 @@ def contact():
|
|||||||
dbContact.carga_contact(data)
|
dbContact.carga_contact(data)
|
||||||
|
|
||||||
# Configurar y enviar email asíncrono
|
# 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 ="""
|
msg.html ="""
|
||||||
<h1>Nuevo contacto recibido</h1>
|
<h1>Nuevo contacto recibido</h1>
|
||||||
@ -290,6 +295,8 @@ def login():
|
|||||||
if bcrypt.check_password_hash(res_pswd_server, f_pswd):
|
if bcrypt.check_password_hash(res_pswd_server, f_pswd):
|
||||||
|
|
||||||
id_user = dbUsers.get_id(f_email)[0]
|
id_user = dbUsers.get_id(f_email)[0]
|
||||||
|
|
||||||
|
|
||||||
is_admin = dbUsers.get_data('SELECT is_admin FROM users WHERE id = %s;', (id_user,))[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)
|
# Crear token JWT: access_token = create_access_token(identity=id_user)
|
||||||
@ -407,10 +414,14 @@ def user_home():
|
|||||||
exp = token_data['exp']
|
exp = token_data['exp']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# id del usuario activo:
|
# id del usuario activo:
|
||||||
usr_id = token_data['sub']
|
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;"
|
q = "SELECT nombre, genero, lst_conn FROM users WHERE id = %s;"
|
||||||
data_saludo = dbUsers.get_data(q, (usr_id,))
|
data_saludo = dbUsers.get_data(q, (usr_id,))
|
||||||
nombre, gender, lst_conn = data_saludo
|
nombre, gender, lst_conn = data_saludo
|
||||||
@ -428,6 +439,9 @@ def user_home():
|
|||||||
# dbUsers.update_data(q, d)
|
# dbUsers.update_data(q, d)
|
||||||
flash(f_mnsj)
|
flash(f_mnsj)
|
||||||
|
|
||||||
|
|
||||||
|
flash(update_pswd)
|
||||||
|
|
||||||
q = "UPDATE users SET lst_conn = %s WHERE id = %s;"
|
q = "UPDATE users SET lst_conn = %s WHERE id = %s;"
|
||||||
d = (cur_date(), usr_id)
|
d = (cur_date(), usr_id)
|
||||||
dbUsers.update_data(q, d)
|
dbUsers.update_data(q, d)
|
||||||
@ -631,7 +645,7 @@ def change_pswd():
|
|||||||
|
|
||||||
if bcrypt.check_password_hash(data, f_old_pswd):
|
if bcrypt.check_password_hash(data, f_old_pswd):
|
||||||
new_hash_pswd = hash_password(f_new_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)
|
t = (new_hash_pswd, usr_id)
|
||||||
dbUsers.update_data(q, t)
|
dbUsers.update_data(q, t)
|
||||||
|
|
||||||
@ -750,7 +764,11 @@ def manage_profiles():
|
|||||||
WHEN u.is_admin = true THEN 'Sí'
|
WHEN u.is_admin = true THEN 'Sí'
|
||||||
WHEN u.is_admin = false THEN 'No'
|
WHEN u.is_admin = false THEN 'No'
|
||||||
END AS admin,
|
END AS admin,
|
||||||
COALESCE(p.conteo, 0) AS conteo
|
COALESCE(p.conteo, 0) AS conteo,
|
||||||
|
CASE
|
||||||
|
WHEN u.is_contact_noti = true THEN 'Sí'
|
||||||
|
WHEN u.is_contact_noti = false THEN 'No'
|
||||||
|
END AS isNotificated
|
||||||
FROM users u
|
FROM users u
|
||||||
LEFT JOIN (
|
LEFT JOIN (
|
||||||
SELECT id_usr, COUNT(*) AS conteo
|
SELECT id_usr, COUNT(*) AS conteo
|
||||||
@ -766,7 +784,8 @@ def manage_profiles():
|
|||||||
f_apellido = f'{form.apellido.data}'.title().strip()
|
f_apellido = f'{form.apellido.data}'.title().strip()
|
||||||
f_genero = form.genero.data
|
f_genero = form.genero.data
|
||||||
f_email = f'{form.email.data}'.lower().strip()
|
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_id = form.id.data.strip()
|
||||||
f_mnsj = None
|
f_mnsj = None
|
||||||
q = None
|
q = None
|
||||||
@ -774,10 +793,10 @@ def manage_profiles():
|
|||||||
subject = None
|
subject = None
|
||||||
html_content = None
|
html_content = None
|
||||||
|
|
||||||
|
# si el f_id no es igual a '' entonces es una actualización de datos
|
||||||
if f_id != '':
|
if f_id != '':
|
||||||
q = "UPDATE users SET nombre = %s, apellido = %s, genero = %s, email = %s, is_admin = %s WHERE id = %s;"
|
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_id)
|
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')
|
f_mnsj = l_flash_msj('Éxito', f'Usuario actualizado: {f_nombre}', 'success')
|
||||||
subject = "Usuario actualizado"
|
subject = "Usuario actualizado"
|
||||||
html_content = """
|
html_content = """
|
||||||
@ -789,12 +808,14 @@ def manage_profiles():
|
|||||||
<p><strong>Email:</strong> {}</p>
|
<p><strong>Email:</strong> {}</p>
|
||||||
""".format(f_nombre, f_apellido, f_genero, f_email)
|
""".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:
|
else:
|
||||||
q_isDuplicated = "SELECT email FROM users WHERE email = %s;"
|
q_isDuplicated = "SELECT email FROM users WHERE email = %s;"
|
||||||
t_isDuplicated = (f_email,)
|
t_isDuplicated = (f_email,)
|
||||||
isDuplicated = dbUsers.get_data(q_isDuplicated, t_isDuplicated)
|
isDuplicated = dbUsers.get_data(q_isDuplicated, t_isDuplicated)
|
||||||
|
|
||||||
if isDuplicated is not None:
|
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)
|
flash(f_mnsj)
|
||||||
return redirect(url_for('manage_profiles'))
|
return redirect(url_for('manage_profiles'))
|
||||||
|
|
||||||
@ -802,8 +823,8 @@ def manage_profiles():
|
|||||||
random_id = getRandomId()
|
random_id = getRandomId()
|
||||||
tmp_pswd = generar_contrasena()
|
tmp_pswd = generar_contrasena()
|
||||||
hashed_pswd = hash_password(tmp_pswd)
|
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);"
|
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)
|
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')
|
f_mnsj = l_flash_msj('Éxito', f'Usuario creado: {f_nombre}', 'success')
|
||||||
subject = "Nueva cuenta creada"
|
subject = "Nueva cuenta creada"
|
||||||
html_content = """
|
html_content = """
|
||||||
@ -859,7 +880,7 @@ def delete_user():
|
|||||||
def get_user():
|
def get_user():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
id_usr = data['id']
|
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,)
|
t = (id_usr,)
|
||||||
dbData = dbUsers.get_data(q, t)
|
dbData = dbUsers.get_data(q, t)
|
||||||
return jsonify({"data": dbData})
|
return jsonify({"data": dbData})
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import {simpleNotification} from '../z_comps/notify.js';
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,10 +49,11 @@
|
|||||||
</nav>
|
</nav>
|
||||||
<!-- {# f pagination #} -->
|
<!-- {# f pagination #} -->
|
||||||
|
|
||||||
<div class="row">
|
<div class="row" data-aos="fade-up" data-aos-delay="0" data-aos-duration="800">
|
||||||
{% for post in data %}
|
{% 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="">
|
<img class="card-img" src="{{ post[7] if post[7] else url_for('static', filename='y_img/other/no_img.png') }}" alt="">
|
||||||
|
|
||||||
|
@ -16,16 +16,16 @@
|
|||||||
|
|
||||||
|
|
||||||
{% block body %}
|
{% 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"
|
||||||
<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">
|
data-aos-duration="800" data-aos-easing="ease-in-out">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Fecha</th>
|
<th>Fecha</th>
|
||||||
@ -41,7 +41,8 @@
|
|||||||
{% for item in data_contact %}
|
{% for item in data_contact %}
|
||||||
<tr data-id="{{item[0]}}">
|
<tr data-id="{{item[0]}}">
|
||||||
<td>
|
<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]}}
|
{{item[1]}}
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
@ -55,20 +56,21 @@
|
|||||||
<td>
|
<td>
|
||||||
<select class="form-select" data-id="{{ item[0] }}">
|
<select class="form-select" data-id="{{ item[0] }}">
|
||||||
<option value="Null" {% if item[8] is none %}selected{% endif %}></option>
|
<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 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 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 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 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 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 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="Opción 7" {% if item[8]=='Opción 7' %}selected{% endif %}>Opción 7</option>
|
||||||
<option value="Archivado" >Archivar</option>
|
<option value="Archivado">Archivar</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
<div class="modal fade" id="modalContactData" tabindex="-1" aria-labelledby="modalContactDataLabel" aria-hidden="true">
|
<div class="modal fade" id="modalContactData" tabindex="-1" aria-labelledby="modalContactDataLabel" aria-hidden="true">
|
||||||
@ -93,8 +95,6 @@
|
|||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- {# if flash #} -->
|
<!-- {# if flash #} -->
|
||||||
{% include 'z_comps/if_flash.html' %}
|
{% include 'z_comps/if_flash.html' %}
|
||||||
|
|
||||||
|
@ -12,13 +12,16 @@
|
|||||||
{% endblock css %}
|
{% endblock css %}
|
||||||
|
|
||||||
{% block body %}
|
{% 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">
|
<input type="text" name="title" class="form-control" placeholder="Título de la publicación" maxlength="100">
|
||||||
<div id="summernote"></div>
|
<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>
|
<button id="btn-submit" type="submit" class="btn btn-success"><i class="bi bi-file-earmark-richtext-fill"></i>
|
||||||
</form>
|
Publicar Documento</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|
||||||
|
@ -11,19 +11,22 @@
|
|||||||
{% block body %}
|
{% 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/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://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 -->
|
<!-- https://bootstrapbrain.com/component/bootstrap-5-blog-card/#code -->
|
||||||
<!-- <div class="col-md-12"> -->
|
<!-- <div class="col-md-12"> -->
|
||||||
<style>
|
<style>
|
||||||
.fade-out {
|
.fade-out {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.3s ease;
|
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 #} -->
|
<!-- {# i pagination #} -->
|
||||||
{% if total_pages > 1 %}
|
{% if total_pages > 1 %}
|
||||||
<nav aria-label="Page navigation">
|
<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">
|
<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 %}
|
{% 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">
|
<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 }}"
|
<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 %}
|
{% endif %}
|
||||||
<!-- {# f pagination #} -->
|
<!-- {# 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 %}
|
{% endblock body %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
|
@ -18,45 +18,43 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h1>Métricas del Sitio</h1>
|
||||||
|
|
||||||
|
<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" >
|
||||||
<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="p-3 bg-light rounded shadow-sm">
|
<div class="p-3 bg-light rounded shadow-sm">
|
||||||
<canvas id="dbContacts"></canvas>
|
<canvas id="dbContacts"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<div class="p-3 bg-light rounded shadow-sm">
|
||||||
<canvas id="dbEdos"></canvas>
|
<canvas id="dbEdos"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<div class="p-3 bg-light rounded shadow-sm">
|
||||||
<canvas id="dbSize"></canvas>
|
<canvas id="dbSize"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<div class="p-3 bg-light rounded shadow-sm">
|
||||||
<canvas id="dbRol"></canvas>
|
<canvas id="dbRol"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<div class="p-3 bg-light rounded shadow-sm">
|
||||||
<canvas id="dbIndustry"></canvas>
|
<canvas id="dbIndustry"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<div class="p-3 bg-light rounded shadow-sm">
|
||||||
<canvas id="dbStatus"></canvas>
|
<canvas id="dbStatus"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,16 +11,61 @@
|
|||||||
{% endblock css %}
|
{% endblock css %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<h2>Administrar Perfiles</h2>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Botón para abrir el modal -->
|
<div>
|
||||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalFormAddUsr">
|
<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
|
<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 -->
|
<!-- 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-dialog modal-dialog-centered modal-lg" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
@ -63,61 +108,30 @@
|
|||||||
{{ form.isAdmin(class_="form-select", maxlength="35", id="fe_isadmin") }}
|
{{ form.isAdmin(class_="form-select", maxlength="35", id="fe_isadmin") }}
|
||||||
</div>
|
</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="submit" class="btn btn-primary" id="btnSubmit"></button>
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
|
||||||
</form>
|
</form>
|
||||||
<!-- {# f form add user #} -->
|
<!-- {# f form add user #} -->
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="modal-footer">
|
<!-- <div class="modal-footer"> <button type="button" class="btn btn-primary">Save changes</button> </div> -->
|
||||||
<button type="button" class="btn btn-primary">Save changes</button>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</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 %}
|
{% endblock body %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
|
|
||||||
|
<!-- {# aos script #} -->
|
||||||
|
{% include 'z_comps/aos_script.html' %}
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let btnAddUsr = document.querySelector('button[data-bs-target="#modalFormAddUsr"]');
|
let btnAddUsr = document.querySelector('button[data-bs-target="#modalFormAddUsr"]');
|
||||||
@ -128,6 +142,7 @@
|
|||||||
let fe_genero = document.getElementById('fe_genero');
|
let fe_genero = document.getElementById('fe_genero');
|
||||||
let fe_email = document.getElementById('fe_email');
|
let fe_email = document.getElementById('fe_email');
|
||||||
let fe_isadmin = document.getElementById('fe_isadmin');
|
let fe_isadmin = document.getElementById('fe_isadmin');
|
||||||
|
let fe_isContactNoti = document.getElementById("isContactNoti");
|
||||||
let form_id = document.querySelector('input[name="id"]');
|
let form_id = document.querySelector('input[name="id"]');
|
||||||
let titleForm = document.getElementById("modalFormAddUsrLabel");
|
let titleForm = document.getElementById("modalFormAddUsrLabel");
|
||||||
let btnSubmit = document.getElementById("btnSubmit");
|
let btnSubmit = document.getElementById("btnSubmit");
|
||||||
@ -139,6 +154,7 @@
|
|||||||
fe_email.value = '';
|
fe_email.value = '';
|
||||||
fe_isadmin.value = '';
|
fe_isadmin.value = '';
|
||||||
form_id.value = '';
|
form_id.value = '';
|
||||||
|
fe_isContactNoti.value = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@ -164,6 +180,7 @@ async function get_user_data(btn) {
|
|||||||
let fe_genero = document.getElementById('fe_genero');
|
let fe_genero = document.getElementById('fe_genero');
|
||||||
let fe_email = document.getElementById('fe_email');
|
let fe_email = document.getElementById('fe_email');
|
||||||
let fe_isadmin = document.getElementById('fe_isadmin');
|
let fe_isadmin = document.getElementById('fe_isadmin');
|
||||||
|
let fe_isContactNoti = document.getElementById("isContactNoti");
|
||||||
let btn_submit = document.querySelector('#formEditUser button[type="submit"]');
|
let btn_submit = document.querySelector('#formEditUser button[type="submit"]');
|
||||||
let titleForm = document.getElementById("modalFormAddUsrLabel");
|
let titleForm = document.getElementById("modalFormAddUsrLabel");
|
||||||
let btnSubmit = document.getElementById("btnSubmit");
|
let btnSubmit = document.getElementById("btnSubmit");
|
||||||
@ -176,8 +193,11 @@ async function get_user_data(btn) {
|
|||||||
fe_genero.value = data[3];
|
fe_genero.value = data[3];
|
||||||
fe_email.value = data[4];
|
fe_email.value = data[4];
|
||||||
fe_isadmin.value = data[5];
|
fe_isadmin.value = data[5];
|
||||||
|
fe_isContactNoti.value = data[6];
|
||||||
form_id.value = data[0]; // Asignamos el ID recibido
|
form_id.value = data[0]; // Asignamos el ID recibido
|
||||||
|
|
||||||
|
console.log(data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -287,7 +307,34 @@ document.getElementById('tblUsers').addEventListener('click', (event) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<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>
|
</script>
|
||||||
|
|
||||||
<!-- {# if flash #} -->
|
<!-- {# if flash #} -->
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
<script>
|
<script>
|
||||||
let data = JSON.parse(`{{ messages | tojson | safe }}`)[0];
|
let dataList = JSON.parse(`{{ messages | tojson | safe }}`);
|
||||||
</script>
|
</script>
|
||||||
<script type="module" src="{{url_for('static', filename='f_contact/contact.js')}}"></script>
|
<script type="module" src="{{url_for('static', filename='f_contact/contact.js')}}"></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user