• No se han encontrado resultados

Desarrollo de una herramienta web para la gestión y visualización de archivos 3D

N/A
N/A
Protected

Academic year: 2020

Share "Desarrollo de una herramienta web para la gestión y visualización de archivos 3D"

Copied!
68
0
0

Texto completo

(1)

Desarrollo de una herramienta web

para la gestión y visualización de

archivos 3D

Por

Mauro Torres

Trabajo Final de la carrera de grado de Ingeniería de Sistemas de la

Universidad Nacional del Centro de la Provincia de Buenos Aires

Directores: Dr. Ignacio Larrabide, Ing. Nicolás Dazeo

(2)

Índice

Capítulo 1: Introducción 3

1.1 Antecedentes 3

1.2 Motivación y objetivo de trabajo 4

1.3 Estado del arte 5

1.4 Contenidos de la carrera aplicados en el desarrollo de este trabajo 6

1.5 Organización del trabajo 7

Capítulo 2: Renderización Remota 9

2.1 Renderización local 9

2.2 Renderización remota - Framework ParaViewWeb y Visualizer 9

2.3 Renderización remota - Arquitectura 10

2.4 - Renderización remota - Backend Apache 11

2.4.1 - Crear proxy y archivo de mapeo 11

2.4.2 - Creación de VirtualHost 12

2.4.3 - Habilitar los módulos 14

2.5 - Renderización remota - Launcher 15

2.5.1 - Configuración del launcher 15

2.6 Visualización remota y archivos 18

Capítulo 3: Backend Golang 19

3.1 Tecnologías 19

3.2 Sistema de Archivos 20

3.3 Autenticación : Token JWT 20

3.4 Roles 21

3.5 Arquitectura y Servicios 23

3.5.1 Servicios administrador 24

3.5.2 Servicios en común especialista y técnico 27

3.5.3 Servicios Especialista 31

3.5.4 Servicios Técnico 33

Capítulo 4: Frontend web 34

4.2 Acciones 37

4.3 Autorizaciones 38

4.4 Roles 38

4.4.1 Rol Administrador 39

4.4.2 Rol Especialista 41

4.4.3 Rol Técnico 49

4.5 Interfaz común entre Especialista y Técnico. 50

(3)

Capítulo 5: Despliegue de la aplicación y resultados 53

5.1: Docker 54

5.1.1 Cliente.dockerfile 54

5.1.2 Fileserver.dockerfile 55

5.1.4 Render.dockerfile 55

5.1.5 docker-compose.dockerfile 56

5.2: Resultados y métricas tomadas 57

5.2.1 Tiempo de carga inicial 57

5.2.2 Tiempo de actualización de datos 57

5.2.3 Memoria de cliente 60

Capítulo 6: Conclusiones 60

6.1 Trabajos Futuros 61

(4)

Capítulo 1: Introducción

1.1 Antecedentes

El desarrollo de nuevas técnicas de análisis y procesamiento de imágenes y simulación en medicina ha tenido un gran impacto en la salud [1,2]. Desde el diagnóstico, hasta la selección de los tratamientos, estas técnicas proveen mayor información a los médicos, asistiendo en la toma de decisiones y guiando el tratamiento [3,4,5]. Estas técnicas están haciendo de la medicina una disciplina de alta precisión [6,7].

Los aneurismas son dilataciones patológicas de las arterias, las cuales pueden romperse si no son tratadas a tiempo. La ruptura de un aneurisma puede llevar a hemorragias con altas tasas de discapacidad e incluso muerte [8]. Los tratamientos más frecuentes son intravasculares mínimamente invasivos, donde se destacan los stents y los coils, por su menor riesgo frente a la cirugía abierta [9,10].

En la última década, el uso de stents intravasculares se volvió más frecuente en estas patologías [11,12]. Pero todavía hay muchos aspectos de su comportamiento y efecto en la hemodinamia local que no es comprendido en profundidad. El uso de la simulación computacional de fluidos es de gran beneficio para comprender los efectos e implicancias de su uso [13,14].

Para analizar el estado de un paciente, se obtiene una imagen 3D, a partir de una tomografía o resonancia. La imagen 3D se utiliza para obtener una descripción geométrica 3D de la anatomía de las paredes de los vasos sanguíneos afectados. Una vez obtenida la región de interés que será simulada usando Dinámica de Fluidos Computacional (CFD, de su nombre en inglés), se utiliza un flujo de trabajo standard para llegar a una simulación del flujo sanguíneo completa de esa parte de la anatomía [15].

(5)

[16,17]. Estos resultados son de gran interés para los especialistas médicos, que analizan posibles causas y tratamientos [18,19].

La simulación de fluidos es una herramienta fundamental para el análisis de formación y planificación del tratamiento de aneurismas, una de las mayores causas de muerte en el mundo [20,21].

1.2 Motivación y objetivo de trabajo

Los ingenieros que realizan este tipo de simulaciones y los médicos que deben tomar las decisiones no siempre se encuentran en el mismo lugar físico. Por esto es necesario llevar los resultados de este análisis a sus manos de una forma simple y segura. Esto requiere de un gran volumen de espacio de almacenamiento en la nube y un ancho de banda que permita la transferencia. Por otro lado, los resultados de este análisis producen datos en formatos específico, requiriendo de herramientas especializadas para su adecuada interpretación y visualización [22]. Estas herramientas deben ser debidamente instaladas, requiriendo de tiempo y de conocimientos técnicos especializados, algo que no siempre está al alcance del médico.

El objetivo de este trabajo es desarrollar una herramienta online de visualización de simulaciones de fluidos en arterias para el estudio y planificación del tratamiento de aneurismas cerebrales para ser utilizada por usuarios sin amplios conocimientos técnicos, que simplifique su interacción con el equipo técnico.

(6)

Para reducir los tiempos de respuesta, se explorará la posibilidad de permitir realizar distintas formas de despliegue (deployment) seleccionando el lugar de procesamiento entre el servidor y el cliente.

1.3 Estado del arte

Se realizó una exploración de las tecnologías existentes, considerando tanto soluciones libres (Open Source) como privativas. Los resultados de este estudio se resumen a continuación:

Three.js: Es una biblioteca lightweight hecha en JavaScript, sirve para

renderizar modelos 3D en navegadores web ( web browsers) utilizando renderizado de canvas 2D, SVG, CSS3D ó WebGL. Esta es de código abierto [23].

ParaViewWeb​: Es un frameworkhecho en JavaScript, sirve para renderizar e

interactuar con modelos 3D en navegadores web, cuenta con el soporte local y remoto [24], y está desarrollado y mantenido por Kitware (Clifton Park, NY, USA)[25,26]

3DViewerOnline: Es una herramienta web, de uso gratuito por 14 días,

permite visualizar modelos 3D, permitiendo hacer pequeñas modificaciones visuales al modelo. Luego del periodo de prueba, se debe abonar una licencia [27]

(7)

1.4 Contenidos de la carrera aplicados en el desarrollo de este

trabajo

Para llevar a cabo este trabajo final fueron aplicados todos los conocimientos aprendidos en el transcurso de la carrera. Se destacan aquellos que fueron especialmente importantes por su relación directa con el trabajo desarrollado:

