inicio del proyecto

This commit is contained in:
David Itehua Xalamihua 2024-08-20 13:45:33 -06:00
commit 5038b2433e
50 changed files with 3266 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
venv

61
db_conf.py Normal file
View File

@ -0,0 +1,61 @@
import socket
import psycopg2
import json
import os
def ip_db_backend_server():
# nombre_equipo = socket.gethostname()
# direccion_ip = socket.gethostbyname(nombre_equipo)
ip_device = os.getenv("ip_device")
# print("la ip es: ", ip_device)
# print(f'La ip del equipo es : {direccion_ip}')
# ip web server : ip db server
try:
db_backend = {
"192.168.1.75": "192.168.1.79",
"192.168.1.76": "192.168.1.80",
"192.168.1.77": "192.168.1.79",
"192.168.1.78": "192.168.1.80",
"192.168.1.83": "192.168.1.79",
}
return db_backend[f'{ip_device}']
except Exception:
return "192.168.1.80"
class DataBaseServer():
db_server_ip = ip_db_backend_server()
port = 5432
user = "postgres"
def get_data(self, query):
conn = psycopg2.connect(
host=DataBaseServer.db_server_ip,
port=DataBaseServer.port,
database="aldeas_inteligentes",
user=DataBaseServer.user,
password="Shala55951254"
)
cursor = conn.cursor()
# Utiliza el parámetro 'query' que recibiste en el método
cursor.execute(query)
result = cursor.fetchall()
cursor.close()
conn.close()
return result
def get_coordenadas(self):
conn = psycopg2.connect(
host=DataBaseServer.db_server_ip,
port=DataBaseServer.port,
database="coordenadas_mx",
user="postgres",
password="Shala55951254"
)
cursor = conn.cursor()
# Utiliza el parámetro 'query' que recibiste en el método
cursor.execute("SELECT* FROM coordenadas_mexico;")
result = cursor.fetchall()
cursor.close()
conn.close()
return result

117
main.py Normal file
View File

@ -0,0 +1,117 @@
from flask import Flask, render_template, url_for, jsonify, send_file, send_from_directory
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, InputRequired
# from flask_cors import CORS
import requests
import json
import os
from db_conf import *
app = Flask(__name__)
app.config['SECRET_KEY'] = 'SiCt2021CsIcDIX'
class LoginForm(FlaskForm):
username = StringField('username', validators=[InputRequired(
'EL código GID es requerido'), DataRequired()])
password = PasswordField('password', validators=[InputRequired(
'La contraseña es requerida'), DataRequired('campo requerido')])
@app.route('/', methods=['GET', 'POST'])
def home():
form = LoginForm()
mensaje = ""
if form.validate_on_submit():
user = form.username.data
pswd = form.password.data
sitios = DataBaseServer().get_data('SELECT * FROM sitios;')[0][1]
dirSubdirsEdos = DataBaseServer().get_data(
'SELECT * FROM dir_csict;')[0][1]
# print(dirSubdirsEdos)
for sitio in sitios:
gid = sitio['CodigoGid']
password = sitio['PasswordGid']
if pswd == password and user == gid:
centroSICT = next(
(x for x in dirSubdirsEdos if int(x['idEdo']) == int(sitio['idEdo'])), None)
if centroSICT is not None:
objeto = {
'codigoGid': gid,
'sitio': sitio['nombreTipologia'].title(),
'ai': sitio['NombreUnidad'].title(),
'edo': sitio['Estado'].title(),
'mun': sitio['Municipio'].title(),
'loc': sitio['Localidad'].title(),
'nIndicadores': len(sitio['indicadores']),
'responsableSitio': sitio['ResponsableSitio'].title(),
'PuestoResponsable': sitio['PuestoResponsable'].title(),
'indicadores': sitio['indicadores'],
'lat': sitio['ubicacion']['latitud'],
'lon': sitio['ubicacion']['longitud'],
'centroSICT': centroSICT
}
return render_template('layout_reportes.html', objeto=objeto, mensaje=mensaje)
# Si el bucle for se completa sin encontrar coincidencias, muestra el mensaje de error
mensaje = 'El código gid y/o contraseña son incorrectas, verifique sus credenciales.'
return render_template('index.html', form=form, mensaje=mensaje)
return render_template('index.html', form=form)
@app.route('/mapa')
def mapa():
return render_template('mapa.html')
@app.route("/mapa/sitios_info")
def sample():
dataRequest = DataBaseServer().get_data('SELECT * FROM sitios;')[0][1]
# with open("./database/sitios.json", mode="r", encoding="utf-8") as file:
# dataRequest = json.load(file)
lstSitios = []
for s in dataRequest:
if 'ubicacion' in s.keys():
tempObj = {
'CodigoGid': s['CodigoGid'],
'NombreUnidad': s['NombreUnidad'].title(),
'Denominacion': s['Denominacion'].title(),
'Estado': s['Estado'].title(),
'Municipio': s['Municipio'].title(),
'Localidad': s['Localidad'].title(),
'ubicacion': s['ubicacion'],
'lenguasIndigenas': s['lenguasIndigenas'].title(),
'fechaInstalacion': s['fechaInstalacion'],
'infografiaSitio': s['infografiaSitio']
}
lstSitios.append(tempObj)
return jsonify(lstSitios)
@app.route('/mapa/coordenadas')
def coordenadas():
c = DataBaseServer().get_coordenadas()[0][1]
return jsonify(c)
@app.route('/mapa/img_ai')
def img_ai():
return send_file('./static/imgs/icon_ai2.png')
@app.errorhandler(404)
def error_page(e):
return render_template('error_page.html')
if __name__ == '__main__':
app.run(port=8080, debug=True, host="0.0.0.0")

16
requirements.txt Normal file
View File

@ -0,0 +1,16 @@
blinker==1.6.2
certifi==2023.7.22
charset-normalizer==3.2.0
click==8.1.7
colorama==0.4.6
Flask==2.3.3
Flask-WTF==1.1.1
idna==3.4
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
psycopg2-binary==2.9.9
requests==2.31.0
urllib3==2.0.5
Werkzeug==2.3.7
WTForms==3.0.1

18
sict-csic.page.conf Normal file
View File

@ -0,0 +1,18 @@
<VirtualHost *:80>
ServerAdmin davidix1991@gmail.com
ServerName sict-csic.page
DocumentRoot /var/www/sict_csic
WSGIDaemonProcess app user=www-data group=www-data threads=5 python-home=/var/www/sict_csic/venv
WSGIScriptAlias / /var/www/sict_csic/sictApp.wsgi
ErrorLog /var/www/sict_csic/error_sict-csic.log
CustomLog /var/www/sict_csic/access_sict-csic.log combined
<Directory /var/www/sict_csic>
WSGIProcessGroup app
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Require all granted
</Directory>
</VirtualHost>

13
sictApp.wsgi Normal file
View File

@ -0,0 +1,13 @@
import sys
import logging
# ruta de linux al proyecto de flask
sys.path.insert(0, '/var/www/sict_csic')
# ruta de linux al ambiente virtual de flask
sys.path.insert(0, '/var/www/sict_csic/venv/lib/python3.11/site-packages')
# Set up logging
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
# Import and run the Flask app
from main import app as application

View File

