commit 5038b2433e1490b2d538ff69a753bb17caf8df17 Author: David Itehua Xalamihua Date: Tue Aug 20 13:45:33 2024 -0600 inicio del proyecto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ceb386 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +venv diff --git a/db_conf.py b/db_conf.py new file mode 100644 index 0000000..96ae8f6 --- /dev/null +++ b/db_conf.py @@ -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 diff --git a/main.py b/main.py new file mode 100644 index 0000000..90d3b51 --- /dev/null +++ b/main.py @@ -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") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..60e8f61 --- /dev/null +++ b/requirements.txt @@ -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 diff --git a/sict-csic.page.conf b/sict-csic.page.conf new file mode 100644 index 0000000..5bd0649 --- /dev/null +++ b/sict-csic.page.conf @@ -0,0 +1,18 @@ + + 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 + + + WSGIProcessGroup app + WSGIApplicationGroup %{GLOBAL} + Order deny,allow + Require all granted + + \ No newline at end of file diff --git a/sictApp.wsgi b/sictApp.wsgi new file mode 100644 index 0000000..f8e94a6 --- /dev/null +++ b/sictApp.wsgi @@ -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 \ No newline at end of file diff --git a/static/css/layoutreports.css b/static/css/layoutreports.css new file mode 100644 index 0000000..69ecf45 --- /dev/null +++ b/static/css/layoutreports.css @@ -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 */ \ No newline at end of file diff --git a/static/css/login.css b/static/css/login.css new file mode 100644 index 0000000..4f8374c --- /dev/null +++ b/static/css/login.css @@ -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; + } +} \ No newline at end of file diff --git a/static/css/mapa.css b/static/css/mapa.css new file mode 100644 index 0000000..7f5a75f --- /dev/null +++ b/static/css/mapa.css @@ -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; + } +} \ No newline at end of file diff --git a/static/css/style.css b/static/css/style.css new file mode 100644 index 0000000..4755ba9 --- /dev/null +++ b/static/css/style.css @@ -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%; + } +} \ No newline at end of file diff --git a/static/imgs/1.webp b/static/imgs/1.webp new file mode 100644 index 0000000..eb9bf22 Binary files /dev/null and b/static/imgs/1.webp differ diff --git a/static/imgs/10.webp b/static/imgs/10.webp new file mode 100644 index 0000000..f271851 Binary files /dev/null and b/static/imgs/10.webp differ diff --git a/static/imgs/11.webp b/static/imgs/11.webp new file mode 100644 index 0000000..a95de74 Binary files /dev/null and b/static/imgs/11.webp differ diff --git a/static/imgs/12.webp b/static/imgs/12.webp new file mode 100644 index 0000000..a804b9c Binary files /dev/null and b/static/imgs/12.webp differ diff --git a/static/imgs/13.webp b/static/imgs/13.webp new file mode 100644 index 0000000..89a0e91 Binary files /dev/null and b/static/imgs/13.webp differ diff --git a/static/imgs/14.webp b/static/imgs/14.webp new file mode 100644 index 0000000..fddf938 Binary files /dev/null and b/static/imgs/14.webp differ diff --git a/static/imgs/15.webp b/static/imgs/15.webp new file mode 100644 index 0000000..bbb0cfa Binary files /dev/null and b/static/imgs/15.webp differ diff --git a/static/imgs/16.webp b/static/imgs/16.webp new file mode 100644 index 0000000..f4ca5af Binary files /dev/null and b/static/imgs/16.webp differ diff --git a/static/imgs/17.webp b/static/imgs/17.webp new file mode 100644 index 0000000..fb44545 Binary files /dev/null and b/static/imgs/17.webp differ diff --git a/static/imgs/2.webp b/static/imgs/2.webp new file mode 100644 index 0000000..b46166b Binary files /dev/null and b/static/imgs/2.webp differ diff --git a/static/imgs/3.webp b/static/imgs/3.webp new file mode 100644 index 0000000..d3be305 Binary files /dev/null and b/static/imgs/3.webp differ diff --git a/static/imgs/4.webp b/static/imgs/4.webp new file mode 100644 index 0000000..3cf0407 Binary files /dev/null and b/static/imgs/4.webp differ diff --git a/static/imgs/5.webp b/static/imgs/5.webp new file mode 100644 index 0000000..f7cad28 Binary files /dev/null and b/static/imgs/5.webp differ diff --git a/static/imgs/6.webp b/static/imgs/6.webp new file mode 100644 index 0000000..35f0cf9 Binary files /dev/null and b/static/imgs/6.webp differ diff --git a/static/imgs/7.webp b/static/imgs/7.webp new file mode 100644 index 0000000..066834a Binary files /dev/null and b/static/imgs/7.webp differ diff --git a/static/imgs/8.webp b/static/imgs/8.webp new file mode 100644 index 0000000..8492584 Binary files /dev/null and b/static/imgs/8.webp differ diff --git a/static/imgs/9.webp b/static/imgs/9.webp new file mode 100644 index 0000000..b30ca01 Binary files /dev/null and b/static/imgs/9.webp differ diff --git a/static/imgs/LogoAI.webp b/static/imgs/LogoAI.webp new file mode 100644 index 0000000..8e6a43a Binary files /dev/null and b/static/imgs/LogoAI.webp differ diff --git a/static/imgs/ODS.webp b/static/imgs/ODS.webp new file mode 100644 index 0000000..32111d4 Binary files /dev/null and b/static/imgs/ODS.webp differ diff --git a/static/imgs/accesibilidad.png b/static/imgs/accesibilidad.png new file mode 100644 index 0000000..9d21a15 Binary files /dev/null and b/static/imgs/accesibilidad.png differ diff --git a/static/imgs/errors_imgs/error_1.gif b/static/imgs/errors_imgs/error_1.gif new file mode 100644 index 0000000..508d5e2 Binary files /dev/null and b/static/imgs/errors_imgs/error_1.gif differ diff --git a/static/imgs/errors_imgs/error_2.gif b/static/imgs/errors_imgs/error_2.gif new file mode 100644 index 0000000..b4eb84b Binary files /dev/null and b/static/imgs/errors_imgs/error_2.gif differ diff --git a/static/imgs/errors_imgs/error_3.gif b/static/imgs/errors_imgs/error_3.gif new file mode 100644 index 0000000..ed718dd Binary files /dev/null and b/static/imgs/errors_imgs/error_3.gif differ diff --git a/static/imgs/export_csv.png b/static/imgs/export_csv.png new file mode 100644 index 0000000..62a781c Binary files /dev/null and b/static/imgs/export_csv.png differ diff --git a/static/imgs/favicon.ico b/static/imgs/favicon.ico new file mode 100644 index 0000000..f62b0a6 Binary files /dev/null and b/static/imgs/favicon.ico differ diff --git a/static/imgs/icon_ai2.png b/static/imgs/icon_ai2.png new file mode 100644 index 0000000..6e07db6 Binary files /dev/null and b/static/imgs/icon_ai2.png differ diff --git a/static/imgs/json_file.png b/static/imgs/json_file.png new file mode 100644 index 0000000..52617f5 Binary files /dev/null and b/static/imgs/json_file.png differ diff --git a/static/imgs/logoSICT.webp b/static/imgs/logoSICT.webp new file mode 100644 index 0000000..c60b0ad Binary files /dev/null and b/static/imgs/logoSICT.webp differ diff --git a/static/imgs/mute.webp b/static/imgs/mute.webp new file mode 100644 index 0000000..f2e008d Binary files /dev/null and b/static/imgs/mute.webp differ diff --git a/static/imgs/speaker.webp b/static/imgs/speaker.webp new file mode 100644 index 0000000..e9afc41 Binary files /dev/null and b/static/imgs/speaker.webp differ diff --git a/static/imgs/txt_file.png b/static/imgs/txt_file.png new file mode 100644 index 0000000..6b92f0f Binary files /dev/null and b/static/imgs/txt_file.png differ diff --git a/static/js/functions.js b/static/js/functions.js new file mode 100644 index 0000000..39603f7 --- /dev/null +++ b/static/js/functions.js @@ -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 +}; \ No newline at end of file diff --git a/static/js/javascript.js b/static/js/javascript.js new file mode 100644 index 0000000..a2cad57 --- /dev/null +++ b/static/js/javascript.js @@ -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); + } + }); + +})(); \ No newline at end of file diff --git a/static/js/layoutreporte.js b/static/js/layoutreporte.js new file mode 100644 index 0000000..cefb57e --- /dev/null +++ b/static/js/layoutreporte.js @@ -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 \ No newline at end of file diff --git a/static/js/mapa.js b/static/js/mapa.js new file mode 100644 index 0000000..ef888b6 --- /dev/null +++ b/static/js/mapa.js @@ -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(` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Nombre Unidad: + + ${nompropio(objeto["NombreUnidad"])} +
+ GID: + + ${objeto["CodigoGid"]} +
+ Denominación: + + ${denominacion} +
+ Estado: + + ${nompropio(objeto["Estado"])} +
+ Municipio: + + ${nompropio(objeto["Municipio"])} +
+ Localidad: + + ${nompropio(objeto["Localidad"])} +
+ Localización: + + ${objeto["ubicacion"]["latitud"]} ${ + objeto["ubicacion"]["longitud"] + } +
+ Lengua indígena: + + ${lenguasIndigenas} +
+ Fecha instalación: + + ${objeto["fechaInstalacion"]} +
+ Página sitio: + + + Infografía Sitio + +
`); +} + +// 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", + ` + + ${nompropio(ele["ESTADO"])} + + + ${ele["SITIOS_INSTALADOS"]} + + ` + ); + + 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 = `Estado: ${layer._path.attributes.id.nodeValue}`; + layer.bindPopup(texto).openPopup(); + // .setLatLng(latlng); + + }); + + }); + }); + }); +})(); + +L.tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { + attribution: 'Map data © OpenStreetMap', + 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 \ No newline at end of file diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..96a8c13 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + {% block title %}{% endblock %} + + + + + + + + + + + + + + + + + + + + {% block cssfiles%}{% endblock %} + + + + + + + + + {% block recursos %} {% endblock %} + + + + + +
+ logo gobierno de México + logo Aldeas Inteligentes +
+ + + + + + + {% block content %} {% endblock %} + +
+ + + + + + + + + + + diff --git a/templates/error_page.html b/templates/error_page.html new file mode 100644 index 0000000..093f78b --- /dev/null +++ b/templates/error_page.html @@ -0,0 +1,62 @@ +{% extends 'base.html' %} {% block title %}Page 404{% endblock %} {% block content %} + + + +
+
+
+
+
+
+

Error 404

+
+ +
+

+ La página a la que deseas acceder al parecer no existe. +

+ +
+
+
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..12166f3 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,36 @@ +{% extends 'base.html' %} + +{% block title %}Aldeas Inteligentes | SICT{% endblock %} + + + +{% block recursos %} + {% endblock %} + + + +{% block content %} + +
+
+ + {{ form.csrf_token }} +
+ GID: + {{ form.username(placeholder="Código GID") }} + Contraseña: + {{ form.password(placeholder="Contraseña Sitio") }} + +
+
+ +
+ +{# variables de flask#} + + + +{% endblock %} + diff --git a/templates/layout_reportes.html b/templates/layout_reportes.html new file mode 100644 index 0000000..fecdf62 --- /dev/null +++ b/templates/layout_reportes.html @@ -0,0 +1,363 @@ +{% extends 'base.html' %} {# title page #} {% block title %}Sitio GID: {{objeto['codigoGid']}} | SICT {% endblock %} {# css files #} {% block cssfiles %} + {% endblock %} {% block content %} {# botones afectación al formulario #} {# inicio de style para ocultar elementos que si se deben de imprimir #} + + + + +{# fin del style para ocultar elementos que si se deben de imprimir #} {# encabezado del formulario #} + + +
+ +
+ + + +
+ + {# encabezado del reporte #} +
+

Reporte Trimestral
Aldeas Inteligentes, Bienestar Sostenible

+
+ +
+
+ + + + + + + +
+
+
+ + +
+
+ + + +
+
+ Trimestre: + Inicio: + + Término: + +
+
+{# + +#} +
+ {# + + #} {% for index in range(objeto['nIndicadores']) %} +
+ {# inicio del loop indicadores #} +
+
+
INDICADOR {{index+1}}
+
+
+ + Nombre indicador: + + {{objeto.indicadores[index].nombre_del_indicador}} + + Definición: + + {{objeto.indicadores[index].definicion}} + + Meta: + + {{objeto.indicadores[index].meta}} + + ODS impactados: + + {{objeto.indicadores[index].ods_impactados}} + + + +
+
+
+ Dimensión a medir: + {{objeto.indicadores[index].dimension_a_medir}} +
+
+ Unidad de medida: + {{objeto.indicadores[index].unidad_de_medida}} +
+
+ Tipo de reporte: + {{objeto.indicadores[index].tipo_reporte}} +
+
+ Tipo de meta: + {{objeto.indicadores[index].tipo_meta}} +
+
+
+
+

Datos para el cálculo:

+
+
+ + + + + + {{objeto.indicadores[index].variable_a.strip()}} + + + + + + + + {% autoescape false %} + {{objeto.indicadores[index].variable_b | striptags | trim }} + {% endautoescape %} + + + +
+
+
+
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parámetros semáforo (%)
ConceptoL.I.L.S.
Aceptable: + {{'%0.2f' |format(objeto.indicadores[index].verde_li * 100|float) }} + + {{'%0.2f' |format(objeto.indicadores[index].verde_ls * 100|float) }} +
Riesgo: + {{'%0.2f' |format(objeto.indicadores[index].amarillo_li * 100|float) }} + + {{'%0.2f' |format(objeto.indicadores[index].amarillo_ls * 100|float) }} +
Crítico: + 0.00 + + {{'%0.2f' |format(objeto.indicadores[index].rojo_ls * 100|float) }} +
+
+ +
+ + {# fin del loop indicadores #} +
+
+ {% endfor %} + + + + +
+
OBSERVACIONES
+
+ +
+
INFORMACIÓN DE SOPORTE QUE SE ANEXARÁ
+
+
+ +
+ + +
+
+ +
+ + firma representante + Doble click para cargar firma digitalizada del representante del sitio +
+ +
+ {{objeto.responsableSitio}}
+ {{objeto.PuestoResponsable}}
+ Firma Representante del Sitio +
+
+
+ +
+ + firma representante + Doble click para cargar la firma digitalizada del representante del Centro SICT +
+ +
+ {{objeto.centroSICT['Nombre_Subdir']}}
+ {{objeto.centroSICT['Cargo']}} + {{objeto.centroSICT['Centro_SICT']}}
+ Firma Vo.Bo. +
+
+
+ + + + +
+

+ + + L.I.: Límite inferior | L.S.: Límite superior | ODS: Objetivos de Desarrollo Sostenible + + +

+

+ 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. +

+
+ + +
+ + + + + + + +{% endblock %} \ No newline at end of file diff --git a/templates/mapa.html b/templates/mapa.html new file mode 100644 index 0000000..196d99b --- /dev/null +++ b/templates/mapa.html @@ -0,0 +1,48 @@ +{% extends 'base.html' %} + +{% block title %}Mapa Sitios Instalados | SICT{% endblock %} + +{% block recursos %} + + + + + + + + + + +{% endblock %} {% block content %} + + + + + +
+ + +
+ + + + +
+ + + + + + + + + +
EstadoSitios
+
+
+ + + + + +{% endblock %} \ No newline at end of file