La cátedra de Lenguajes de Programación [28,29] y Diseño de Compiladores I [30,31], aportó conceptos muy importantes para comprender la utilización de funciones teniendo en cuenta el tipo de pasaje de parámetro para mejorar el rendimiento de la herramienta.

Las materias como Diseño de Software [32,33] y Programación Orientada a Objetos [34,35] fueron claves para comprender la arquitectura y el diseño de

ParaViewWeb, además de la detección e implementación de patrones de diseño

necesarios para hacer efectiva la separación de renderizado de la interfaz.

Los conocimientos adquiridos en la cátedra de Sistemas Operativos [36,37] hicieron posible la comprensión del concepto de librerías, su utilidad, y de cómo el sistema operativo interactúa con ellas.

Utilizando los conceptos aprendidos en la optativa del Taller de Desarrollo Web [37.5] para discernir las diferentes responsabilidades del cliente y del servidor, las tareas que cada uno tiene que llevar a cabo y la comunicación entre estos.

La cátedra de Metodologías de Software me capacitó para la elaboración de diagramas y vistas arquitectónicas presentadas a lo largo de este trabajo final.

Al momento de implementar la base de datos cátedras de Estructuras de Datos I [38,39] y Bases de Datos [40,41] fueron fundamentales brindaron conceptos claves al momento de definir que datos voy a utilizar, como los voy a guardar, qué relaciones van a tener entre ellos y que formato van a tener esos datos.

(8)

Además, las cátedras de Ciencias de la Computación I [46,47] y II [48,49] aportaron al entendimiento de la transición entre los diferentes estados de la aplicación web y ayudando a reducir las condiciones lógicas para una mayor mantenibilidad del código.

Y por último para entender cómo funciona la renderización remota o local, las cátedras como Álgebra Lineal [50] y Matemática Discreta [51] son fundamentales para entender las transformaciones de las matrices cuando el usuario final interactúa con las figuras geométricas y cómo estos valores se discretizan para utilizarlos en tipos primitivos primitivas.

1.5 Organización del trabajo

Con el fín de facilitar la comprensión y la lectura del trabajo, se encuentra desarrollado en capítulos seleccionados que se detallan a continuación:

Capítulo 2: Se detalla el framework elegido, los dos tipos de renderizaciones que la aplicación soporta e información necesaria relacionada, incluyendo cómo trabaja cada una de ellas. Está dividido en dos partes. La primera trata sobre la renderización local y las librerías que utiliza para lograrlo. Luego se pasa a la renderización remota, se detallan las configuraciones necesarias, como funciona y sus diferentes aplicaciones.

Capítulo 3: Detalla cómo trabaja el servidor de autenticación, las estructuras que utiliza, como funciona la autenticación de los usuarios, como este administra los archivos de cada especialista y que datos se guardan en la base de datos.

(9)

Capítulo 5: Detalla cómo se creó cada imagen de cada parte de la aplicación y la creación de un orquestador para administrar todas las imágenes juntas utilizado la tecnología de Docker.

(10)

Capítulo 2: Renderización Remota

Se detalla el framework elegido, los dos tipos de renderizaciones que la aplicación soporta e información necesaria relacionada, incluyendo cómo trabaja cada una de ellas. Está dividido en dos partes. La primera trata sobre la renderización local y las librerías que utiliza para lograrlo. Luego se pasa a la renderización remota, se detallan las configuraciones necesarias, como funciona y sus diferentes aplicaciones. La decisión de soportar dos tipos de renderizaciones se tomó en base a qué puede suceder que el servidor remoto de renderización no esté disponible por sobrecarga o por indisponibilidad y cómo esta herramienta es de uso médico, la alternativa de renderización local solucionaría este problema.

2.1 Renderización local

Para los casos en que el servidor de renderización no se encuentra disponible, la aplicación posee la opción de renderización local. Esta solo funciona para los archivos de extensión .stl, y utiliza la librería vtk.js, para poder realizar la renderización del archivo elegido. La librería vtk.js es parte del framework

ParaViewWeb​. Se agregó una validación para que la extensión del archivo siempre

sea .stl, en caso contrario se informa con un mensaje que el archivo no es válido. La renderización que se hace es sin permitir modificaciones de ningún tipo sobre los archivos de datos visualizados. Solo se permite hacer operaciones de zoom,rotar y desplazar sobre el objeto en los 7 grados de libertad posibles.

2.2 Renderización remota - Framework ParaViewWeb y Visualizer

(11)

Sin embargo, buscando en la documentación del framework, se encuentra disponible la aplicación Visualizer​, desarrollada por Kitware ​cuya premisa es ser igual a ParaView, que es lo que se pretendía hacer, para que los especialistas la utilicen directamente en la web. Esto reduce enormemente el tiempo de desarrollo para tener una herramienta utilizable en el menor tiempo y automatizar todo el trabajo. Visualizer es una aplicación web que delega las capacidades de procesamiento de ParaView en el backend para producir visualizaciones interactivas a través de la web. La aplicación se puede usar en modo local, que implica tener conocimientos avanzados en sistemas, dado que hay que descargar el proyecto por línea de comando con el administrador de paquetes de npm, ejecutarlo por línea de comando y finalmente utilizarlo accediendo a un servidor local. Adicionalmente, posee el modo remoto que puede ser configurado para que el usuario no tenga más que seleccionar el archivo que desea renderizar.

2.3 Renderización remota - Arquitectura

Para montar un entorno multiusuario de renderización, se necesitan 4 componentes (Figura 1): un cliente web que utilizan los usuarios finales, un backend para actuar como un punto de entrada para los clientes, el launcher que arranca un nuevo proceso de visualización para cada cliente que lo requiera y una instancia de ParaViewWeb.[52,53]

Figura 1: Arquitectura de ParaViewWeb

(12)

2.4 - Renderización remota - Backend Apache

Las principales responsabilidades delbackendson servir contenido estático y hacer el redireccionamiento de la red, proveyendo un único punto de entrada para todos los clientes que quieran comunicarse.

El backend debe poder hacer un redireccionamiento de ciertos pedidos al

launchercuando un cliente quiera iniciar una nueva sesión de visualización. Además debe ser capaz de obtener del launcher el puerto donde aquella sesión se esté escuchando. Para llevar a cabo la implementación del backend vamos a utilizar el servidor HTTP Apache que debe ser configurado como se detalla a continuación.

2.4.1 - Crear

proxy

y archivo de mapeo

El sistema debe conocer la asociación entre cada cliente web y su correspondiente puerto [54,55]. Para ello se necesita disponer de un archivo de mapeo, donde el launcher informa a Apache sobre las sesiones y puertos de cada cliente. Para esta configuración se asume que el directorio de trabajo, se llama <MAPPING-FILE-DIR>

También se asume que el usuario “ daemon” es el usuario que va a ejecutar el Apache y el usuario “ pvw-user” va a ejecutar el launcher. El último usuario debe ejecutar lo siguiente para la correcta configuración del entorno:

$ sudo mkdir -p <MAPPING-FILE-DIR> $ sudo touch <MAPPING-FILE-DIR>/proxy.txt $ sudo groupadd mappingfileusers

$ sudo usermod -a -G mappingfileusers pvw-user $ newgrp mappingfileusers

$ sudo usermod -a -G mappingfileusers daemon

$ sudo chgrp mappingfileusers <MAPPING-FILE-DIR>/proxy.txt $ sudo chmod 660 <MAPPING-FILE-DIR>/proxy.txt

Estos hacen lo siguiente:

(13)

3. Se crea un nuevo grupo llamado mappingfileusers. Este contendrá a los usuarios autorizados a acceder al proxy.

4. Se agrega al usuario pvw-user al grupo mappingfileusers.[56] 5. Se carga el grupo mappingfileusers a la sesión actual.

6. Se agrega al usuario daemon al grupo mappingfileusers. 7. Se asigna el archivo creado, al grupo mappingfileusers.

8. Se asignan permisos de lectura y escritura al dueño y a los que pertenecen al grupo mappingfileusers.

2.4.2 - Creación de

VirtualHost

El término VirtualHost en Apache hace referencia a correr más de un sitio web en una misma máquina. Para la configuración del VirtualHost se deben que correr los siguientes comandos:

$ sudo touch /etc/apache2/sites-available/001-pvw.conf

$ sudo ln -sf /etc/apache2/sites-available/001-pvw.conf /etc/apache2/sites-enabled/

(14)

<VirtualHost *:80>

ServerName www.backendapache.com ServerAdmin marowark@gmail.com

DocumentRoot “/www/www.backendapache.com” ErrorLog${APACHE_LOG_DIR}/error.log

CustomLog${APACHE_LOG_DIR}/access.log combined ProxyPass /paraview 0.0.0.0:9000/paraview

RewriteEngineOn

RewriteMap session-to-port txt:<MAPPING-FILE-DIR>/proxy.txt RewriteCond%{QUERY_STRING} ^sessionId=(.*)&path=(.*)$ [NC] RewriteRule ^/proxy.*$ ws://${session-to-port:%1 }/%2 [P]

<Directory "${MY-DOCUMENT-ROOT}"> Options Indexes FollowSymLinks Order allow,deny

Allow from all

AllowOverride None Requireall granted </Directory>

</VirtualHost>

La tag VirtualHost se acompaña de *:80, esto implica que el servidor no va a responder el pedido, es decir, primero va a intentar parear por todos los

ServerName de cada VirtualHost que tenga configurado el archivo (puede existir

más de un VirtualHost por archivo). Si no puede parear con ninguno, toma por defecto la primer opción disponible.

El asterisco (*) se puede cambiar por una IP específica, para que el servidor solo responda sobre IP específicas. Sin embargo, en entornos donde las direcciones ip son asignadas por un ISP dinámicamente, cada vez que nos cambien la IP, tenemos que cambiarla en el archivo de configuración.

En ServerName se asigna nombre al servidor, y DocumentRoot contiene el path del directorio en donde van a estar todos los archivos del backend. La directiva ErrorLog establece el nombre del archivo en donde el servidor va a loguear los errores, en caso de que ocurriesen.

(15)

La directiva ProxyPass es utilizada por Apache para actuar de intermediario. Todas las peticiones que lleguen a /paraview son redirigidas por defecto a

0.0.0.0:9000/paraview. Al existir la directiva RewriteRule, las peticiones se modifican

según se cumplan las condiciones de RewriteCond. La directiva RewriteMap define un mapa clave-valor llamado session-to-port. Este mapa se va a guardar en archivo proxy.txt en el path txt:<MAPPING-FILE-DIR>/proxy.txtcomo clave se tomará la sesión y como valor el puerto del cliente. El prefijo txt indica que se almacenará el par sesión-puerto por línea.

La directiva RewriteCond es la condición por la cual la directiva RewriteRule va a ser activada y está configurada de la siguiente manera:

El prefijo%{QUERY_STRING}indica que se va a fijar en la parte de la consulta de la URL que contiene los parámetros e intercepta los pedidos que coincidan con los parámetros ^sessionId=(.*)&path=(.*)$. Además este posee la opción [NC] , para que no distinga mayusculas de minusculas en la búsqueda.

La directiva RewriteRule es la que finalmente realiza el trabajo de reescribir en tiempo de ejecución.

Cuando una petición viene de la forma /proxy.*, esta regla se activa. El puerto para la sesión del usuario que generó la petición, lo obtiene del mapa que declaramos anteriormente. Para buscar el valor del puerto, utiliza la clave que viene por el parámetro %1, que hace referencia al primer (.*) de la directiva RewriteCond. Lo mismo sucede con el parámetro %2, que además posee la opción [P] que hace que la redirección de la petición se dirija hacia el proxy, definido por el ProxyPass, de la siguiente forma ws://${session-to-port:%1}/%2.

Cuando se produce la reescritura, esto significa que la sesión ya existía previamente y solo de debe redireccionar En caso contrario, se debe crear una nueva sesión.

2.4.3 - Habilitar los módulos

(16)

$ sudo a2enmod vhost_alias $ sudo a2enmod proxy $ sudo a2enmod proxy_http $ sudo a2enmod proxy_wstunnel

Luego de habilitar todos los módulos, se habilita la configuración del servidor. Para esto se carga la configuración de 001-pvw.conf, se quita la configuración por defecto, y se reinicia Apache para que tome todos los cambios.

$ sudo a2ensite 001-pvw.conf $ sudo a2dissite 000-default.conf $ sudo service apache2 restart

2.5 - Renderización remota - Launcher

Este es el módulo responsable de iniciar un nuevo proceso de visualización para cada usuario que lo requiera. Este launcher está incluido en ParaViewWeb (Figura 1) y no se requiere instalar ningún software extra. Solo se necesita ajustar la configuración como en el backend de Apache. El principal objetivo del launcher es permitir a los clientes requerir una nueva sesión de visualización e interactuar con ella. El launcher responde de la siguiente manera para cada petición:

1. comienza un nuevo proceso al acceder el usuario 2. genera una clave única para la sesión

3. comunica la clave única al cliente web y al backend de Apache, así el

backend sabe a donde hacer el redireccionamiento para los pedidos

subsecuentes de la sesión.

2.5.1 - Configuración del

launcher

El launcher posee un archivo de configuración, se van a explicar las

características más importantes del mismo y cómo estas interactúan con el backend

(17)