@ -0,0 +1,549 @@
/* INICIO CONTENEDOR DE FORMULARIO */
#containerIndicadores {
font-size: 14.5px;
}
/* FIN CONTENEDOR DE FORMULARIO */
/* inicio sección btns */
#layoutContainer {
width: 95%;
margin-left: auto;
margin-right: auto;
margin-top: 10px;
}
#btnsreportes {
text-align: center;
margin-bottom: 2%;
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 2%;
}
#btnsreportes button>a:link {
text-decoration: none;
}
/* fin sección btns */
h4 {
text-align: center;
}
/* inicio encabezado */
/* INICIO | Fecha Doc. | Código GID | No. Indicadores */
#first_row {
display: grid;
grid-template-columns: repeat(3, auto);
align-items: center;
justify-items: center;
}
/* FIN */
/* INICIO | Aldea Inteligente | Sitio */
#second_row {
display: grid;
grid-template-columns: repeat(2, auto);
align-items: center;
justify-items: center;
}
/* FIN */
/* INICIO | Estado | Municipio | Localidad */
#third_row {
display: grid;
grid-template-columns: repeat(3, auto);
justify-items: center;
align-items: center;
}
/* FIN */
#fourth_row {
display: grid;
grid-template-columns: repeat(5, auto);
justify-items: center;
align-items: center;
}
#fourth_row>input {
text-align: center;
}
.lTrim {
justify-self: flex-end;
}
.lInicio {
justify-self: flex-end;
}
#inicioTrim {
justify-self: flex-start;
}
.lTermino {
justify-self: flex-end;
}
#finTrim {
justify-self: flex-start;
}
/* FIN ENCABEZADO */
/* INICIO SECCIÓN DE INDICADORES */
/* Dentro de .contenedor almacenan cada uno de los indicadores */
.contenedor {
margin-top: 15px;
}
/* INICIO | Indicador 1, 2, 3... */
.headerIndicador {
width: 95%;
margin-left: auto;
margin-right: auto;
border-radius: 5px;
display: grid;
align-items: center;
justify-items: center;
background-color: #691c32;
color: white;
margin-bottom: 8px;
}
.headerIndicador>h6 {
font-weight: bold;
margin: 5px;
}
/* FIN */
/* INICIO | Nombre Indicador | Definición | Meta | ODS Impactados | ( y sus variables)*/
.datosGlobalesIndicador {
width: 95%;
margin-left: auto;
margin-right: auto;
display: grid;
row-gap: 4px;
grid-template-columns: auto auto;
column-gap: 5px;
margin-bottom: 15px;
}
.datosGlobalesIndicador p {
text-align: justify;
text-justify: inter-word;
}
.lNombreIndicador,
.lDefinicion,
.lMeta,
.lODS {
justify-self: flex-end;
}
/* FIN */
/* INICIO | Dimensión a medir | Unidad de medida | Tipo de reporte | Tipo de meta */
.dimensionAmedir {
width: 95%;
margin-left: auto;
margin-right: auto;
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.cajasDAM {
display: grid;
border: 1px dotted gray;
}
.cajaItem1 {
justify-self: center;
}
.cajaItem2 {
justify-self: center;
}
/* FIN */
/* INICIO Datos para el cálculo | var a | var b */
.datosCalculo {
margin-top: 8px;
margin-bottom: 8px;
width: 95%;
margin-left: auto;
margin-right: auto;
}
.datosCalculo input {
margin-left: 5%;
text-align: center;
}
.varCalculo {
display: grid;
grid-template-columns: 15% auto;
row-gap: 3px;
}
.varCalculo input {
justify-self: flex-end;
align-self: center;
}
.varCalculo span {
padding-left: 5px;
align-self: center;
}
.titleDatosCalc {
font-size: medium;
font-weight: bold;
text-align: center;
}
/* FIN */
/* INICIO | SEMÁFORO | TABLA SEMAFORIZACIÓN */
.semaforo {
width: 95%;
margin-left: auto;
margin-right: auto;
display: grid;
grid-template-columns: auto auto;
align-items: center;
}
.circle {
border: 3px solid black;
height: 125px;
width: 125px;
border-radius: 50%;
text-align: center;
font-weight: bold;
display: grid;
align-items: center;
justify-self: flex-end;
margin-right: 30%;
}
.semaforo table {
margin-left: 30%;
}
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
th,
td {
text-align: center;
padding: 2px;
}
.thMain {
background-color: #111;
color: white;
}
/* FIN */
/* INICIO | OBSERVACIONES | INFORMACIÓN DE SOPORTE QUE SE ANEXARA */
textarea {
display: block;
width: 95%;
margin-left: auto;
margin-right: auto;
border-radius: 5px;
resize: none;
border: 1px solid black;
padding: 10px;
text-align: justify;
white-space: normal;
margin-bottom: 5px;
}
/* FIN */
/* INICIO | Firma representante AI | Firma representante CSICT */
#firmas {
width: 95%;
margin-left: auto;
margin-right: auto;
display: grid;
grid-template-columns: repeat(2, 1fr);
justify-items: center;
text-align: center;
padding-top: 15px;
padding-bottom: 15px;
}
#firmas>div {
width: 98%;
}
/* FIN */
/* leyenda proyecto aldeas inteligentes */
#leyendaProyecto {
margin-top: 25px;
text-align: center;
width: 95%;
margin-left: auto;
margin-right: auto;
}
#leyenda {
text-align: justify;
}
/* fin sección indicadores */
/* INICIO grilla de links */
.link_container {
display: grid;
grid-template-columns: repeat(2, 1fr);
justify-items: center;
}
/* FIN */
/* inicio de grid imágenes */
#myGallery {
display: grid;
grid-template-columns: repeat(9, 1fr);
width: 90%;
margin-left: auto;
margin-right: auto;
}
#myGallery img {
max-width: 100%;
}
/* fin de grid imágenes */
/* CELULAR - MOVIL */
@media screen and (min-width: 0px) and (max-width:720px) {
#btnsreportes {
grid-template-rows: repeat(3, 1fr);
row-gap: 2px;
grid-template-areas: "btnLimpiar btnLimpiar btnLimpiar" "btnCambiarGid btnCambiarGid btnCambiarGid" "btnPrint btnPrint btnPrint";
}
#btnLimpiar {
grid-area: btnLimpiar;
}
#btnCambiarGid {
grid-area: btnCambiarGid;
}
#btnPrint {
grid-area: btnPrint;
}
/* INICIO | Fecha Doc. | Código GID | No. Indicadores */
#first_row {
grid-template-columns: 1fr;
justify-items: flex-start;
row-gap: 2px;
}
/* FIN*/
/* INICIO | Aldea Inteligente| Sitio */
#second_row {
grid-template-columns: 1fr;
justify-items: flex-start;
}
/* FIN*/
/* INICIO | Estado | Municipio | Localidad */
#third_row {
grid-template-columns: 1fr;
justify-items: flex-start;
}
/* FIN */
/* INICIO | Trimestre | Inicio | Inp. Inicio | Término | Inp. Término */
#fourth_row {
grid-template-columns: repeat(3, auto);
grid-template-rows: repeat(2, 1fr);
row-gap: 3px;
grid-template-areas: "lTrim lInicio InputInicio" "lTrim lTermino InputFin";
}
.lTrim {
grid-area: lTrim;
}
.lInicio {
grid-area: lInicio;
}
#inicioTrim {
grid-area: InputInicio;
}
.lTermino {
grid-area: lTermino;
}
#finTrim {
grid-area: InputFin;
}
/* FIN */
/* INICIO | Nombre Indicador | Definición | Meta | ODS Impactadis */
.datosGlobalesIndicador {
grid-template-columns: 1fr;
}
.lNombreIndicador,
.lDefinicion,
.lMeta,
.lODS {
justify-self: flex-start;
}
/* FIN */
/* INICIO | Dimsensión a medir | Unidad de medida | Tipo de reporte | Tipo de meta */
.dimensionAmedir {
grid-template-columns: repeat(2, 1fr);
}
/* FIN */
/* INICIO Datos para el cálculo | var a | var b */
.varCalculo {
grid-template-columns: 1fr;
grid-template-areas: "varA" "inputVarA" "varB" "inputVarB";
}
.inputVarA {
grid-area: inputVarA;
}
.inputVarB {
grid-area: inputVarB;
}
.varA {
grid-area: varA;
}
.varB {
grid-area: varB;
margin-top: 8px;
}
.varCalculo input {
justify-self: flex-start;
margin-left: 0px;
padding-left: 0px;
}
/* FIN */
/* INICIO | SEMÁFORO | TABLA SEMAFORIZACIÓN */
.circle {
justify-self: center;
margin-right: 0%;
}
.semaforo table {
justify-self: center;
margin-left: 0%;
}
/* FIN */
/* INICIO | Firmas |*/
#firmas {
grid-template-columns: 1fr;
row-gap: 10px;
}
/* FIN */
/* INICIO GRID GALLERIA IMGS ODS*/
#myGallery {
grid-template-columns: repeat(6, 1fr);
}
/* FIN */
/* INICIO LINK CONTAINER */
.link_container {
grid-template-columns: 1fr;
}
/* FIN */
}
/*inicio elementos a ocultar en la impresión del documento*/
/*help: https://stackoverflow.com/questions/21485581/css-hide-placeholder-on-print*/
@media print {
/*inicio ocultar navbar, sección de botones de reportes, leyenda y el aŕea de notificaciones*/
.navbar,
#btnsreportes,
.leyenda,
#notification-area>*,
.link_container {
display: none;
}
/* fin */
::-webkit-input-placeholder {
/* WebKit browsers */
color: transparent;
}
:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: transparent;
}
::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: transparent;
}
:-ms-input-placeholder {
/* Internet Explorer 10+ */
color: transparent;
}
}
/* fin */

68
static/css/login.css Normal file
View File

@ -0,0 +1,68 @@
/* inicio btsp icons */
/*@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css");*/
/* fin btsp icons */
/* INICIO LOG IN */
.loginContainer {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, auto);
grid-template-areas: "lgid igid igid" "lpass ipass ipass" "btn btn btn";
align-items: center;
row-gap: 2.5%;
}
.lgid {
grid-area: lgid;
justify-self: flex-end;
margin-right: 2%;
}
.igid {
grid-area: igid;
}
.lpass {
grid-area: lpass;
justify-self: flex-end;
margin-right: 2%;
}
.ipass {
grid-area: ipass;
}
.btn {
grid-area: btn;
margin-top: 2.5%;
}
#forLogIn {
margin-top: 15%;
}
input {
text-align: center;
}
/* FIN DEL LOG IN */
/*CELULAR (MOVIL)*/
@media screen and (min-width: 0px) and (max-width:720px) {
.loginContainer {
grid-template-areas: "lgid lgid lgid" "igid igid igid" "lpass lpass lpass" "ipass ipass ipass" "btn btn btn";
}
.lgid,
.lpass {
justify-self: flex-start;
}
}

231
static/css/mapa.css Normal file
View File

@ -0,0 +1,231 @@
#map {
height: calc(90% - 44px);
width: 98% !important;
margin-left: auto;
margin-right: auto;
/*position: absolute !important;*/
}
.specialWidth {
width: 100px;
}
table,
thead,
tbody,
th,
td {
font-family: "Montserrat", sans-serif;
font-weight: bold;
border: #691c32 solid 1px;
border-collapse: collapse;
font-size: 12px;
}
th {
text-align: right;
/* width: 180px; */
background: #691c32;
color: white;
padding: 5px;
}
td {
background-color: white;
}
th,
td {
text-align: center;
}
.centerText {
text-align: center;
}
.headerContainer {
background-color: #691c32;
color: white;
margin-bottom: 1px;
padding: 1px;
}
#title {
text-align: center;
}
#tableSitios td {
background-color: #ffffff;
}
/* tabla sticky thead test */
#tableSitios {
table-layout: fixed;
border-collapse: collapse;
}
#tableSitios tbody {
display: block;
overflow: auto;
width: auto;
height: 400px;
}
#tableSitios thead tr {
display: block;
}
#tableSitios th,
#tableSitios td {
width: 100px;
border: 1px solid #000000;
}
/* tabla flotante */
#tableContainerSitios {
/* nuevo inicio */
/* overflow: auto; */
height: 400px;
/* nuevo fin */
position: absolute;
z-index: 1;
top: 25%;
padding-left: 5px;
/*
*/
}
#contImgDownloads {
display: grid;
grid-template-columns: repeat(3, auto);
grid-template-areas: "nsitios nsitios nsitios" "csvDescarga jsonDescarga txtDescarga";
justify-items: center;
align-items: center;
padding: 10px;
/* Estilos */
background-color: #691c32;
font-size: 20px;
color: #ffffff;
font-weight: bolder;
border-radius: 8px;
margin-bottom: 8px;
}
#nsitios {
grid-area: nsitios;
}
#jsonDescarga {
grid-area: jsonDescarga;
}
#csvDescarga {
grid-area: csvDescarga;
}
#txtDescarga {
grid-area: txtDescarga;
}
#map {
position: absolute;
z-index: -1;
width: 100%;
}
#csvDescarga,
#jsonDescarga,
#txtDescarga {
cursor: pointer;
}
/* #contenedorMapa {
display: grid;
grid-template-columns: 15% 85%;
} */
/* inicio table vertical test */
/* https://codepen.io/veekungx/pen/MWgvBxe?editors=1100 */
.vertical {
display: -ms-grid;
-ms-grid-rows: auto auto;
-ms-grid-columns: auto auto;
display: grid;
grid-template-columns: min-content min-content;
grid-template-rows: auto auto;
grid-template-areas: "caption caption" "head body";
}
.vertical thead {
grid-area: head;
display: flex;
flex-shrink: 0;
min-width: min-content;
-ms-grid-row: 2;
-ms-grid-column: 1;
}
.vertical tbody {
grid-area: body;
display: flex;
-ms-grid-row: 2;
-ms-grid-column: 2;
}
.vertical tr {
display: flex;
flex-direction: column;
min-width: min-content;
flex-shrink: 0;
}
.vertical td,
.vertical th {
display: block;
}
.vertical caption {
display: block;
-ms-grid-row: 1;
-ms-grid-column: 1;
-ms-grid-column-span: 2;
grid-area: caption;
}
/* fin table vertical test */
@media screen and (min-width: 0px) and (max-width:720px) {
#tableContainerSitios {
/* nuevo inicio */
/* overflow: auto; */
height: 400px;
/* nuevo fin */
position: relative;
top: 3px;
/*z-index: 1;*/
/*top: 25%;*/
}
#tableSitios {
margin-left: auto;
margin-right: auto;
}
#tableSitios tbody {
height: 225px;
}
#contImgDownloads {
grid-area: contImgDownloads;
}
}