{

"resources"​ : [ {​ "port_range"​ : [​9001​, ​9103​], ​"host"​ : ​"172.21.0.2"​ } ], "sessionData"​: {

​"updir"​: ​"/opt/wslink-launcher" },

"configuration"​: {

​"log_dir"​ : ​"/opt/wslink-launcher/log"​, ​"host"​ : ​"0.0.0.0"​,

​"port"​ : ​9000​,

​"endpoint"​: ​"paraview"​,

​"sessionURL"​ : ​"ws://${host}:${port}/ws"​, ​"timeout"​ : 2​5​,

​"upload_dir"​ : ​"/opt/wslink-launcher/upload"​, ​"fields"​ : [​"file"​, ​"updir"​]

​"proxy_file"​ : ​"/opt/wslink-launcher/proxy-mapping.txt"​, ​"sanitize"​: {

​ "version"​: {

​"type"​: ​"regexp"​,

​"regexp"​: ​"^v[0-9]+.[0-9]+.[0-9]+$"​,

​"default"​: ​"v0.0.0"

},

​ "file"​: {

​"type"​: ​"regexp"​,

​"regexp"​: ​"^[-\\\\w./]+$"​,

​"default"​: ​"emptyFile"

} } },

"properties"​ : {

"webapps_dir"​:​ "/opt/paraview/install/share/paraview-5.5/web"​, ​"python_exec"​: ​"/opt/paraview/install/bin/pvpython"

},

"apps"​: {

​"visualizer"​: {

​"cmd"​: [

​"${python_exec}"​,

"-dr"​,

"${webapps_dir}/visualizer/pvw-visualizer.py"​,

​"--port"​,​"${port}"​,

"--data"​,​"${dataDir}"​, "--authKey"​, ​"${secret}"​,

​"--viewport-max-width"​, ​"1920"​,

​"--viewport-max-height"​, ​"1080"​,

​ "--timeout"​, ​"30"

],

​"ready_line"​ : ​"Starting factory"

(18)

A continuación se detalla qué significa cada parte de la configuración del launcher host: es la interfaz de red que va a utilizar el launcher.

port: el puerto de la interfaz que va a usar el launcher.

endpoint: el endpoint de SessionManager, propio del launcher. content (opcional): carpeta compartida a través de HTTP.

proxy_file : es el archivo que creamos para que launcher y backend de Apache se comuniquen guardando en el mapa las claves de las sesiones y puerto que utilizan. sessionURL: es la URL necesaria para comunicarse con el proceso de visualización. El backend de Apache va a reconocer esta URL y va a reescribirla para hacer el reenvío de paquetes hacia el proceso de visualización correcto a través del websocket.

timeout: es el tiempo máximo de espera cuando se intenta crear un nuevo proceso. log_dir: es el directorio donde el launcher va a guardar los logs de cada sesión. upload_dir: es la carpeta donde se guardan los archivos que los especialistas utilizan.

fields: estos campos serán filtrados al momento de generar la respuesta.

Las variables python_exec, visualizer_path y dataDir se definen para ser utilizadas posteriormente por el comando que ejecutará el launcher.

sessionData: permite agregar valores arbitrarios del tipo clave/valor que serán incluidos en la respuesta cuando se cree exitosamente una sesión para el cliente web.

resources es una lista de combinaciones host:port-range, que el launcher va a tener en cuenta al momento de asignarlas al cliente web cuando haga los pedidos. El launcher va a tomar cada host y sus puertos asociados, y va a agregarlos a una lista maestra de “recursos disponibles” como clave-valor, por ejemplo, si tenemos : [ { "host" : "localhost", "port_range" : [9001, 9103] },

{ "host" : "host1", "port_range" : [9001, 9103] } ], la lista maestra queda:

[[​"localhost"​, ​9001​], [​"localhost"​, ​9002​],

[​"localhost"​, ​9103​],

(19)

[​"host1.example.com"​, ​9103​] ]

Cuando el cliente realice una petición, el launcher va a elegir al primer recurso disponible y usarlo para atenderla. El host y el puerto elegidos, van a estar disponibles como ${host} y ${port} para ser usados en sessionURL y en app.visualizer.cmd.

Cuando el proceso asociado al cliente eventualmente termine, la combinación host:port va a estar disponible nuevamente para futuras peticiones. Hasta qué esto no suceda, esta combinación de host:port será considerada como no disponible por el launcher.

2.6 Visualización remota y archivos

Al realizar la prueba de crear 2 procesos de renderización sobre el mismo archivo, el backend falló. Este fallo fue causado por la imposibilidad del segundo proceso de leer el archivo, dado que el archivo estaba bloqueado por el primer proceso.

Esto sucede porque si un proceso está visualizando un archivo, el proceso toma control del mismo evitando que otros procesos lo lean.

Por ello, para evitar este error, al momento de visualizar un archivo, primero se verifica que exista en una tabla hash creada para ese fin. En esta tabla se almacena como clave el email del especialista y como valor una lista de archivos que el especialista está visualizando.

Si el archivo en cuestión está en la tabla, devuelve un error explicando que este archivo está siendo visualizando. En caso contrario, continúa el proceso de apertura y agrega este archivo a la lista de archivos abiertos del especialista. De esta manera se evita el error y poder seguir operando con la aplicación.

(20)

Capítulo 3: Backend Golang

En este capítulo se detalla cómo trabaja el servidor de autenticación, las estructuras que utiliza, como funciona la autenticación de los usuarios, como este administra los archivos de cada especialista y que datos se guardan en la base de datos.

El sistema debe, además de visualizar, autenticar los usuarios y administrar los archivos de los especialistas. Para ello, se decidió crear un servidor HTTP responsable de llevar a cabo estas tareas. La decisión de crear este servidor está basada en que el proceso de renderización es a través de un WebSocket entre el backend de Apache y el cliente web. A través de este WebSocket se envían muchas imágenes para la representación de las interacciones que tiene el usuario con el modelo renderizado. Agregar a este la sobrecarga de la administración de autenticación y la administración de los archivos de los especialistas, afectaría la performance de la visualización.

3.1 Tecnologías

(21)

3.2 Sistema de Archivos

Para el almacenamiento de archivos se decidió utilizar el sistema de archivos propio del sistema operativo que contenga al servidor. Dado que guardar el archivo en la base de datos es ineficiente porque MongoDB utiliza BSON para documentos que sean menores a 16MB, guardándolo en binario. Pero para archivos más grandes MongoDB tiene GridFs, que divide al archivo en pequeños pedazos de 255k (por default). Al hacer esta división con archivos de 100~150MB durante el guardado y la unión de estos pedazos al momento de lectura, atenta a la performance del proceso de renderización y a la experiencia del usuario al momento de cargar un archivo haciéndolo más lento. [62]

Entonces para organizar los archivos, se tiene una carpeta base, dentro de ésta se va a crear una carpeta con el nombre del email del especialista cuando se dé de alta un nuevo especialista.

Cada especialista tiene pacientes, cuando un especialista da de alta un paciente, se crea una carpeta con el nombre del paciente dentro de la carpeta del especialista.

Dentro de la carpeta del paciente se pueden crear nuevas carpetas y archivos. Se restringe la disposición de archivos en la carpeta raíz, ya que todos los archivos deben estar organizados en carpetas.

Todas las llamadas de altas, bajas, modificaciones o listados, son llamadas al SO, y este se encarga de realizar los controles de nombres repetidos, caracteres inválidos, etc. En caso de que se encuentre un error, este se captura y se envia el error al frontend web para poder mostrar el error en pantalla y que el usuario tome las acciones correspondientes.

3.3 Autenticación : Token JWT

(22)

Este token se guarda en el servidor en una hash clave-valor: como clave esta el email del usuario y como valor el token. Cada vez que un usuario quiera hacer uso del servidor, tiene que enviar el token en la cabecera de la petición para validar si está autenticado. De no estarlo, arroja un error de token invalido.

Este token tiene un tiempo de vencimiento de 5 minutos. En caso de que

pase este tiempo entre consultas de servicio, se arroja un error explicando qué tiene que volver a autenticarse. Éste mensaje es mostrado por el cliente web. Además el servidor elimina este token de la hash en memoria así ya no ocupa espacio.

3.4 Roles

En la creación de la herramienta web, se definieron 3 (tres) roles para los usuarios, cada uno con su funcionalidad y responsabilidades específicas. En el siguiente diagrama de casos de uso (Figura 2), se muestra cuales son los actores y cuáles son los casos de uso

(23)

El administrador tiene como principal responsabilidad las altas, bajas y modificaciones de los usuarios ya sean de categoría de especialista o categoría técnico. Dado que esta herramienta es cerrada a una comunidad específica, no tiene sentido crear una interfaz de registro manual publico.

Si un especialista o técnico quiere utilizar alguna operación, tiene que estar registrado, el proceso del registro lo lleva a cabo el administrador. En la base de datos por defecto existe un usuario del tipo administrador llamado admin con contraseña admin.

El rol especialista tiene todas las funcionalidades con los archivos de sus pacientes, dar de alta, baja, modificación y listado a sus archivos y carpetas. Además, tiene las funcionalidades de visualizar un archivo, ya sea de manera remota o de manera local.

El rol técnico tiene las funcionalidades de listar todos los especialistas y explorar todos sus archivos, además poder dar de alta nuevos archivos en alguna carpeta de algún paciente de algún especialista, descargar los archivos de los especialistas y hacer el procesamiento correspondiente. Una vez que este procesamiento está realizado, puede subir el resultado a la carpeta del especialista. Tiene la peculiaridad de no tener permitido modificar o dar de baja un archivo, solo de crear nuevos.

Previamente a poder utilizar las funcionalidades de la herramienta, cada uno de los usuarios tiene que estar registrado en el sistema y autenticado (Figura 2). Estas son las principales responsabilidades de cada rol, en los siguientes apartados, se van a detallar como esta implementado ya sea en la parte del frontend o del

(24)

3.5 Arquitectura y Servicios

Figura 3 - Arquitectura Backend Golang

El cliente web hace todas las peticiones hacia el backend Golang (Figura 3), y todas las respuestas de este servidor son objetos JSON, este objeto contiene el resultado de la operación mostrando un código definido en la RFC2616, un mensaje en un string un result qué es el resultado de la operación. [64]

El cliente web tiene que estar autenticado para poder interactuar con las diferentes servicios, esta autentificación se realiza mediante el siguiente llamado:

Endpoint : /login Method : POST

Headers: Content-Type : application/json Body : {

email: email1@gmail.com,

password : ​1234

}

Este servicio realiza las siguientes validaciones: ● El email tiene que existir en la base de datos.

● El email y la contraseña tienen que ser iguales a los que están guardados en la base de datos.

(25)

Para verificar si el usuario ya tiene una sesión activa, se utiliza una caché en memoria, cada vez que un usuario se autentica correctamente, se guarda en esta caché clave-valor el email del usuario y como valor un objeto que contiene el token y el tiempo desde que se inició la sesión.

Si estas condiciones se cumplen, la llamada al servicio de /login devuelve el token para poder interactuar con los diferentes servicios.

Para terminar de utilizar la herramienta y desautenticar, se debe llamar al siguiente servicio :

Endpoint : /logout Method : POST

Headers: Content-Type : application/json Body : {

token : {{token}} }

Este servicio remueve el token correspondiente de la caché de usuarios logueados.

A continuación se detallarán los diferentes servicios implementados para cada rol de la aplicación. Para simplificar, el valor {{token}} es el resultado de la autenticación de un usuario que se pasa a través del cuerpo de cada llamado.

En los siguientes servicios, se verifica: ● El token es válido

● El tiempo de uso que no esté vencido

● Los valores que se pasan no esten vacios o sean nulos

Si la petición se resuelve correctamente, se refresca el tiempo de uso del token por 5 minutos más.

3.5.1 Servicios administrador

(26)

Endpoint : /admin/add/user Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}}

email : email2@gmail.com password : 123456

category : 0 }