181
static/css/style.css Normal file
View File

@ -0,0 +1,181 @@
body {
font-family: "Montserrat", sans-serif;
/*height: 100vh;*/
height: 100%;
width: 98%;
margin-left: auto;
margin-right: auto;
}
/* INICIO DE NAVBAR */
.navbar {
background-color: #691C32;
font-weight: bold;
padding-left: 1em;
}
.navbar li:hover {
text-underline-offset: 5px;
text-decoration: underline overline;
color: white;
}
.custom-toggler .navbar-toggler-icon {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgb(255,255,255)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
}
.custom-toggler.navbar-toggler {
border-color: rgb(255, 255, 255);
}
/* FIN DE NAVBAR */
/* INICIO HEADER LOGOS LAYOUT */
#topLogoContainer {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, auto);
column-gap: 5px;
background-color: #691c32;
padding-top: 10px;
}
.lc {
grid-row-start: 1;
grid-row-end: 3;
grid-column-start: 1;
grid-column-end: 3;
justify-self: flex-start;
margin-left: 2.5%;
}
.lai {
grid-row-start: 1;
grid-row-end: 3;
grid-column-start: 3;
grid-column-end: 5;
justify-self: flex-end;
margin-right: 2.5%;
}
#topLogoContainer>img {
max-height: 60px;
}
/* FIN HEADER LOGOS LAYOUT */
/* INICIO DE NOTIFICACIONES CSS */
#notification-area {
padding-left: 10px;
position: fixed;
top: 0px;
right: 10px;
width: 350px;
height: 0vh;
display: flex;
flex-direction: column;
/* flex-direction: row; */
/* justify-content: flex-end; */
justify-content: first baseline;
}
#notification-area .notification {
position: relative;
padding: 15px 10px;
background: #111;
color: #f5f5f5;
font-family: "Montserrat";
font-size: 20px;
font-weight: 600;
border-radius: 5px;
margin: 5px 0px;
opacity: 0;
left: 20px;
animation: showNotification 500ms ease-in-out forwards;
}
.notification {
border: 5px solid black;
}
@keyframes showNotification {
to {
opacity: 1;
left: 0px;
}
}
#notification-area .notification.warning {
background: #9f2241;
}
#notification-area .notification.success {
background: #235b4e;
}
#notification-area .notification.error {
background: orangered;
}
#notification-area .notification.info {
background: #fb8500;
color: #343a40;
}
/* FIN DE NOTIFICACIONES CSS */
/* TABLET y PC */
/*
@media screen and (min-width:0px) and (max-width:768px) {
body {
color: red;
}
/*
.lgid,
.lpass {
justify-self: flex-start;
align-self: flex-end;
}
.igid,
.ipass {
align-self: flex-start;
}
*/
/*}*/
/*CELULAR (MOVIL)*/
@media screen and (min-width: 0px) and (max-width:720px) {
.lc {
grid-row-start: 1;
grid-row-end: 2;
grid-column-start: 1;
grid-column-end: 5;
justify-self: center;
}
.lai {
grid-row-start: 2;
grid-row-end: 3;
grid-column-start: 1;
grid-column-end: 5;
justify-self: center;
}
#topLogoContainer>img {
max-width: 100%;
}
}

BIN
static/imgs/1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
static/imgs/10.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
static/imgs/11.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
static/imgs/12.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
static/imgs/13.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
static/imgs/14.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
static/imgs/15.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
static/imgs/16.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
static/imgs/17.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
static/imgs/2.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
static/imgs/3.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
static/imgs/4.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
static/imgs/5.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
static/imgs/6.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
static/imgs/7.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
static/imgs/8.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
static/imgs/9.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
static/imgs/LogoAI.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
static/imgs/ODS.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 MiB

BIN
static/imgs/export_csv.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
static/imgs/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
static/imgs/icon_ai2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
static/imgs/json_file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
static/imgs/logoSICT.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
static/imgs/mute.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

BIN
static/imgs/speaker.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1000 B

BIN
static/imgs/txt_file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

474
static/js/functions.js Normal file
View File