Este servicio es utilizado para crear un nuevo usuario dentro de la herramienta. En el cuerpo se especifican los valores de email, password y categoría. El número de la categoría hace referencia a 0 si es un especialista ó 1 si es un técnico.

Se realiza la validación que el email no esté previamente utilizado en la base de datos.

En caso de que sea un usuario nuevo del tipo especialista, se crea en el sistema de archivos la carpeta correspondiente para que este pueda subir sus pacientes y archivos a renderizar.

Además en la base de datos se guarda la categoria, email y password del nuevo usuario. A esta última se le aplica un SHA256 para que en el caso de que la base sea vulnerada, la contraseña no sea visible.

Endpoint : /admin/delete/user Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}}

email : email1@gmail.com }

(27)

En caso de que este usuario está autenticado en el sistema, se borra de la caché su entrada para no seguir permitiendo el uso. Además si el especialista tenía archivos abiertos, también se quita su entrada de la caché en memoria, para evitar consumir memoria innecesaria.

Endpoint : /admin/edit/user Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}}

oldemail : email1@gmail.com newemail : email3@gmail.com newpassword: asd

newcategory: 0 }

Este servicio permite editar a un cliente, para cambiar el email se utilizan las variables oldemail y newemail, se realizan las validaciones que el oldemail

exista y el newemail no exista en la base de datos para poder cambiarlo. Además si el usuario que se quiere editar es de tipo especialista, se renombra la carpeta en el sistema de archivos para que quede consistente con el cambio.

Para el cambio de categoría, en caso de que un usuario que tenía la categoría especialista pase a ser tecnico, a este se le borra la carpeta creada en el sistema de archivos. Para el caso contrario, qué un técnico pase a ser especialista, se crea la carpeta en el sistema de archivos. En ambos casos se actualiza la categoría en la base de datos para que el cambio quede consistente.

(28)

Endpoint : /admin/view/users Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}} }

Este servicio devuelve todos los usuario del sistema, que sean de tipo especialista o técnico. Se utiliza para la presentación de todos los usuarios y que el administrador pueda crear, borrar o editar más usuarios.

3.5.2 Servicios en común especialista y técnico

Los siguientes servicios pueden ser utilizadas por especialistas o técnicos (Figura 2), dado que ambos tienen las mismas necesidades. Al momento de controlar el token, se verifica que la categoría sea de un especialista o de un técnico.

Si es un técnico el que utiliza el servicio, es requisito que envíe a qué especialista se le está aplicando el servicio, sino no hay manera de distinguir al especialista. En caso de que sea un especialista el que utiliza el servicio, del token se puede obtener el email del mismo para armar la ruta de los archivos sin más complicaciones.

Endpoint : /add/folder Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}} folder : paciente1 }

(29)