@ -0,0 +1,474 @@
function notify(type, message, segundos) {
let n = document.createElement("div");
let id = Math.random().toString(36).substr(2, 10);
let notificationArea = document.getElementById("notification-area");
// let imgDinamic = document.getElementById('notifyImg');
// notificationArea.style.height = '100vh';
n.setAttribute("id", id);
n.classList.add("notification", type);
n.innerText = message;
// imgDinamic.setAttribute('src', imgPath);
document.getElementById("notification-area").appendChild(n);
setTimeout(() => {
let notifications = document
.getElementById("notification-area")
.getElementsByClassName("notification");
for (let i = 0; i < notifications.length; i++) {
if (notifications[i].getAttribute("id") == id) {
// imgDinamic.remove();
notifications[i].remove();
break;
}
}
notificationArea.style.height = "0%";
}, segundos);
// {# 5000 = 5 segundos #}
}
function setDataSpan(idSpan, value) {
document.getElementById(idSpan).innerText = value;
}
function stringDay(dayNumber) {
let dayString = '';
if (dayNumber >= 1 && dayNumber <= 9) {
dayString = `0${dayNumber}`;
} else {
dayString = `${dayNumber}`;
};
return dayString;
}
function currentDate() {
let today = new Date();
let date = `${stringDay(today.getDate())}/${stringMonth(
today.getMonth() + 1
)}/${today.getFullYear()}`;
return date;
}
function fastReplace(myString, characterReplacement, newCharacter) {
`${myString}`
.replace(characterReplacement, newCharacter)
.replace(characterReplacement, newCharacter);
}
function nompropio(stringToconvert) {
let largoStr = stringToconvert.length;
let i = 0;
let resp;
let nextMayus = false;
for (; i < largoStr; i++) {
let letra = stringToconvert[i];
if (i == 0) {
resp = letra.toUpperCase();
} else {
if (nextMayus == false && letra == " ") {
resp += letra;
nextMayus = true;
} else if (nextMayus == true) {
resp += letra.toUpperCase();
nextMayus = false;
} else {
resp += letra.toLowerCase();
}
}
}
return resp;
}
function validarContentInput(idInput, colorAlerta, colorNoAlerta) {
let inputToValidate = document.getElementById(idInput);
if (inputToValidate.disabled == false) {
// inputToValidate.style.backgroundColor = colorAlerta;
inputToValidate.style.border = `3px solid ${colorAlerta}`;
}
inputToValidate.addEventListener("change", () => {
if (inputToValidate.value == "") {
inputToValidate.style.border = `3px solid ${colorAlerta}`;
} else {
inputToValidate.style.border = `2px solid ${colorNoAlerta}`;
}
});
}
function roundNumber(numfloat, tipoMedida) {
let respuesta;
if (tipoMedida == "Porcentaje.") {
respuesta = numfloat * 100;
} else {
respuesta = numfloat;
}
return parseFloat(respuesta.toFixed(2));
}
function stringMonth(mesNumero) {
let m = "";
if (mesNumero <= 9) {
m = `0${mesNumero}`
} else {
m = mesNumero
}
/*
switch (mesNumero) {
case 1:
m = "enero";
break;
case 2:
m = "febrero";
break;
case 3:
m = "marzo";
break;
case 4:
m = "abril";
break;
case 5:
m = "mayo";
break;
case 6:
m = "junio";
break;
case 7:
m = "julio";
break;
case 8:
m = "agosto";
break;
case 9:
m = "septiembre";
break;
case 10:
m = "octubre";
break;
case 11:
m = "noviembre";
break;
case 12:
m = "diciembre";
break;
}
*/
return m;
}
//aquí me quede
function isFrecuenciaAbsoluta(idTagUnidadMedida, idCirculo, idTable, idTipoMeta) {
let circulo = document.getElementById(idCirculo);
let tabla = document.getElementById(idTable);
let idTag = document.getElementById(idTagUnidadMedida);
let meta = document.getElementById(idTipoMeta);
//console.log(idTag.firstChild.data);
if (idTag.innerText != 'Porcentaje.') {
circulo.remove();
tabla.remove();
}
if (meta.innerText != 'Trimestral.') {
circulo.remove();
tabla.remove();
}
}
function camposObligatorios() {
let mensaje;
let req = 0;
let inputTags = document.getElementsByTagName("input");
let fieldSoporte = document.getElementById("infosoporte");
for (let i = 0; i < inputTags.length; i++) {
if (inputTags[i].value == '' && inputTags[i].disabled == false && inputTags[i].getAttribute('type') != 'file') {
req += 1;
}
}
if (fieldSoporte.value.length == 0) {
req += 1;
}
if (req > 0) {
if (req == 1) {
mensaje = "El campo con borde naranja es obligatorio";
} else {
mensaje = `Los ${req} campos marcados con borde naranja son obligatorios`;
}
}
return mensaje
}
function limpiarFormulario(colorAlerta) {
let ArrayInputs = document.getElementsByTagName("input");
let ArrayTxtarea = document.getElementsByTagName("textarea");
let i = 0;
while (i < ArrayInputs.length) {
if (ArrayInputs[i].disabled == false) {
ArrayInputs[i].value = "";
document.getElementById(
ArrayInputs[i].id
).style.border = `3px solid ${colorAlerta}`;
}
i++;
}
ArrayTxtarea[0].value = "";
ArrayTxtarea[1].value = "";
ArrayTxtarea[1].style.border = `3px solid ${colorAlerta}`;
}
function lastDayOfMonth(myYear, myMonth) {
var month = myMonth;
var d = new Date(myYear, myMonth, 0);
return d.getDate();
}
function numFrmt(num) {
let r;
if (num < 10) {
r = `0${num}`;
} else {
r = `${num}`;
}
return r;
}
function validarContentTextArea(idTxtArea, colorAlerta, colorNoAlerta) {
let txtArea = document.getElementById(idTxtArea);
txtArea.style.border = `3px solid ${colorAlerta}`;
txtArea.addEventListener('change', () => {
if (txtArea.value == '') {
txtArea.style.border = `3px solid ${colorAlerta}`;
// inputToValidate.style.border = `2px solid ${colorNoAlerta}`;
} else {
txtArea.style.border = `2px solid ${colorNoAlerta}`;
}
});
}
function valorSemaforo(
idVarA,
idVarB,
semaforoToChange,
idSemaforoForm,
idAmarilloLi,
idAmarilloLs,
idSigno,
idFilaRojo,
idFilaAmarillo,
idFilaVerde
) {
/*
idVarA: contenedor de la variable a (input),
idVarB: contenedor de la variable b (input),
semaforoToChange: es en donde se pintara el porcentaje (span),
idSemaforoForm: es el id del semáforo que se pintara
idAmarilloLi: es el id del amarillo límite inferior (span)
idAmarilloLs: es el id del amarillo límite superior (span)
idSigno: es el id donde tiene el signo de porcentaje, pendiente de meterle la lójica
*/
let varA = document.getElementById(idVarA);
let varB = document.getElementById(idVarB);
let circulo = document.getElementById(idSemaforoForm);
let amarilloLi = document.getElementById(idAmarilloLi);
let amarilloLs = document.getElementById(idAmarilloLs);
let signo = document.getElementById(idSigno);
let redColor = "#9b2226";
let yellowColor = "#fca311";
let greenColor = "#008000";
let whiteColor = "#ffffff";
let listObj = [varA, varB];
listObj.forEach((ele) => {
ele.addEventListener("change", () => {
let parseVarA = parseFloat(varA.value);
let parseVarB = parseFloat(varB.value);
let valPorcentual;
let parseAmarilloLi = parseFloat(amarilloLi.textContent);
let parseAmarilloLs = parseFloat(amarilloLs.textContent);
let semaforo = document.getElementById(semaforoToChange);
if (varA.value != "" && varB.value != "") {
valPorcentual = ((parseVarA / parseVarB) * 100).toFixed(2);
let r = (semaforo.textContent = valPorcentual);
if (valPorcentual < parseAmarilloLi) {
circulo.style.background = redColor;
tableRowStyleSemaforo(idFilaRojo, redColor, whiteColor);
// quitar estilos a las otras filas
tableRowStyleSemaforo(idFilaAmarillo, whiteColor, "black");
tableRowStyleSemaforo(idFilaVerde, whiteColor, "black");
} else if (
valPorcentual > parseAmarilloLs &&
valPorcentual != "Infinity"
) {
circulo.style.background = greenColor;
tableRowStyleSemaforo(idFilaVerde, greenColor, whiteColor);
// quitar estilos a las otras filas
tableRowStyleSemaforo(idFilaRojo, whiteColor, "black");
tableRowStyleSemaforo(idFilaAmarillo, whiteColor, "black");
} else if (
valPorcentual >= parseAmarilloLi &&
valPorcentual <= parseAmarilloLs
) {
circulo.style.background = yellowColor;
tableRowStyleSemaforo(idFilaAmarillo, yellowColor, "black");
// quitar estilos a las otras filas
tableRowStyleSemaforo(idFilaRojo, whiteColor, "black");
tableRowStyleSemaforo(idFilaVerde, whiteColor, "black");
} else if (valPorcentual == "NaN") {
circulo.style.background = whiteColor;
signo.textContent = "";
tableRowStyleSemaforo(idFilaRojo, whiteColor, "black");
tableRowStyleSemaforo(idFilaAmarillo, whiteColor, "black");
tableRowStyleSemaforo(idFilaVerde, whiteColor, "black");
//console.log("not a number");
} else {
circulo.style.background = whiteColor;
semaforo.textContent = "";
tableRowStyleSemaforo(idFilaRojo, whiteColor, "black");
tableRowStyleSemaforo(idFilaAmarillo, whiteColor, "black");
tableRowStyleSemaforo(idFilaVerde, whiteColor, "black");
}
semaforo.style.color = whiteColor;
signo.textContent = "%";
signo.style.color = whiteColor;
} else {
semaforo.textContent = "";
circulo.style.background = whiteColor;
}
});
});
}
function tableRowStyleSemaforo(idRow, bgColor, fgColor) {
let fila = document.getElementById(idRow);
fila.style.background = bgColor;
fila.style.color = fgColor;
}
function generalStylesSignField(idDivTagFirma, idImgTag, idInputFiletag) {
// idDivTagFirma div contenedor del input y el img (tags)
let divAffect = document.getElementById(idDivTagFirma);
// función para afectar los estilos contenedores de la imagen
let imgAffect = document.getElementById(idImgTag);
// afectar el input type file
let inputTag = document.getElementById(idInputFiletag);
divAffect.style.display = "table-cell";
divAffect.style.height = "150px";
divAffect.style.width = "1%";
divAffect.style.verticalAlign = "middle";
divAffect.style.textAlign = "center";
divAffect.style.color = "#000000";
divAffect.style.backgroundColor = "#FFFFFF";
divAffect.style.border = "solid 2px #000000";
divAffect.style.borderRadius = "10px";
divAffect.style.padding = "10px";
imgAffect.style.display = "None";
imgAffect.style.width = "100%";
imgAffect.style.height = "125px";
imgAffect.style.objectFit = "contain";
inputTag.style.display = "none";
}
function uploadPictureToWeb(idDivSignContainer, idInputFile, idImgContainer) {
let divTagC = document.getElementById(idDivSignContainer);
let inputTag = document.getElementById(idInputFile);
let spanTag = divTagC.querySelector("span");
divTagC.addEventListener("dblclick", () => {
inputTag.click();
if (spanTag) {
spanTag.innerText = "";
}
$(idInputFile).onChange(function() {
runUpload(this.files[0], idImgContainer);
});
});
}
function runUpload(file, idImgTag) {
// https://www.photoroom.com/quitar-fondo-imagen/
let imgcont = document.getElementById(idImgTag);
let span = imgcont.parentElement.querySelector("span");
try {
if (file == undefined) {
// console.log("no se ha elegido ninguna imagen de firma");
imgcont.style.display = "none";
imgcont.setAttribute("src", "");
span.textContent = "Dar docle click para cargar imagen firma";
}
if (
file.type === "image/png" ||
file.type === "image/jpg" ||
file.type === "image/jpeg"
) {
let reader = new FileReader(),
image = new Image();
reader.readAsDataURL(file);
reader.onload = function(_file) {
if (_file.target.result.length > 0) {
$(idImgTag).el.src = _file.target.result;
$(idImgTag).el.style.display = "inline";
span.textContent = "";
}
}; // END reader.onload()
}
} catch (error) {
imgcont.style.display = "none";
imgcont.setAttribute("src", "");
span.textContent = "Doble click para cargar firma digitalizada";
}
}
function deshabilitarInput(idInputToDisabled) {
let elemento = document.getElementById(idInputToDisabled);
elemento.disabled = true;
elemento.placeholder = 'N/A';
elemento.style.background = '#ced4da';
elemento.style.border = `3px solid #000`;
}
export {
notify,
setDataSpan,
currentDate,
nompropio,
fastReplace,
validarContentInput,
roundNumber,
limpiarFormulario,
lastDayOfMonth,
numFrmt,
valorSemaforo,
tableRowStyleSemaforo,
generalStylesSignField,
uploadPictureToWeb,
runUpload,
isFrecuenciaAbsoluta,
validarContentTextArea,
deshabilitarInput,
camposObligatorios
};

17
static/js/javascript.js Normal file
View File

@ -0,0 +1,17 @@
import { notify } from "./functions.js";
(() => {
let btnLogIn = document.getElementById("btnInicioSesion");
btnLogIn.addEventListener("click", (e) => {
mensaje = "";
let id = document.getElementById("username");
let pswd = document.getElementById("password");
// alert(mensaje);
if (id.value != "" && pswd.value != "" && mensaje != "") {
e.preventDefault();
notify("warning", mensaje, 5000);
}
});
})();

306
static/js/layoutreporte.js Normal file
View File

@ -0,0 +1,306 @@
import {
validarContentInput,
limpiarFormulario,
notify,
lastDayOfMonth,
isFrecuenciaAbsoluta,
numFrmt,
valorSemaforo,
generalStylesSignField,
uploadPictureToWeb,
validarContentTextArea,
deshabilitarInput,
camposObligatorios,
currentDate
} from "./functions.js";
const colorSiVacio = "#f48c06";
const colorNoVacio = "#03071e";
const idInicioTrim = "inicioTrim";
const idFinTrim = "finTrim";
const inicioX = document.getElementById("inicioTrim");
const finX = document.getElementById("finTrim");
(() => {
validarContentInput(idInicioTrim, colorSiVacio, colorNoVacio);
validarContentInput(idFinTrim, colorSiVacio, colorNoVacio);
})();
// validación de textarea
(() => {
validarContentTextArea('infosoporte', colorSiVacio, colorNoVacio);
})();
let inputs = document.getElementsByTagName("input");
for (let i of inputs) {
validarContentInput(i.id, colorSiVacio, colorNoVacio);
}
let validarInicioDate = (() => {
inicioX.addEventListener("change", () => {
let dateIni = String(inicioX.value).split("-");
let monthIni = parseInt(dateIni[1]);
let yearIni = parseInt(dateIni[0]);
if (monthIni == 1 || monthIni == 4 || monthIni == 7 || monthIni == 10) {
let frmDate;
switch (monthIni) {
case 1:
frmDate = `${yearIni}-03-${lastDayOfMonth(yearIni, 3)}`;
break;
case 4:
frmDate = `${yearIni}-06-${lastDayOfMonth(yearIni, 6)}`;
break;
case 7:
frmDate = `${yearIni}-09-${lastDayOfMonth(yearIni, 9)}`;
break;
case 10:
frmDate = `${yearIni}-12-${lastDayOfMonth(yearIni, 12)}`;
break;
}
inicioX.value = `${yearIni}-${numFrmt(monthIni)}-01`;
finX.value = frmDate;
finX.style.border = `2px solid ${colorNoVacio}`;
} else {
notify(
"warning",
"Los trimestres deben iniciar en:" +
"\n" +
"1) enero" +
"\n" +
"4) abril" +
"\n" +
"7) julio" +
"\n" +
"10) octubre",
5000
);
inicioX.value = "";
finX.value = "";
finX.style.border = `3px solid ${colorSiVacio}`;
}
});
})();
let validarFinDate = (() => {
finX.addEventListener("change", () => {
let dateFin = String(finX.value).split("-");
let monthfin = parseInt(dateFin[1]);
let yearFin = parseInt(dateFin[0]);
if (monthfin == 3 || monthfin == 6 || monthfin == 9 || monthfin == 12) {
let frmDate;
switch (monthfin) {
case 3:
frmDate = `${yearFin}-01-01`;
break;
case 6:
frmDate = `${yearFin}-04-01`;
break;
case 9:
frmDate = `${yearFin}-07-01`;
break;
case 12:
frmDate = `${yearFin}-10-01`;
break;
}
inicioX.value = frmDate;
finX.value = `${yearFin}-${numFrmt(monthfin)}-${lastDayOfMonth(
yearFin,
monthfin
)}`;
inicioX.style.border = `2px solid ${colorNoVacio}`;
} else {
notify(
"warning",
"Los trimestres deben finalizar en:" +
"\n" +
"3) marzo" +
"\n" +
"6) junio" +
"\n" +
"9) septiembre" +
"\n" +
"12) diciembre",
5000
);
inicioX.value = "";
finX.value = "";
inicioX.style.border = `3px solid ${colorSiVacio}`;
}
});
})();
let btnLimpiarFormulario = (() => {
let btnLimpiar = document.getElementById("btnLimpiar");
btnLimpiar.addEventListener("click", () => {
limpiarFormulario(colorSiVacio);
});
})();
for (let o of inputs) {
// cambiar a ternaria
if (o.id.includes("varA_")) {
let n = Number(o.id.replace("varA_", ""));
let varAinput = `varA_${n}`;
let varBinput = `varB_${n}`;
let semaforo = `semaforo_${n}`;
let idCirculo = `circle_${n}`;
let amarillo_li = `amarillo_li_${n}`;
let amarillo_ls = `amarillo_ls_${n}`;
let signo = `signo_${n}`;
let idUnidadDeMedida = `unidadMedida_${n}`;
let idTable = `table_${n}`;
let idMeta = `index_meta_${n}`;
let rowRojo = `critico_${n}`;
let rowAmarillo = `riesgo_${n}`;
let rowVerde = `aceptable_${n}`;
valorSemaforo(
varAinput,
varBinput,
semaforo,
idCirculo,
amarillo_li,
amarillo_ls,
signo,
rowRojo,
rowAmarillo,
rowVerde
);
}
}
let btnImprimir = (() => {
let btnPrint = document.getElementById('btnPrint');
btnPrint.addEventListener('click', () => {
let r = 0;
let inputTags = document.getElementsByTagName("input");
let fieldSoporte = document.getElementById("infosoporte");
for (let i = 0; i < inputTags.length; i++) {
if (inputTags[i].value == '' && inputTags[i].disabled == false && inputTags[i].getAttribute('type') != 'file') {
r += 1;
}
}
if (fieldSoporte.value.length == 0) {
r += 1;
}
if (r > 0) {
let mensaje;
if (r == 1) {
mensaje = "El campo con borde naranja es obligatorio";
} else {
mensaje = `Los ${r} campos marcados con borde naranja son obligatorios`;
}
notify('warning', mensaje, 5000);
} else {
window.print();
}
})
})();
(() => {
let crDate = document.getElementById("currentDate");
crDate.innerText = currentDate();
})();
(function() {
// http://stackoverflow.com/questions/4083351/what-does-jquery-fn-mean
var $ = function(elem) {
if (!(this instanceof $)) {
return new $(elem);
}
this.el = document.getElementById(elem);
};
window.$ = $;
$.prototype = {
onChange: function(callback) {
this.el.addEventListener("change", callback);
return this;
},
};
})();
(() => {
generalStylesSignField(
"squareSignFielRepresentante",
"imgSignRepresentante",
"fileUploadRepresentante"
);
generalStylesSignField(
"squareSignFielSubCentroSCT",
"imgSignSubCentroSCT",
"fileUploadSubCentroSCT"
);
// generalStylesSignField('userActionsDos', 'imgPrimeDos', 'fileUploadDos');
uploadPictureToWeb(
"squareSignFielRepresentante",
"fileUploadRepresentante",
"imgSignRepresentante"
);
uploadPictureToWeb(
"squareSignFielSubCentroSCT",
"fileUploadSubCentroSCT",
"imgSignSubCentroSCT"
);
// uploadPictureToWeb('userActions', 'fileUpload', 'imgPrime');
// uploadPictureToWeb('userActionsDos', 'fileUploadDos', 'imgPrimeDos');
})();
// bloqueo de los campos sin variable de cálculo
(() => {
if (parseInt(nIndicadores) > 0) {
let nI = parseInt(nIndicadores);
let e = 1;
for (; e <= nI; e++) {
let varA = document.getElementById(`varA${e}Strong`);
let inputA = `varA_${e}`;
let varB = document.getElementById(`varB${e}Strong`);
let inputB = `varB_${e}`;
let idUnidadDeMedida = `unidadMedida_${e}`;
let idCirculo = `circle_${e}`
let idTable = `table_${e}`;
let idMeta = `index_meta_${e}`;
`${varA.textContent}`.replace('\n', '').trim().length <= 1 ? deshabilitarInput(inputA) : varA;
`${varB.textContent}`.replace('\n', '').trim().length <= 1 ? deshabilitarInput(inputB) : varB;
isFrecuenciaAbsoluta(idUnidadDeMedida, idCirculo, idTable, idMeta);
validarContentInput(inputA, colorSiVacio, colorNoVacio)
validarContentInput(inputB, colorSiVacio, colorNoVacio)
}
notify("success", `${camposObligatorios()}`, 7000)
} else {
notify("warning", "No se han cargado los indicadores de la Aldea Inteligente.", 7000)
}
})()
// idea de descargar la página web:
// https://www.youtube.com/watch?v=C8jxInLM9nM&ab_channel=PrettyPrinted
// grillado de galeria
// https://codepen.io/eHtmlu/pen/BaodGVp

577
static/js/mapa.js Normal file
View File