email@especialista1.com/paciente1​. Esta no es una entrada válida si lo utiliza un técnico, la variable folder tiene que tener la siguiente forma email@especialista1/paciente1/subcarpeta1​. Dado que un técnico no puede crearle nuevos pacientes a los especialistas, debe ser siempre una subcarpeta. Se asume que cada especialista solo puede tener un paciente con un único nombre, además se realiza este control para no tener errores con el sistema de archivos.

Endpoint : /delete/folder Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}} folder : paciente1 }

Este servicio es utilizado para borrar las carpetas. Si un especialista utiliza este servicio y desea eliminar un paciente, tiene que enviar el nombre de la carpeta en la variable folder, en el ejemplo de arriba estaríamos eliminando la carpeta especialista1@gmail.com/paciente1 del sistema de archivos. En caso de que se quiera eliminar una subcarpeta del paciente1, se tiene que aclarar en folder ejemplo: paciente1/ejemplo1​.

Para el técnico, la variable folder tiene que tener la siguiente forma folder:especialista1@gmail.com/paciente1/ejemplo1 especificando el email del especialista y la subcarpeta que desea eliminar.Antes de la eliminación se realiza una validación de que no se esté visualizando ningun archivo dentro de esa carpeta, dado que sino el backend de Apache podría tener errores al intentar leer un archivo que no existe más.

(30)

Endpoint : /rename/folder Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}} oldfolder : paciente1 newfolder : paciente3 }

Este servicio es utilizado para renombrar una carpeta. Toma el nombre actual deoldfolder y lo renombra pornewfolder. Se realiza una validación de que newfolder no exista previamente en el mismo directorio y que no exista ningún archivo actualmente visualizado por el especialista dentro de esta ruta, dado que sino el

backend de Apache va a tener problemas al intentar leer un archivo inexistente.

Para el caso del especialista, dentro de su carpeta paciente1 pasa a llamarse paciente3​. En caso de que el especialista quiera renombrar una subcarpeta, tiene que enviarla en oldfolder como paciente1/subcarpeta1 y en newfolder el nuevo nombre paciente1/nuevonombre2​. Para el caso del técnico, el ejemplo anterior no es válido, dado que un técnico no puede cambiarle el nombre a un paciente. Tiene que enviar una subcarpeta de un paciente, con el email del especialista al cual le estaría cambiando el nombre. Por ejemplo, en oldfolder:​especialista1@gmail.com​/paciente1/subcarpeta1 y en newfolder:especialista1@gmail.com/paciente1/subcarpeta2

Endpoint : /rename/file Method : POST

Headers: {

Content-Type : application/json Body : {

(31)

Este servicio sirve para renombrar un archivo, el nombre de la carpeta que contiene el archivo viene en la variable folder. Antes de renombrarlo se realizan las siguientes validaciones: la carpeta tiene que existir, el nombre del archivo tiene que existir en la carpeta y el nuevo nombre del archivo no tiene que existir en la carpeta. Además se verifica que este archivo no se esté visualizando, dado que sino

el backend de Apache va a tener problemas visualizando un archivo que no existe

más. Para el caso del especialista el renombre es directo, el paciente1/nombreviejo se renombra por ​paciente1/nombrenuevo​. En el caso del técnico, en la variable folder tiene que especificar a qué especialista hace

referencia para aplicarle el servicio de renombre ejemplo:

folder:especialista1@gmail.com/paciente1

Endpoint : /add/file Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}} folder : paciente1 file : bitecode }

Este servicio se utiliza para agregar un archivo a una carpeta. Para el caso del especialista, se envía en folder el nombre de la carpeta directamente, pero para el técnico , se tiene que especificar a qué especialista se le está subiendo el archivo,

entonces en folder tiene que tener la siguiente forma

especialista1@gmail.com/paciente​.

De la variable file se obtiene el nombre del archivo y en el cuerpo también se adjunta el bytecode del archivo en cuestión, primero se valida que el nuevo archivo no exista en la carpeta que se quiere agregar, luego se hace la decodificación del bytecode a un objeto File para luego guardarlo en el sistema de archivos.

(32)

Endpoint : /delete/file Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}} folder : paciente1 file : nombrefile }

Este servicio es utilizado para borrar archivos. Para el caso del especialista, la variable folder es la carpeta actual del archivo que se quiere eliminar y en file el nombre del archivo, pero el técnico debe especificar en la variable folder a que

especialista corresponde la eliminación

folder:especialista1@gmail.com/paciente1​.

Se realiza la validación de que efectivamente este archivo exista y que además no se esté visualizando para evitar tener problemas con el backend de Apache al intentar leer un archivo inexistente. Para ambos casos, si se quiere eliminar un archivo de una subcarpeta tiene que enviar en folder paciente1/subcarpeta1​. Esta operación no tiene vuelta atrás.

3.5.3 Servicios Especialista

Los siguientes servicios solo los puede utilizar alguien qué es un especialista Endpoint : /specialist/get/files

Method : POST Headers: {

Content-Type : application/json Body : {

token : {{token}} }

(33)

El JSON es el siguiente : {

folder: ​"especialista1@gmail.com"

subfolders:[{ ...

}]

files : [​"file1"​,​"file2"​¨]

}

Este objeto se utiliza en el frontendcomo base para realizar la navegación en la pantalla del especialista sin estar constantemente pidiéndole al backend carpeta por carpeta.

Endpoint : /specialist/open/file Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}} file : archivo1 folder : carpeta1 }

Este servicio es utilizado para abrir un archivo. Se controla que el archivo no esté previamente abierto, chequeando en la caché de archivos abiertos por especialista, además se controla que el archivo exista. Si el especialista no tiene ningun archivo previamente abierto, se genera la entrada en la cache con este archivo.

Endpoint : /specialist/open/file Method : POST