@ -0,0 +1,577 @@
import { nompropio } from "./functions.js";
// punto central de donde se colocará el mapa, latitud, longitud y zoom
var map = L.map("map").setView([24.026078546314853, -102.65858297569135], 5);
let tableSitios = document.getElementById("dataSitiosInstalados");
let verde = "#10312B";
let morado = "#691c32";
let blanco = "#ffffff";
let negro = "#000000";
let url_icon_ai = window.location.origin + "/mapa/img_ai"
let sitios = window.location.origin + "/mapa/sitios_info"
let coordenadas = window.location.origin + "/mapa/coordenadas"
let sitioIcon = L.icon({
iconUrl: url_icon_ai,
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34]
});
// JSON estados, de inicio los establezco en cero (0) y se actualizara dependiendo el los registros en el archivo sitios.json
let estados = [{
IDEDO: 1,
ESTADO: "Aguascalientes",
ACRONIMO: "Ags.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 2,
ESTADO: "Baja California",
ACRONIMO: "B.C.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 3,
ESTADO: "Baja California Sur",
ACRONIMO: "B.C.S.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 4,
ESTADO: "Campeche",
ACRONIMO: "Camp.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 5,
ESTADO: "Coahuila",
ACRONIMO: "Coah.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 6,
ESTADO: "Colima",
ACRONIMO: "Col.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 7,
ESTADO: "Chiapas",
ACRONIMO: "Chis.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 8,
ESTADO: "Chihuahua",
ACRONIMO: "Chih.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 9,
ESTADO: "Ciudad de México",
ACRONIMO: "CDMX",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 10,
ESTADO: "Durango",
ACRONIMO: "Dgo.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 11,
ESTADO: "Guanajuato",
ACRONIMO: "Gto.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 12,
ESTADO: "Guerrero",
ACRONIMO: "Gro.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 13,
ESTADO: "Hidalgo",
ACRONIMO: "Hgo.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 14,
ESTADO: "Jalisco",
ACRONIMO: "Jal.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 15,
ESTADO: "México",
ACRONIMO: "Méx.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 16,
ESTADO: "Michoacán",
ACRONIMO: "Mich.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 17,
ESTADO: "Morelos",
ACRONIMO: "Mor.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 18,
ESTADO: "Nayarit",
ACRONIMO: "Nay.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 19,
ESTADO: "Nuevo León",
ACRONIMO: "N.L.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 20,
ESTADO: "Oaxaca",
ACRONIMO: "Oax.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 21,
ESTADO: "Puebla",
ACRONIMO: "Pue.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 22,
ESTADO: "Querétaro",
ACRONIMO: "Qro.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 23,
ESTADO: "Quintana Roo",
ACRONIMO: "Q.R.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 24,
ESTADO: "San Luis Potosí",
ACRONIMO: "S.L.P.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 25,
ESTADO: "Sinaloa",
ACRONIMO: "Sin.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 26,
ESTADO: "Sonora",
ACRONIMO: "Son.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 27,
ESTADO: "Tabasco",
ACRONIMO: "Tab.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 28,
ESTADO: "Tamaulipas",
ACRONIMO: "Tams.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 29,
ESTADO: "Tlaxcala",
ACRONIMO: "Tlax.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 30,
ESTADO: "Veracruz",
ACRONIMO: "Ver.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 31,
ESTADO: "Yucatán",
ACRONIMO: "Yuc.",
SITIOS_INSTALADOS: 0,
},
{
IDEDO: 32,
ESTADO: "Zacatecas",
ACRONIMO: "Zac.",
SITIOS_INSTALADOS: 0,
},
];
// función que al pasar el cursor encima de un th o tr de la tabla este se refleje en el mapa
function thMapStyle(idThName) {
let edoTh = document.getElementById(idThName);
let strTh = String(idThName).substring(3);
if (idThName) {
let th = `th_${strTh}`;
let td = `td_${strTh}`;
let thAffect = document.getElementById(th);
let tdAffect = document.getElementById(td);
edoTh.addEventListener("mouseenter", () => {
thAffect.style.background = verde;
tdAffect.style.background = verde;
tdAffect.style.color = blanco;
let estado = document.getElementById(strTh);
estado.style.fill = "#f3722c"
estado.style.fillOpacity = '0.8';
});
edoTh.addEventListener("mouseleave", () => {
thAffect.style.background = "#691c32";
tdAffect.style.background = blanco;
tdAffect.style.color = negro;
let estado = document.getElementById(strTh);
estado.style.fill = "#3388ff";
estado.style.fillOpacity = '0.2'
});
}
}
function sitioData(objeto) {
let lenguasIndigenas = String(objeto["lenguasIndigenas"]).length == 0 ? "N/D" : nompropio(objeto["lenguasIndigenas"]);
let denominacion = String(objeto["Denominacion"]).length == 0 ? "N/D" : nompropio(objeto["Denominacion"]);
let marker = L.marker(
[objeto["ubicacion"]["latitud"], objeto["ubicacion"]["longitud"]], { title: "Más información", icon: sitioIcon }
).addTo(map).bindPopup(`<table id="${objeto["Estado"]}">
<tr>
<th class="specialWidth">
Nombre Unidad:
</th>
<td>
${nompropio(objeto["NombreUnidad"])}
</td>
</tr>
<tr>
<th class="specialWidth">
GID:
</th>
<td>
${objeto["CodigoGid"]}
</td>
</tr>
<tr>
<th class="specialWidth">
Denominación:
</th>
<td>
${denominacion}
</td>
</tr>
<tr>
<th class="specialWidth">
Estado:
</th>
<td>
${nompropio(objeto["Estado"])}
</td>
</tr>
<tr>
<th class="specialWidth">
Municipio:
</th>
<td>
${nompropio(objeto["Municipio"])}
</td>
</tr>
<tr>
<th class="specialWidth">
Localidad:
</th>
<td>
${nompropio(objeto["Localidad"])}
</td>
</tr>
<tr>
<th class="specialWidth">
Localización:
</th>
<td>
${objeto["ubicacion"]["latitud"]} ${
objeto["ubicacion"]["longitud"]
}
</td>
</tr>
<tr>
<th class="specialWidth">
Lengua indígena:
</th>
<td>
${lenguasIndigenas}
</td>
</tr>
<tr>
<th class="specialWidth">
Fecha instalación:
</th>
<td>
${objeto["fechaInstalacion"]}
</td>
</tr>
<tr>
<th class="specialWidth">
Página sitio:
</th>
<td>
<a href="${objeto["infografiaSitio"]}" target="_blank">
Infografía Sitio
</a>
</td>
</tr>
</table>`);
}
// tabla conteo de sitios por estado
(() => {
// petición de sitios y actualización de json estados y sitios instalados
fetch(sitios)
.then((data) => data.json())
.then((resData) => {
resData.forEach((element) => {
if (element["ubicacion"]) {
sitioData(element);
// actualizar los sitios instalados
estados.forEach((ele) => {
if (nompropio(ele["ESTADO"]) == nompropio(element["Estado"])) {
ele["SITIOS_INSTALADOS"] += 1;
}
});
}
});
let t = 0;
estados.forEach((ele) => {
if (ele["SITIOS_INSTALADOS"] > 0) {
let idEdoTh = `th_${ele["ESTADO"]}`;
let idEdoTd = `td_${ele["ESTADO"]}`;
t += ele["SITIOS_INSTALADOS"];
tableSitios.insertAdjacentHTML(
"beforeend",
`<tr id="tr_${ele["ESTADO"]}">
<th class="centerText" id="th_${ele["ESTADO"]}">
${nompropio(ele["ESTADO"])}
</th>
<td id="td_${ele["ESTADO"]}" >
${ele["SITIOS_INSTALADOS"]}
</td>
</tr>`
);
thMapStyle(idEdoTh);
thMapStyle(idEdoTd);
}
});
let btnDownload = document.getElementById("nsitios");
btnDownload.innerText = `${t} sitios instalados`;
});
})();
// importar las delimitaciones estatales de toda la república mexica
(() => {
// estado JSON 2
fetch(coordenadas)
.then((data) => data.json())
.then((resJson) => {
// let geoJsonLayer = L.geoJson(resJson).addTo(map);
resJson.forEach((ele) => {
let idDbEdo = ele["properties"]["sta_name"];
let idEdo = String(idDbEdo);
let geoJsonLayer = L.geoJson(ele["geometry"]).addTo(map);
// console.log(ele.properties.geo_point_2d)
geoJsonLayer.eachLayer(function(layer) {
// layer._path.id = ele['properties']['nombre_igg'];
layer._path.id = idEdo;
// console.log(layer._path.attributes)
layer.on('mouseover', function() {
// console.log(layer._path.attributes.id.nodeValue)
this.setStyle({
'fillColor': '#f3722c',
'fillOpacity': '0.3',
// "color": "red"
})
});
layer.on('mouseout', function() {
this.setStyle({
'fillColor': '#3388ff',
'fillOpacity': '0.2'
})
});
layer.on('click', function() {
// console.log(layer._path.attributes);
let texto = `<b>Estado: ${layer._path.attributes.id.nodeValue}</b>`;
layer.bindPopup(texto).openPopup();
// .setLatLng(latlng);
});
});
});
});
})();
L.tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>',
maxZoom: 18,
}).addTo(map);
// btn de descarga base de datos
(() => {
let btnDescarga = document.getElementById("csvDescarga");
btnDescarga.addEventListener("click", () => {
let lstSitios = [];
let columns =
"Código GID|Nombre Unidad|Denominación|Lengua indígena|Estado|Municipio|Localidad|Fecha instalación|Latitud|Longitud\n";
fetch(sitios)
.then((data) => data.json())
.then((data) => {
data.forEach((ele) => {
if (ele["ubicacion"]) {
lstSitios.push([
ele["CodigoGid"],
ele["NombreUnidad"],
nompropio(ele["Denominacion"]),
nompropio(ele["lenguasIndigenas"]),
nompropio(ele["Estado"]),
nompropio(ele["Municipio"]),
nompropio(ele["Localidad"]),
ele["fechaInstalacion"],
ele["ubicacion"]["latitud"],
ele["ubicacion"]["longitud"],
]);
}
});
lstSitios.forEach((row) => {
columns += row.join("|");
columns += "\n";
});
var hiddenElement = document.createElement("a");
hiddenElement.href =
"data:text/csv;charset=utf-8," + encodeURI(columns);
hiddenElement.download = "sitios_instalados.csv";
hiddenElement.click();
});
});
})();
// descargar json
function downloadObjectAsJson(exportObj, exportName) {
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj));
var downloadAnchorNode = document.createElement('a');
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute("download", exportName + ".json");
document.body.appendChild(downloadAnchorNode); // required for firefox
downloadAnchorNode.click();
downloadAnchorNode.remove();
}
(() => {
let lstSitios = [];
let jsonDownload = document.getElementById("jsonDescarga");
jsonDownload.addEventListener('click', () => {
fetch(sitios).then(data => data.json()).then(data => {
data.forEach(ele => {
lstSitios.push(ele)
})
downloadObjectAsJson(lstSitios, "sitios_instalados");
})
})
})();
// descargar txt
(() => {
let btnDescarga = document.getElementById("txtDescarga");
btnDescarga.addEventListener("click", () => {
let lstSitios = [];
let columns =
"Código GID|Nombre Unidad|Denominación|Lengua indígena|Estado|Municipio|Localidad|Fecha instalación|Latitud|Longitud\n";
fetch(sitios)
.then((data) => data.json())
.then((data) => {
data.forEach((ele) => {
if (ele["ubicacion"]) {
lstSitios.push([
ele["CodigoGid"],
ele["NombreUnidad"],
nompropio(ele["Denominacion"]),
nompropio(ele["lenguasIndigenas"]),
nompropio(ele["Estado"]),
nompropio(ele["Municipio"]),
nompropio(ele["Localidad"]),
ele["fechaInstalacion"],
ele["ubicacion"]["latitud"],
ele["ubicacion"]["longitud"],
]);
}
});
lstSitios.forEach((row) => {
columns += row.join("|");
columns += "\n";
});
var hiddenElement = document.createElement("a");
hiddenElement.href =
"data:text/txt;charset=utf-8," + encodeURI(columns);
hiddenElement.download = "sitios_instalados.txt";
hiddenElement.click();
});
});
})();
// var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(storageObj));
// var dlAnchorElem = document.getElementById('downloadAnchorElem');
// dlAnchorElem.setAttribute("href", dataStr );
// dlAnchorElem.setAttribute("download", "scene.json");
// dlAnchorElem.click();
// verificar info
// js download array as csv file
// https://www.javatpoint.com/javascript-create-and-download-csv-file

128
templates/base.html Normal file
View File