Headers: {

Content-Type : application/json Body : {

(34)

Este servicio es utilizado para cerrar un archivo. Se valida que el archivo esté previamente abierto, controlando en la caché si figura o no, además que el archivo que se quiera cerrar exista. Si cumple todas las validaciones, se remueve de la caché la entrada correspondiente al archivo que nos pasan por file.

3.5.4 Servicios Técnico

Los siguientes servicios solo lo puede utilizar un usuario con la categoría de técnico

Endpoint : /technician/search/files Method : POST

Headers: {

Content-Type : application/json Body : {

token : {{token}}

emails : [especialista1@gmail.com] }

Este servicio es utilizado para obtener todos los archivos de ciertos especialistas. En el parámetro emails, si se envía como en el ejemplo con algún especialista, solo va a traer los archivos de los especialistas elegidos. En cambio, si se envía vacío, se van a devolver todas las carpetas y archivos de todos los especialistas. El resultado se pone en un objeto JSON

{ {

folder: ​"especialista1@gmail.com"

subfolders:[{ ...

}]

files : [​"file1"​,​"file2"​¨]

(35)

Es similar al servicio de los especialistas para obtener las carpetas, pero en vez de un solo especialista, va por un grupo de especialistas.

Capítulo 4: Frontend web

En este capítulo se describe toda la funcionalidad disponible del frontend web y las tecnologías que se utilizaron para desarrollarlo (React [65], Redux [66], Npm [67], Webpack [68], Vtk.js [69]), cuales son las operaciones que pueden realizar los 3 tipos de roles en la aplicación, específicamente: administrador, especialista y técnico.

El frontend es la cara de la herramienta web. Presenta toda la funcionalidad detallada anteriormente en el backend de Golang [70] de una manera visualmente agradable para todos los tipos de usuarios. Se tomó la decisión de utilizar React dado que el framework ParaViewWeb, que es utilizado para el render, se encuentra desarrollado con esta tecnología.

Para la administración de paquetes se decidió utilizar NPM. Esta decisión está basada en lo mismo que el punto anterior, el framework ParaViewWeb se encuentra disponible a través de este administrador de paquetes. Para hacer las llamadas al servidor de Golang se utilizó Axios [71].Esta es una librería que permite hacer request HTTP asincronicas, devolviendo una Promesa Javascript.

Para tener un diseño web visualmente aceptable se decidió utilizar el

framework Bootstrap [72] desarrollado por Twitter que permite crear de forma

sencilla aplicaciones web con diseños adaptables a la pantalla del usuario, es decir, que se ajusten a cualquier dispositivo y tamaño de pantalla para que siempre se vea bien.

Cuando se tiene un proyecto conNPMque es por dependencias de módulos, al momento de despliegue se necesitan tener todas las dependencias de los módulos que la aplicación web utiliza, y a su vez, las dependencias de estas y asi en cadena, esto hace muy pesada a la aplicación web.

(36)

módulos bajo demanda,entre otras) qué hace a la aplicación más manejable al momento de hacer un despliegue en producción.

Para la parte de visualización remota se utilizó el framework de ParaViewWeb. Se comenzó a construir la aplicación en base a los diferentes componentes que este brinda. Con el avance de la utilización de este framework haciendo pruebas de conceptos, buscando en la documentación, e implementando en el frontend, se encontró una herramienta ya desarrollada por Kitware similar a la que se estaba construyendo.

Se descartó la parte desarrollada para la visualización remota y se integró la herramienta Visualizer que cuenta con muchas más características y funcionalidades de las que se hubieran podido desarrollar. Para la parte de visualización local, se pudo implementar gracias a las librerías que proporciona

VTK.js, estas librerías son la base de ParaViewWeb, pudiendo renderizar de

manera local los archivos con extensión .stl.

4.1 Arquitectura Web

Al utilizar la librería de React, todo lo que se muestra en la web es un componente. La desventaja de esto es que el estado de la aplicación se tiene que replicar en varios componentes.

(37)

Figura 4 - Arquitectura MVC Redux Redux tiene 3 conceptos principales :

● Proveer una única fuente de datos para el estado de la aplicación ● Asegurar que el estado de la aplicación sea read-only y si se requiere

un cambio, se tiene que hacer emitir alguna acción

● Mantener un árbol de transformaciones basadas en las acciones mencionadas anteriormente

Estos conceptos son realizados a través de los conceptos de store,reducer y actions (Figura 4). El store mantiene el estado de la aplicación.

Si quisiéramos usar datos del store, los leemos a través de la interfaz que provee el store. Si quisiéramos cambiar el estado de la aplicación, tenemos que despachar una acción sobre el store para disparar el cambio. Si quisiéramos ser notificados cuando un cambio ocurra, nos suscribimos al store a través de una función listener.

El reducer es una función que realiza la transformación de estados. Para

crear un store, primero necesitamos describir un reducer. Losreducerson funciones que toman el arbol de estados y los transforman dependiendo de la acción despachada hacia el store. El reducer no necesariamente cambia el estado para todas las acciones, pero siempre responde una estado por más que no haya cambios.

(38)

información adicional que puede afectar la manera que el reducer transforma el estado.

La manera en que funciona es la siguiente:

● Una acción es despachada hacia el store disparada desde la vista ● El store recibe la acción y se la pasa al reducer, junto con el estado

actual.

● El reducer lleva a cabo la transformación del estado teniendo en

cuenta el actionType y devuelve una nueva copia del estado.

● El store toma el nuevo estado y lo establece como el estado de la aplicación. Todos los suscritos a este cambio son notificados.

● Los suscriptores actualizan la vista de acuerdo a los cambios, habilitando o no nuevas acciones a despachar.

A continuación se detallan todas las acciones que se utilizan para administrar el estado del frontend de la herramienta web.

4.2 Acciones

Las acciones del administrador, especialista y técnico se encargan de consumir los servicios que están definidos en los incisos 3.5.1, 3.5.2, 3.5.3 y 3.5.4 obteniendo la respuesta del servidor y actualizando el estado actual.

Lo interesante es como el frontend web hace con estas respuestas:

● Para la parte de la autenticación, se tiene la acción setCurrentUser(user) que establece en el ​store el usuario que se autenticó, para así poder acceder al email desde cualquier parte de la aplicación.

(39)

usuario técnico o especialista está navegando en la herramienta. El objeto level contiene la información de carpetas, archivos, ruta y profundidad, esta última se usa para validaciones de qué botones mostrar según el rol autenticado y la profundidad actual.

● Al momento de realizar una acción, la herramienta notifica por medio de un mensaje flash que aparece en el tope de la misma, informando el resultado de la operación. Para esto se tiene 2 acciones, addFlashMessage(message) qué agrega un mensaje a la lista de mensajes con un id. Cuando hace click en la cruz del mensaje se despacha la acción deleteFlashMessage(id) que elimina un mensaje de la cola a través del id.

● Para mostrar al usuario que una acción se está llevando a cabo, la acción setSpinnerState(bool) muestra o oculta un símbolo de espera.

4.3 Autorizaciones

Por cuestiones de seguridad, un usuario del tipo técnico solo puede acceder a los servicios propios de él. En caso de intentar acceder a los servicios del especialista será rechazado y se retornará a la pantalla de login explicando qué tiene que autenticarse con el rol del especialista en una notificación. Este comportamiento se repite para todos los roles, solo pueden acceder a sus propios servicios.

Para realizar este control, se crearon las acciones authenticateAdmin authenticateTechnician y ​authenticateSpecialist qué utilizan el patrón

wrapper, por parámetro se pasan las páginas y formularios que se desean proteger

y se realizan las validaciones correspondientes controlando la categoría de cada usuario presente en el token.

4.4 Roles

(40)

el tipo de cliente que se está utilizando para facilitar las acciones que el usuario requiere.

Para todas las acciones posibles en el frontend que los diferentes roles puedan realizar, siempre se realizan validaciones sobre las mismas ( EJ: nombres repetidos, caracteres inválidos, nombres vacíos). Cuando una verificación falla, se muestra un mensaje de error con la descripción del mismo, para que el usuario tome la acción correctiva correspondiente y pueda continuar utilizando la herramienta. Estas validaciones dan una respuesta rápida de posibles inconvenientes al usuario y facilitan el correcto uso del sistema.

En caso que las validaciones se cumplan, se realiza la petición al backend. En caso que la respuesta de la petición sea correcta, se cierra la pantalla y se continua donde estaba. En caso de que sea una acción crítica como eliminar un elemento, se muestra también un mensaje de notificación en la parte central superior de la pantalla informando que la operación fue exitosa.

En caso que la petición haya fallado, se informa al usuario sobre el error por el mismo sistema de notificaciones para que pueda aplicar las acciones correctivas correspondientes y seguir utilizando la herramienta.

Este tratamiento de errores sirve de guía al usuario no experimentado. Mejora la experiencia dentro del sistema y aportan al requerimiento no funcional de la usabilidad.

4.4.1 Rol Administrador

Un administrador autenticado en la aplicación observa en la pantalla 2 botones (Figura 5), estos le dan la posibilidad de listar todos los usuarios o de agregar uno nuevo.

(41)

En la lista de todos los usuarios del sistema, al hacer clic derecho (Figura 6) sobre cada uno podemos editarlos o eliminarlos. Además, hay un botón para agregar un nuevo usuario.

Figura 6 - Menú Contextual Administrador

Al hacer click sobre el botón de agregar un nuevo usuario, se va abre una ventana (Figura 7) donde se pueden ingresar los datos del usuario a crear: el email, la contraseña y la categoría. La última es especialista por defecto.

(42)

Al momento de eliminar el usuario (Figura 9), se nos va a pedir una confirmación de si esta seguro que desea realizar esta acción, en caso afirmativo se envía una petición irreversible al servidor de backend.

Figura 9 - Eliminar un usuario

En el botón de agregar un usuario nuevo, nos va a llevar a la misma interfaz que el botón anteriormente descrito (Figura 7 ). Se puede acceder a esta sección desde varios lugares para facilitar y es la principal tarea del administrador (agregar usuarios) brindando una experiencia de usuario más ágil y reutilizando la misma interfaz para que el código sea mantenible.

4.4.2 Rol Especialista

(43)

Este botón nos permite agregar pacientes. Al hacer click, abre una pantalla (Figura 11) donde tenemos que ingresar el nombre del paciente y hacer click en el botón “Add” para finalizar la creación. Tanto el botón “ Cancel” como la cruz superior izquierda, cierre esta pantalla.

Una vez creado el paciente, haciendo click derecho sobre el mismo podemos seguir creando pacientes, renombrar al paciente seleccionado, o eliminar al paciente seleccionado.

(44)

La acción “Delete” nos va a abrir una nueva ventana (Figura 13) y nos va a pedir una confirmación sobre la acción que estamos realizando.

Figura 13 - Eliminar paciente

Si hacemos click en “Confirm” va a borrar al paciente , si se hace click en la cruz derecha superior, esta ventana se cierra sin cambios.

Al momento de agregar o editar un paciente, se realizan las siguientes validaciones:

● El paciente no puede tener un nombre vacío.

● El paciente solo puede tener caracteres en minúscula, caracteres en mayúscula, espacios y números.

● Los nombres de los pacientes son únicos, no pueden existir 2 pacientes con el mismo nombre.

Todas estas validaciones se realizan para evitar el uso de la red, en caso de cumplirlas se hace una petición al servidor para llevar a cabo la acción requerida.

Para acceder a los archivos del paciente, tenemos que hacer click izquierdo sobre él. Ésto nos va a mostrar 3 nuevas acciones disponibles (Figura 14).

(45)

Al hacer click en el botón “ Add File” nos va a permitir subir un archivo en la carpeta en la cual estamos parados y nos va a abrir la siguiente ventana (Figura 15)

Figura 15 - Agregar un archivo

Haciendo click en el botón “ Choose File” elegimos el archivo de nuestra pc para subir. Al hacer click en “Add” se va a subir al backend de Golang el archivo, mientras se realiza este proceso se muestra un spinner qué está cargando. Antes de utilizar el servicio del backend de Golang, se realizan las siguientes validaciones :

● No puede haber 2 archivos con exactamente el mismo nombre. ● Solo se pueden subir archivos con la extensión .vtk

● No se puede subir un archivo vacío al servidor .

Al hacer clic derecho sobre los archivos tienen 4 acciones posibles: “ Render”, “Rename”, “Download” y “Delete”.

(46)

Figura 16 - Editar un archivo

Cuando se hace clic en “Rename” se abre una venta con el nombre de archivo sin la extensión (Figura 16). Esto es para que el tipo de archivo sea transparente para el usuario final.. Una modificación accidental de la extensión podría producir un fallo a futuro, dado que el renderizador hace un chequeo de la extensión. En caso de que la extensión no sea válida, el renderizador va a fallar. Al presionar el botón “ Render”, nos va a aparecer un spinner que la herramienta Visualizer indica que está cargando. La pantalla se mantiene mientras se está inicializando todo el proceso para la visualización.

Figura 17 - Cargando Visualizer

(47)

Al abrir la herramienta nos dirigimos a la pestaña de documentos (Figura 18), ahí figura las carpetas de los pacientes, al hacer clic en la carpeta entramos en ella y al hacer clic en el archivo que queremos visualizar (Figura 19), va a empezar la carga del archivo, esto puede demorar dependiendo del tamaño.

Figura 18 - Lobby Visualizer

(48)

Figura 20 - Herramientas Visualizer

En caso de que el servidor remoto de visualización no responda, esta la opción de visualización local, está se encuentra ni bien se entra en la pantalla de logueo (Figura 21).

(49)

Ambos nos van a llevar a la pantalla de visualización local donde tenemos que elegir un archivo (Figura 22).

Figura 22 - Eleccion de archivo local

Solo se aceptan archivo con extensión .stl. Una vez elegido el archivo, va a empezar a cargarlo, mostrándonos un spinner.

Cuando finaliza, nos muestra la figura cargada (Figura 23), pero como es una visualización local carece de features para manipular el modelo.

Solo se puede hacer zoom in/out con la rueda del ratón y controlar al modelo con el click izquierdo moviendolo en la dirección que querramos.

(50)

4.4.3 Rol Técnico

Cuando un usuario técnico ingresa a la herramienta, se muestran un listado que contiene a todos los especialistas (Figura 24).

Figura 24 - Lista de especialistas

Para ingresar en los archivos de los especialistas, tiene que hacer clic izquierdo en un especialista (Figura 24) y este nos va a mostrar un listado de sus pacientes (Figura 25).

Figura 25 - Pacientes especialista

Referencias

Documento similar

De acuerdo con Harold Bloom en The Anxiety of Influence (1973), el Libro de buen amor reescribe (y modifica) el Pamphihis, pero el Pamphilus era también una reescritura y

entorno algoritmo.

Habiendo organizado un movimiento revolucionario en Valencia a principios de 1929 y persistido en las reuniones conspirativo-constitucionalistas desde entonces —cierto que a aquellas

In medicinal products containing more than one manufactured item (e.g., contraceptive having different strengths and fixed dose combination as part of the same medicinal

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in

This section provides guidance with examples on encoding medicinal product packaging information, together with the relationship between Pack Size, Package Item (container)

Package Item (Container) Type : Vial (100000073563) Quantity Operator: equal to (100000000049) Package Item (Container) Quantity : 1 Material : Glass type I (200000003204)