@ -0,0 +1,128 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- David Itehua Xalamihua {DIX} -->
<!-- Server No. 1 -->
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description"
content="Proyecto Aldeas Inteligentes, Bienestar Sostenible, sitio temporal mapa de sitios instalados. (preliminar hecho por David Itehua Xalamihua)">
<!-- {# inicio ícono #} -->
<link rel="icon" href="{{url_for('static', filename='imgs/favicon.ico')}}" />
<!-- {# fin ícono #} -->
<!--{#inicio de titulo dinamico#]-->
<title>{% block title %}{% endblock %}</title>
<!--{#fin de titulo dinamico#]-->
<!-- {# inicio bootstrap #} -->
<!--{#<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" />#}-->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
crossorigin="anonymous"></script>
<!-- {# fin de bootstrap #} -->
<!--{# inicio boostrap icons #}-->
<!--{# https://icons.getbootstrap.com/ #}-->
<!--{# <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css"> #}-->
<!--{# fin bootstrap icons #}-->
<!-- {# inicio fuente Monserrat #} -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Montserrat&display=swap" rel="stylesheet" />
<!--{#inicio para añadir mas archivos css#}-->
{% block cssfiles%}{% endblock %}
<!--{# fin para añadir más archivos de css #}-->
<!-- {# fin fuente Monserrat #} -->
<!-- {# inicio mi hoja de estilos #} -->
<link rel="stylesheet" href="{{url_for('static', filename='css/style.css')}}" />
<!-- {# fin mi hoja de estilos #} -->
<!-- {# inicio otros recursos #} -->
{% block recursos %} {% endblock %}
<!-- {# fin otros recursos #} -->
</head>
<body>
<div id="topLogoContainer">
<img class="lc" src="{{url_for('static', filename='imgs/logoSICT.webp')}}" alt="logo gobierno de México" />
<img class="lai" src="{{url_for('static', filename='imgs/LogoAI.webp')}}" alt="logo Aldeas Inteligentes" />
</div>
<!--{# inicio para validar el navbar #}-->
<nav class="navbar navbar-expand-lg navbar-custom">
<!-- {# <a class="navbar-brand" href="#">Navbar</a> #} -->
<button class="navbar-toggler ml-auto custom-toggler" type="button" data-toggle="collapse"
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link link-light" href="{{url_for('home')}}">
Reportes
<!--{# <span class="sr-only">(current)</span> #}-->
</a>
</li>
<li class="nav-item">
<a class="nav-link link-light" href="{{url_for('mapa')}}">Mapa</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle link-light" href="#" id="navbarDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Más información
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="https://coberturauniversal.gob.mx/" target="_blank">Portal de
Cobertura Universal</a>
<!--{# <a class="dropdown-item" href="#" target="_blank">Another action</a> #}-->
<!--{# <div class="dropdown-divider"></div> #}-->
<!--{# <a class="dropdown-item" href="#">Something else here</a> #}-->
</div>
</li>
<!-- {# <li class="nav-item">
<a class="nav-link disabled" href="#">Disabled</a>
</li> #} -->
</ul>
<!--{#
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
#}-->
</div>
</nav>
<!--{# fin para validar el navbar #}-->
{% block content %} {% endblock %}
<div id="notification-area"></div>
<!--{# script inicio hamburger menu bootstrap #}-->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous">
</script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"
integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous">
</script>
<!--{# script fin hamburger menu bootstrap #}-->
<!-- {# fin js btsp #} -->
</body>
</html>

62
templates/error_page.html Normal file
View File

@ -0,0 +1,62 @@
{% extends 'base.html' %} {% block title %}Page 404{% endblock %} {% block content %}
<style>
.page_404 {
padding: 40px 0;
background: #fff;
font-family: "Arvo", serif;
}
.page_404 img {
width: 100%;
}
.four_zero_four_bg {
background-image: url("{{url_for('static', filename='imgs/errors_imgs/error_2.gif')}}");
height: 800px;
background-position: center;
}
.four_zero_four_bg h1 {
font-size: 80px;
}
.four_zero_four_bg h3 {
font-size: 80px;
}
/*
.link_404{
color: #fff!important;
padding: 10px 20px;
background: #39ac31;
margin: 20px 0;
display: inline-block;}
*/
.contant_box_404 {
margin-top: -5px;
}
</style>
<section class="page_404">
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="col-sm-10 col-sm-offset-1 text-center">
<div class="four_zero_four_bg">
<h1 class="text-center">Error 404</h1>
</div>
<div class="contant_box_404">
<h3 class="h2">
La página a la que deseas acceder al parecer no existe.
</h3>
<!-- <a href="" class="link_404">Go to Home</a> -->
</div>
</div>
</div>
</div>
</div>
</section>
{% endblock %}

36
templates/index.html Normal file
View File

@ -0,0 +1,36 @@
{% extends 'base.html' %}
<!--{# inicio titulo dinamico #}-->
{% block title %}Aldeas Inteligentes | SICT{% endblock %}
<!--{# fin titulo dinamico #}-->
<!--{# inicio css login #}-->
{% block recursos %}
<link rel="stylesheet" href="{{url_for('static', filename='css/login.css')}}"> {% endblock %}
<!--{# fin css login #}-->
<!--{# inicio contenido #}-->
{% block content %}
<div class="d-flex justify-content-center">
<form method="POST" action="{{ url_for('home') }}" id="forLogIn">
<!--{# <legend>Inicio de Sesión</legend> #}-->
{{ form.csrf_token }}
<div class="loginContainer">
<span class="lgid">GID:</span>
<span class="igid">{{ form.username(placeholder="Código GID") }}</span>
<span class="lpass">Contraseña:</span>
<span class="ipass">{{ form.password(placeholder="Contraseña Sitio") }}</span>
<input type="submit" value="Iniciar Sesión" class="btn btn-success" id="btnInicioSesion" />
</div>
</form>
</div>
{# variables de flask#}
<script>
let mensaje = "{{mensaje}}";
</script>
<script src="{{url_for('static', filename='js/javascript.js')}}" type="module"></script>
{% endblock %}
<!--{# fin contenido #}-->

View File

@ -0,0 +1,363 @@
{% extends 'base.html' %} {# title page #} {% block title %}Sitio GID: {{objeto['codigoGid']}} | SICT {% endblock %} {# css files #} {% block cssfiles %}
<link rel="stylesheet" href="{{url_for('static', filename='css/layoutreports.css')}}" /> {% endblock %} {% block content %} {# botones afectación al formulario #} {# inicio de style para ocultar elementos que si se deben de imprimir #}
<style type="text/css" media="print">
</style>
{# fin del style para ocultar elementos que si se deben de imprimir #} {# encabezado del formulario #}
<div id="layoutContainer">
<div id="btnsreportes">
<button type="button" class="btn btn-warning" id="btnLimpiar">Limpiar formulario</button>
<button type="button" class="btn btn-danger" id="btnCambiarGid"> <a class="link-light" href="{{url_for('home')}}">Cambiar GID</a></button>
<button type="button" class="btn btn-success" id="btnPrint">Imprimir formulario</button>
</div>
{# encabezado del reporte #}
<div>
<h4>Reporte Trimestral <br>Aldeas Inteligentes, Bienestar Sostenible</h4>
</div>
<div id="contenedorEncabezado">
<div id="first_row">
<label>
<b>Fecha Doc.:</b>
<span id="currentDate"></span>
</label>
<label>
<b>Código GID:</b>
<span>{{objeto['codigoGid']}}</span>
</label>
<label class=""><b>No. Indicadores: </b>
<span>{{objeto['nIndicadores']}}</span>
</label>
</div>
</div>
<div id="second_row">
<label> <b> Aldea Inteligente: </b>{{objeto['ai']}} </label>
<label> <b> Sitio: </b>{{objeto['sitio']}}</label>
</div>
<div id="third_row">
<label> <b>Estado:</b> {{objeto['edo']}}</label>
<label> <b> Municipio:</b> {{objeto['mun']}}</label>
<label> <b> Localidad:</b> {{objeto['loc']}}</label>
</div>
<div id="fourth_row">
<span class="lTrim"><b>Trimestre:</b></span>
<span class="lInicio"><b>Inicio: </b></span>
<input id="inicioTrim" type="date" />
<span class="lTermino"><b>Término: </b></span>
<input id="finTrim" type="date" />
</div>
</div>
{#
<!-- todos los indicadores -->
#}
<div id="containerIndicadores">
{#
<!-- inicio plantilla -->
#} {% for index in range(objeto['nIndicadores']) %}
<div>
{# inicio del loop indicadores #}
<div class="contenedor">
<div class="headerIndicador">
<h6> INDICADOR {{index+1}}</h6>
</div>
<div class="datosGlobalesIndicador">
<span class="lNombreIndicador"><b>Nombre indicador: </b></span>
<span>{{objeto.indicadores[index].nombre_del_indicador}}</span>
<span class="lDefinicion"><b>Definición: </b></span>
<span>{{objeto.indicadores[index].definicion}}</span>
<span class="lMeta"><b>Meta: </b></span>
<span id="meta_{{index+1}}">{{objeto.indicadores[index].meta}}</span>
<span class="lODS"><b> ODS impactados: </b></span>
<span>{{objeto.indicadores[index].ods_impactados}}</span>
<!-- linea base ${num} -->
<!--
<div>
<p align="right">
<strong>
Linea base:
</strong>
</p>
</div>
<div align="left">
<span>
${obj['linea_base']}
</span>
</div>
-->
</div>
<div class="dimensionAmedir">
<div class="cajasDAM">
<span class="cajaItem1"><b>Dimensión a medir:</b></span>
<span class="cajaItem2">{{objeto.indicadores[index].dimension_a_medir}}</span>
</div>
<div class="cajasDAM">
<span class="cajaItem1"><b> Unidad de medida: </b></span>
<span class="cajaItem2" id="unidadMedida_{{index+1}}">{{objeto.indicadores[index].unidad_de_medida}} </span>
</div>
<div class="cajasDAM">
<span class="cajaItem1"><b>Tipo de reporte: </b></span>
<span class="cajaItem2">{{objeto.indicadores[index].tipo_reporte}}</span>
</div>
<div class="cajasDAM">
<span class="cajaItem1"><b> Tipo de meta: </b></span>
<span class="cajaItem2" id="index_meta_{{index+1}}">{{objeto.indicadores[index].tipo_meta}}</span>
</div>
</div>
<div class="datosCalculo">
<div>
<p class="titleDatosCalc">Datos para el cálculo:</p>
</div>
<div class="varCalculo">
<input class="inputVarA" type="text" id="varA_{{index+1}}" maxlength="10" size="8" />
<span class="varA">
<b id="varA{{index+1}}Strong">
{{objeto.indicadores[index].variable_a.strip()}}
</b>
</span>
<input class="inputVarB" type="text" id="varB_{{index+1}}" maxlength="10" size="8" />
<span class="varB">
<b id="varB{{index+1}}Strong">
{% autoescape false %}
{{objeto.indicadores[index].variable_b | striptags | trim }}
{% endautoescape %}
</b>
</span>
</div>
</div>
<div class="semaforo">
<div class="circle" id="circle_{{index+1}}">
<label>
<span id="semaforo_{{index+1}}"> </span>
<span id="signo_{{index+1}}"> </span>
</label>
</div>
<!--{# inicio del div table #}-->
<div>
<table id="table_{{index+1}}">
<thead>
<tr>
<th colspan="3" class="thMain">Parámetros semáforo (%)</th>
</tr>
<tr>
<th class="thMain">Concepto</th>
<th class="thMain">L.I.</th>
<th class="thMain">L.S.</th>
</tr>
</thead>
<tbody>
<tr id="aceptable_{{index+1}}">
<th style="text-align: right">Aceptable:</th>
<td id="verde_li_{{index+1}}">
{{'%0.2f' |format(objeto.indicadores[index].verde_li * 100|float) }}
</td>
<td id="verde_ls_{{index+1}}">
{{'%0.2f' |format(objeto.indicadores[index].verde_ls * 100|float) }}
</td>
</tr>
<tr id="riesgo_{{index+1}}">
<th style="text-align: right">Riesgo:</th>
<td id="amarillo_li_{{index+1}}">
{{'%0.2f' |format(objeto.indicadores[index].amarillo_li * 100|float) }}
</td>
<td id="amarillo_ls_{{index+1}}">
{{'%0.2f' |format(objeto.indicadores[index].amarillo_ls * 100|float) }}
</td>
</tr>
<tr id="critico_{{index+1}}">
<th style="text-align: right">Crítico:</th>
<td>
0.00
</td>
<td id="rojo_ls_{{index+1}}">
{{'%0.2f' |format(objeto.indicadores[index].rojo_ls * 100|float) }}
</td>
</tr>
</tbody>
</table>
</div>
<!--{# fin del div table #}-->
</div>
{# fin del loop indicadores #}
</div>
</div>
{% endfor %}
<!-- {# fin de plantilla #} -->
<!-- {# inicio del campo de observaciones #} -->
<!-- {# sección obervaciones, información de soporte y firmas #} -->
<div class="headerIndicador" style="margin-top: 10px;">
<h6>OBSERVACIONES</h6>
</div>
<textarea rows="7" cols="75" id="observaciones" maxlength="1250" placeholder="En caso de tener comentarios relacionados a la conectividad o al sitio registrarlos aquí."></textarea>
<div class="headerIndicador">
<h6>INFORMACIÓN DE SOPORTE QUE SE ANEXARÁ</h6>
</div>
<div class="txt_area_container">
<textarea rows="7" cols="75" id="infosoporte" maxlength="1250" placeholder="Indicar la evidencia que se anexará para confirmar los datos registrados en el presente reporte, por ejemplo: listas de asistencias, listas de ventas, listas de cursos, etc."></textarea>
</div>
<div id="firmas">
<div>
<!-- inicio nuevo bloque preliminar -->
<div id="squareSignFielRepresentante">
<input type="file" name="" id="fileUploadRepresentante" />
<img src="" alt="firma representante" id="imgSignRepresentante" />
<span class="leyenda">Doble click para cargar firma digitalizada del representante del sitio</span>
</div>
<!-- fin nuevo bloque preliminar -->
<div>
<span id="encargadoSitio">{{objeto.responsableSitio}}</span><br />
<span id="cargoEncargado">{{objeto.PuestoResponsable}} </span><br />
<span>Firma Representante del Sitio</span>
</div>
</div>
<div>
<!-- inicio nuevo bloque preliminar -->
<div id="squareSignFielSubCentroSCT">
<input type="file" name="" id="fileUploadSubCentroSCT" />
<img src="" alt="firma representante" id="imgSignSubCentroSCT" />
<span class="leyenda">Doble click para cargar la firma digitalizada del representante del Centro SICT</span>
</div>
<!-- fin nuevo bloque preliminar -->
<div>
<span id="nombreSubCSICT">{{objeto.centroSICT['Nombre_Subdir']}}</span
><br />
<span id="cargo"
>{{objeto.centroSICT['Cargo']}}
{{objeto.centroSICT['Centro_SICT']}}</span
><br />
<span>Firma Vo.Bo.</span>
</div>
</div>
</div>
<!-- {# fin del campo de observaciones #} -->
<!-- div imagenes container -->
<div id="leyendaProyecto">
<p>
<b>
<i>
L.I.: Límite inferior | L.S.: Límite superior | ODS: Objetivos de Desarrollo Sostenible
</i>
</b>
</p>
<p id="leyenda" style="font-weight: bold; font-size: 14px;">
El proyecto “Aldeas Inteligentes, Bienestar Sostenible” y el servicio de conectividad a internet provista mediante este, es público y gratuito, ajeno a cualquier partido político. Queda prohibido su uso para fines distintos a los establecidos en el programa.
</p>
</div>
<div class="link_container">
<a href="https://www.gob.mx/privacidadsimplificado" target="_blank">
Aviso de Privacidad Simplificado
</a>
<a href="https://www.gob.mx/aviso_de_privacidad" target="_blank">
Aviso de Privacidad Integral
</a>
<a href="{{url_for('mapa')}}" target="_blank">
Mapa de Sitios Instalados
</a>
<a id="manual" href="http://192.168.1.66/MANUAL_INFORME_DE_ACTIVIDADES_DE_LAS_ALDEAS_INTELIGENTES.pdf" target="_blank">
Manual de usuario
</a>
<a href="" id="historico" target="_blank">
</a>
</div>
<div id="myGallery">
<a href="https://www.un.org/sustainabledevelopment/es/poverty/" target="_blank">
<img src="{{url_for('static', filename='imgs/1.webp')}}" alt="ODS 1">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/hunger/" target="_blank">
<img src="{{url_for('static', filename='imgs/2.webp')}}" alt="ODS 2">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/health/" target="_blank">
<img src="{{url_for('static', filename='imgs/3.webp')}}" alt="ODS 3">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/education/" target="_blank">
<img src="{{url_for('static', filename='imgs/4.webp')}}" alt="ODS 4">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/gender-equality/" target="_blank">
<img src="{{url_for('static', filename='imgs/5.webp')}}" alt="ODS 5">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/water-and-sanitation/" target="_blank">
<img src="{{url_for('static', filename='imgs/6.webp')}}" alt="ODS 6">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/energy/" target="_blank">
<img src="{{url_for('static', filename='imgs/7.webp')}}" alt="ODS 7">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/economic-growth/" target="_blank">
<img src="{{url_for('static', filename='imgs/8.webp')}}" alt="ODS 8">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/infrastructure/" target="_blank">
<img src="{{url_for('static', filename='imgs/9.webp')}}" alt="ODS 9">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/inequality/" target="_blank">
<img src="{{url_for('static', filename='imgs/10.webp')}}" alt="ODS 10">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/cities/" target="_blank">
<img src="{{url_for('static', filename='imgs/11.webp')}}" alt="ODS 11">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/sustainable-consumption-production/" target="_blank">
<img src="{{url_for('static', filename='imgs/12.webp')}}" alt="ODS 12">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/climate-change-2/" target="_blank">
<img src="{{url_for('static', filename='imgs/13.webp')}}" alt="ODS 13">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/oceans/" target="_blank">
<img src="{{url_for('static', filename='imgs/14.webp')}}" alt="ODS 14">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/biodiversity/" target="_blank">
<img src="{{url_for('static', filename='imgs/15.webp')}}" alt="ODS 15">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/peace-justice/" target="_blank">
<img src="{{url_for('static', filename='imgs/16.webp')}}" alt="ODS 16">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/globalpartnerships/" target="_blank">
<img src="{{url_for('static', filename='imgs/17.webp')}}" alt="ODS 17">
</a>
<a href="https://www.un.org/sustainabledevelopment/es/sustainable-development-goals/" target="_blank">
<img src="{{url_for('static', filename='imgs/ODS.webp')}}" alt="ODS">
</a>
</div>
</div>
</div>
<script>
let nIndicadores = '{{objeto.nIndicadores}}'
</script>
<script src="{{url_for('static', filename='js/layoutreporte.js')}}" type="module"></script>
</div>
{% endblock %}

48
templates/mapa.html Normal file
View File

@ -0,0 +1,48 @@
{% extends 'base.html' %}
<!-- {# inicio título dinámico #} -->
{% block title %}Mapa Sitios Instalados | SICT{% endblock %}
<!-- {# fin título dinámico #} -->
{% block recursos %}
<!-- {# inicio cdn leaflet #} -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
<!-- {# fin cdn leaflet #} -->
<!-- {# inicio css mapa #} -->
<link rel="stylesheet" href="{{url_for('static', filename='css/mapa.css')}}" />
<!-- {# fin css mapa #} -->
{% endblock %} {% block content %}
<div id="tableContainerSitios">
<div id="contImgDownloads">
<b id="nsitios"></b>
<img id="csvDescarga" src="{{url_for('static', filename='imgs/export_csv.png')}}" alt="" width="60px" />
<img id="jsonDescarga" src="{{url_for('static', filename='imgs/json_file.png')}}" alt="" width="60px" />
<img id="txtDescarga" src="{{url_for('static', filename='imgs/txt_file.png')}}" alt="" width="60px" />
</div>
<table id="tableSitios">
<thead>
<tr>
<th class="centerText">Estado</th>
<th class="centerText specialWidth">Sitios</th>
</tr>
</thead>
<tbody id="dataSitiosInstalados"></tbody>
</table>
</div>
<div id="map"></div>
<script src="{{url_for('static', filename='js/mapa.js')}}" type="module"></script>
{% endblock %}