scieee AI-readable full text Open interactive document viewer

Diseño interactivo de interfaces gráficas de usuario para Progress

Caballero Sánchez, Ricardo; Díaz Jiménez, Adrián

Abstract

Este proyecto se centra en la creación de una aplicación de escritorio que, mediante tecnologías web, nos permite crear, de manera visual, interfaces gráficas. El proyecto nace de la necesidad de crear interfaces gráficas con un lenguaje que no está muy preparado para ello: Progress. Progress es un lenguaje de programación utilizado para el mantenimiento y uso de bases de datos. Es por ello que la creación de la capa visual con este lenguaje es una tarea tediosa y el resultado es difícil de mantener. En este proyecto hemos desarrollado un programa que nos permite elegir una serie de características que tendrá la interfaz y las variables mostradas en ella con el objetivo de generar el código Progress correspondiente. Además, se crean los componentes visuales que pueden ser arrastrados y movidos a la zona de la pantalla donde finalmente se verán al ejecutar el código Progress. De esta forma, se simplifica mucho la elaboración y modificación de estas pantallas, viendo en todo momento el resultado visual final que tendrá este código al ser ejecutado. También nos permite ver en tiempo real el código Progress que se genera automáticamente con cada acción y guardar este código en un fichero. Los ficheros que se generan con la aplicación pueden ser cargados de nuevo para realizar modificaciones. Enlace a proyecto GitHub.

Full text

DISEÑO INTERACTIVO DE INTERFACES GRÁFICAS DE USUARIO PARA PROGRESS Ricardo Caballero Sánchez Adrián Díaz Jiménez GRADO EN INGENIERÍA INFORMÁTICA GRADO EN INGENIERÍA DEL SOFTWARE FACULTAD DE INFORMÁTICA UNIVERSIDAD COMPLUTENSE DE MADRID TRABAJO DE FIN DE GRADO Director: Manuel Montenegro Montes Diseño interactivo de interfaces gráficas de usuario para Progress 2/75 A nuestros familiares, amigos y compañeros de universidad y trabajo por su interés y apoyo constante Diseño interactivo de interfaces gráficas de usuario para Progress 3/75 Contenido RESUMEN ............................................................................................................................................... 8 PALABRAS CLAVE ....................................................................................................................................... 8 ABSTRACT ............................................................................................................................................. 9 KEYWORDS ................................................................................................................................................ 9 CAPITULO 1.- INTRODUCCIÓN ....................................................................................................... 10 1.1.- ANTECEDENTES Y MOTIVACIÓN ..................................................................................................... 10 1.2.- OBJETIVOS .................................................................................................................................. 10 1.3.- PLAN DE TRABAJO ....................................................................................................................... 11 CAPITULO 2.- INTRODUCTION ........................................................................................................ 13 2.1.- BACKGROUND AND MOTIVATION .................................................................................................... 13 2.2.- GOALS ........................................................................................................................................ 13 2.3.- WORKING PLAN ........................................................................................................................... 14 CAPITULO 3.- TECNOLOGÍAS ......................................................................................................... 16 3.1.- ELECTRON .................................................................................................................................. 16 3.1.1.- Node.js ......................................................................................................................... 16 3.1.2.- Chromium ..................................................................................................................... 17 3.1.3.- Estructura Electron.JS .................................................................................................. 17 3.2.- PEG.JS ..................................................................................................................................... 17 3.3.- VISUAL STUDIO CODE .................................................................................................................. 18 3.4.- GITHUB ...................................................................................................................................... 18 3.5.- LENGUAJE DE PROGRAMACIÓN JAVASCRIPT .................................................................................. 18 3.6.- FRAMEWORK PARA LA CAPA DE PRESENTACIÓN JQUERY ................................................................. 18 3.7.- CAPA DE PRESENTACIÓN.............................................................................................................. 19 3.7.1.- HTML5 ......................................................................................................................... 19 3.7.2.- CSS .............................................................................................................................. 19 3.7.3.- Bootstrap ...................................................................................................................... 19 Diseño interactivo de interfaces gráficas de usuario para Progress 4/75 3.7.4.- jQuery UI ...................................................................................................................... 19 3.7.5.- Interact.JS .................................................................................................................... 20 CAPITULO 4.- CREACIÓN DE INTERFACES DE USUARIO ........................................................... 21 4.1.- FORMULARIOS ............................................................................................................................. 21 4.1.1.- Frames ......................................................................................................................... 21 4.1.2.- Variables ...................................................................................................................... 21 4.1.3.- Formulario de Frame .................................................................................................... 22 4.1.4.- Formulario de Variable ................................................................................................. 23 4.2.- FRAME DE ENTRADA .................................................................................................................... 24 4.2.1.- Zonas principales ......................................................................................................... 24 4.2.2.- Posicionamiento de Variables ...................................................................................... 25 4.2.3.- Modificación de variables ............................................................................................. 32 4.2.4.- Elementos del Frame. .................................................................................................. 33 4.2.5.- Código generado .......................................................................................................... 34 4.3.- FRAME DE SALIDA ........................................................................................................................ 35 4.4.- VISTA DE CÓDIGO ........................................................................................................................ 37 CAPITULO 5.- GENERACIÓN Y ANÁLISIS SINTÁCTICO DE CÓDIGO PROGRESS .................... 38 5.1.- ESTRUCTURA DE DATOS EN JAVASCRIPT ....................................................................................... 38 5.1.1.- Clase Progress ............................................................................................................. 38 5.1.2.- Clase Frame ................................................................................................................. 40 5.1.3.- Clase Variable .............................................................................................................. 43 5.2.- ESTRUCTURA DE DATOS EN PROGRESS ......................................................................................... 46 5.2.1.- Generación de código Progress ................................................................................... 46 5.3.- ANALIZADOR SINTÁCTICO DE PROGRESS ........................................................................................ 48 5.3.1.- Gramática y Semántica de PEG.js ............................................................................... 48 5.3.2.- Reglas utilizadas .......................................................................................................... 50 CAPITULO 6.- OTRAS FUNCIONALIDADES ................................................................................... 52 Diseño interactivo de interfaces gráficas de usuario para Progress 5/75 6.1.- VALIDACIÓN DE DATOS ................................................................................................................. 52 6.1.1.- Validación de datos en la creación de código. ............................................................. 52 6.1.2.- Validación de datos en la carga de archivo. ................................................................. 56 6.1.3.- Mensajes de Validación de Datos: ............................................................................... 59 CAPITULO 7.- CONCLUSIONES Y TRABAJO FUTURO ................................................................. 61 7.1.- CUMPLIMIENTO DE OBJETIVOS ...................................................................................................... 61 7.2.- DIFICULTADES ENCONTRADAS ....................................................................................................... 62 7.3.- TRABAJO FUTURO. ....................................................................................................................... 63 7.3.1.- Ampliación de tipos. ..................................................................................................... 63 7.3.2.- Efectos visuales. .......................................................................................................... 64 7.3.3.- Alineaciones por defecto. ............................................................................................. 64 7.3.4.- Añadir rejilla.................................................................................................................. 64 7.3.5.- Ordenar visualización de frames. ................................................................................. 64 7.3.6.- Ampliar características del frame. ................................................................................ 64 7.3.7.- Ampliación de lectura de documentos. ......................................................................... 64 7.3.8.- Vista simulada del frame de salida. .............................................................................. 64 CAPITULO 8.- CONCLUSIONS AND FUTURE WORK .................................................................... 65 8.1.- ACHIEVEMENT OF GOALS .............................................................................................................. 65 8.2.- DIFFICULTIES ENCOUNTERED ........................................................................................................ 66 8.3.- FUTURE WORK............................................................................................................................. 67 8.3.1.- Type extension ............................................................................................................. 67 8.3.2.- Visual effects ................................................................................................................ 67 8.3.3.- Default alignments ........................................................................................................ 67 8.3.4.- Add grid ........................................................................................................................ 67 8.3.5.- Order display of frames ................................................................................................ 67 8.3.6.- Expand characteristics of the frame ............................................................................. 68 8.3.7.- Extension of document reading .................................................................................... 68 Diseño interactivo de interfaces gráficas de usuario para Progress 6/75 8.3.8.- Simulated view of the output frame .............................................................................. 68 CAPITULO 9.- CONTRIBUCIONES DE CADA PARTICIPANTE ...................................................... 69 9.1.- CONTRIBUCIÓN RICARDO CABALLERO SÁNCHEZ ............................................................................ 69 9.2.- CONTRIBUCIÓN ADRIÁN DÍAZ JIMÉNEZ ........................................................................................... 72 BIBLIOGRAFÍA ..................................................................................................................................... 75 Diseño interactivo de interfaces gráficas de usuario para Progress 7/75 Tabla de ilustraciones 1.-Estructura Electron.js [11] .................................................................................................................. 17 2.- Formulario de Frame ........................................................................................................................ 23 3.- Formulario de Variable ...................................................................................................................... 24 4.-Vista del frame de entrada ................................................................................................................. 25 5.-Frame de entrada – Paso 1 ............................................................................................................... 26 6.- Frame de entrada – Paso 2 .............................................................................................................. 27 7.- Frame de entrada – Paso 3 .............................................................................................................. 28 8.- Panel visualización de variable ......................................................................................................... 32 9.- Zona 4 ( Elementos del Frame) ........................................................................................................ 33 10.- Ventana Editar Frame ..................................................................................................................... 33 11.- Vista Update ................................................................................................................................... 34 12.- Vista Display ................................................................................................................................... 34 13.-QAD ................................................................................................................................................. 35 14.- Ejemplo Frame de Salida ................................................................................................................ 36 15.- Vista de Código............................................................................................................................... 37 Diseño interactivo de interfaces gráficas de usuario para Progress 8/75 RESUMEN Este proyecto se centra en la creación de una aplicación de escritorio que, mediante tecnologías web, nos permite crear, de manera visual, interfaces gráficas. El proyecto nace de la necesidad de crear interfaces gráficas con un lenguaje que no está muy preparado para ello: Progress. Progress es un lenguaje de programación utilizado para el mantenimiento y uso de bases de datos. Es por ello que la creación de la capa visual con este lenguaje es una tarea tediosa y el resultado es difícil de mantener. En este proyecto hemos desarrollado un programa que nos permite elegir una serie de características que tendrá la interfaz y las variables mostradas en ella con el objetivo de generar el código Progress correspondiente. Además, se crean los componentes visuales que pueden ser arrastrados y movidos a la zona de la pantalla donde finalmente se verán al ejecutar el código Progress. De esta forma, se simplifica mucho la elaboración y modificación de estas pantallas, viendo en todo momento el resultado visual final que tendrá este código al ser ejecutado. También nos permite ver en tiempo real el código Progress que se genera automáticamente con cada acción y guardar este código en un fichero. Los ficheros que se generan con la aplicación pueden ser cargados de nuevo para realizar modificaciones. Enlace a proyecto GitHub. PALABRAS CLAVE Progress, frames, variable, temp-table, interfaz gráfica, Electron, Interact.JS, analizador sintáctico, PEG.JS. Diseño interactivo de interfaces gráficas de usuario para Progress 9/75 ABSTRACT This project is focused on the creation of a desktop application that, using web technologies, allows us to create graphical interfaces in a visual way. The project is born from the need to create graphical interfaces with a language that is not prepared for it, Progress. Progress is a programming language used for the maintenance and use of databases. That is why the creation of the visual layer with this language is a tedious task, and the resulting views are difficult to maintain. In this project we have developed a program that allows us to choose a series of properties in the interface and a series of variables shown in it in order to generate the corresponding Progress code. Additionally, visual components created can be dragged and moved to the area of the screen where they will finally be displayed when the corresponding Progress code is run. In this way, this tool greatly simplifies the elaboration of these screens and allows us to modify them quickly, and to see at all times the final visual result this code will have when executed. It also allows us to see in real time the Progress code that is automatically generated with each action and save this code in a file. The files that have been generated with the application can be reloaded to make modifications. Link to GitHub project. KEYWORDS Progress, frames, variable, temp-table, graphical user interface, Electron, Interact.JS, parser, PEG.JS Diseño interactivo de interfaces gráficas de usuario para Progress 16/75 CAPITULO 3.- TECNOLOGÍAS Actualmente existen Frameworks para crear aplicaciones de escritorio, en las que se puede usar las tecnologías web conocidas, tales como HTML5, JavaScript, CSS, JSON entre otros. Como ejemplo de aplicaciones de escritorio realizadas mediante tecnologías web, podemos mencionar Avast y Nod32. Al usar este tipo de desarrollo se nos brinda la facilidad de crear interfaces gráficas con mucha más facilidad ya que podemos reutilizar nuestros conocimientos de HTML y CSS, cosa que con otros Frameworks de aplicaciones de escritorio podría resultar mucho más trabajoso y complicado. Por esta razón, nuestro proyecto se ha desarrollado con muchas de estas herramientas, las cuales mencionaremos a continuación, todas ellas relacionadas con tecnologías web. 3.1.- ELECTRON Para llevar a cabo nuestro proyecto, nos hemos decidido por el Framework Electron, ya que para nosotros nos ha parecido más adecuado dado nuestros conocimientos acerca de las tecnologías web que hay detrás. Electron (anteriormente Atom Shell) es un Framework de código abierto. Permite el desarrollo de aplicaciones gráficas de escritorio usando un modelo cliente servidor similar al utilizado en aplicaciones web [13],[14]. Del lado del cliente nos encontraríamos con un motor Chromium como interfaz y de la parte del servidor el entorno de ejecución Node.js [10]. Electron es el Framework elegido para el desarrollo de algunas aplicaciones conocidas como, por ejemplo, Microsoft Visual Studio Code o Atom de GitHub. 3.1.1.- Node.js Node.js es un entorno en tiempo de ejecución multiplataforma de código abierto. Está diseñado para la capa de servidor de las aplicaciones web, aunque no necesariamente se debe limitar a ello. Node.js, diseñado para crear aplicaciones web escalables, es un entorno de ejecución de JavaScript orientado a eventos asíncronos [16]. Al contrario que la mayoría de código JavaScript, el código escrito para Node.js no se ejecuta en la parte del navegador web, sino en el servidor. Al estar basado en el lenguaje JavaScript, Node.js se puede combinar para un desarrollo homogéneo entre cliente y servidor, y permite la adaptación de patrones para desarrollo del lado del servidor como MVC, facilitando la reutilización de código entre el lado del cliente y del servidor. Diseño interactivo de interfaces gráficas de usuario para Progress 17/75 3.1.2.- Chromium Es la versión de código abierto de Google Chrome. Este proyecto se creó para obtener la ayuda de la comunidad con el fin de mejorar entre todos el motor del navegador, o a su vez crear su propio navegador. Chromium es usado por Electron como motor de la interfaz, es decir la visión de la aplicación en el lado del cliente está generada por Chromium [10]. 3.1.3.- Estructura Electron.JS El funcionamiento de Electron se divide en dos tipos de procesos, el proceso principal main y el proceso renderer. El proceso principal es el proceso de Node.js el cual se comunica con varias API de Electron.js para ayudarnos a comunicarnos con el Sistema Operativo, podemos decir que es nuestra aplicación. El proceso renderer es un proceso de Chromium, pero este proceso tiene Node.js incorporado para poder acceder a los módulos y a los posibles módulos que instalemos con npm [10]. 1.-Estructura Electron.js [11] 3.2.- PEG.JS Es un simple generador de analizadores sintácticos para JavaScript. Genera rápidos analizadores con un excelente control de errores [15]. En nuestra aplicación usamos PEG.js para poder analizar fragmentos del lenguaje de Progress y poder crear nuestros objetos que serán tratados en nuestra aplicación. Diseño interactivo de interfaces gráficas de usuario para Progress 18/75 3.3.- VISUAL STUDIO CODE Es un editor de código fuente desarrollado por Microsoft, creado con Electron. Lo utilizamos para el desarrollo del proyecto. 3.4.- GITHUB Es una plataforma web de gestión de proyectos y control de versiones de código. Permite trabajar colaborativamente con cualquier persona del mundo, planificar proyectos y hacer un seguimiento de los mismos. Está basado en el sistema de control de versiones Git, desarrollado por Linus Torvalds. Este sistema realiza el control de versiones mediante un registro de cambios realizados en el código. Usamos esta tecnología ya que, como explicamos en el apartado de Electron, es la compañía desarrolladora de esta herramienta, además de por su facilidad de uso y su integración con Visual Studio Code. 3.5.- LENGUAJE DE PROGRAMACIÓN JAVASCRIPT Como lenguaje de programación hemos elegido JavaScript. JavaScript es un lenguaje orientado a objetos, débilmente tipado y dinámico [2] ,[7]. Barajamos la posibilidad de usar TypeScript. TypeScript es un superconjunto de JavaScript que esencialmente añade tipos estáticos y objetos basados en clases. Es por eso que nos podía interesar para definir una estructura de datos más rígida. Finalmente decidimos no utilizar TypeScript y perder la capacidad de tener un fuerte tipado porque: • TypeScript está más indicado para proyectos de mayor tamaño mientras que JavaScript es ideal para proyectos de menor envergadura. • TypeScript necesita ser compilado. • Tener que aprender un lenguaje nuevo. Para definir nuestra estructura de datos, utilizamos clases de JavaScript, las cuáles nos ofrecen lo que necesitábamos para este proyecto. Comentaremos estas clases posteriormente, en el capítulo 5.1.- Estructura de datos en JavaScript. 3.6.- FRAMEWORK PARA LA CAPA DE PRESENTACIÓN JQUERY Nos decidimos a usar jQuery para el manejo de los componentes visuales (HTML). Diseño interactivo de interfaces gráficas de usuario para Progress 19/75 jQuery es una biblioteca de JavaScript que nos permite principalmente manipular el árbol DOM (Document Object Model) de una página web, simplificando la manera de interactuar con los documentos HTML y manejar eventos [4],[5]. 3.7.- CAPA DE PRESENTACIÓN 3.7.1.- HTML5 HTML5 es la última versión de HTML (“HyperText Markup Language”). Podemos definir HTML como un estándar que sirve para definir la estructura y el contenido de una página web [8]. 3.7.2.- CSS CSS (“Cascading Style Sheets”), en español «Hojas de estilo en cascada», es un lenguaje de diseño gráfico que nos permite definir y crear la presentación de un documento HTML [2] 3.7.3.- Bootstrap Bootstrap es un Framework CSS y JavaScript diseñado para la creación de interfaces más limpias de una manera más rápida y cómoda. Incluye plantillas de diseño basadas en HTML y CSS con la que es posible modificar tipografías, formularios, botones, tablas, navegaciones, menús desplegables, etc [1],[3]. Una de las mayores ventajas que aporta es el sistema de grid o cuadrículas de Bootstrap. Se trata de un sistema de cuadrículas que crea diseños de página mediante el uso de varias filas y columnas en las que se inserta el contenido. El tamaño de la cuadrícula se adapta a medida que se redimensiona al tamaño de la ventana. También nos ofrece la posibilidad de definir el tamaño de las columnas en función del tamaño de las ventanas. Esto nos permite crear un diseño adaptado a varios dispositivos. 3.7.4.- jQuery UI jQuery UI es una biblioteca de componentes para jQuery. Esta librería añade un conjunto de plug-ins, widgets y efectos visuales que nos permite tener una capa de presentación interactiva desarrollada de manera más rápida y sencilla. Por ejemplo, tenemos la función sortable, que utilizamos en el proyecto, la cual nos permite ordenar los elementos de un componente visual, como por ejemplo una lista. Uno de los elementos que también utilizamos en el proyecto es el datepicker, que nos hace aparecer un pequeño calendario en una variable y nos permite seleccionar una fecha en diferentes formatos. Aparte de estos ejemplos tiene otras muchas funcionalidades y efectos que no utilizamos en el proyecto como por ejemplo las funciones draggable, droppable, resizable, que nos permiten, arrastrar, soltar y redimensionar respectivamente [6]. Diseño interactivo de interfaces gráficas de usuario para Progress 20/75 3.7.5.- Interact.JS Es una librería de JavaScript la cual está creada para facilitar la captura de eventos de arrastrar y soltar con el ratón, reescalado y gestos multitáctiles [12]. Su API es simple y flexible, está unificada para gestos de pantallas táctiles y eventos de ratón. Esta tecnología es la que usamos a la hora de mover los objetos de nuestra aplicación. Diseño interactivo de interfaces gráficas de usuario para Progress 21/75 CAPITULO 4.- CREACIÓN DE INTERFACES DE USUARIO En este punto hablaremos del desarrollo y uso de la interfaz de usuario, que debido a la naturaleza del proyecto es una parte muy importante de éste. Recordemos que nuestro proyecto consiste en crear una aplicación que nos permita desarrollar una interfaz gráfica de manera visual, en lenguaje Progress para el ERP de QAD. 4.1.- FORMULARIOS Antes de hablar de los formularios es necesario ver las estructuras elegidas en Progress para la creación de interfaces visuales y sus características. Así podremos entender mejor los tipos de campos que hay en los formularios y sus casos de uso. 4.1.1.- Frames Un frame en Progress se puede definir como un panel donde se engloban las variables a mostrar. Puede concebirse como un conjunto de variables que se muestran en el mismo momento, tanto para introducir información como para mostrar información ya guardada. Podemos distinguir dos clases de frames: Un frame de entrada es una agregación de varias variables que son mostradas para añadir información. Un frame de salida sirve exclusivamente para mostrar la información. Un frame puede ser usado tanto para entrada como para salida de datos. Sin embargo, en nuestro proyecto consideramos a los frames de entrada como paneles para la introducción de datos, es decir para pantallas de mantenimiento del ERP, y los frames de salida para pantallas de reporte de información. 4.1.2.- Variables En Progress tenemos principalmente los siguientes tipos de variables: • Integer: un entero que emplea 4 bytes de almacenamiento. El rango de valores que puede representar va de -231 a 231-1. • Character: un carácter o cadena de caracteres. • Logical: variable booleana con valores true o false. • Decimal: dato numérico de hasta 50 dígitos de longitud, incluyendo 10 dígitos a la derecha del punto decimal. • Date: utilizado para representar fechas en diferentes formatos. Diseño interactivo de interfaces gráficas de usuario para Progress 22/75 En nuestra aplicación hemos creado un formulario para la obtención de datos del frame a crear (como, por ejemplo, su título o sus propiedades) y otro formulario para la información relativa a las variables del frame. 4.1.3.- Formulario de Frame En un frame puede se pueden definir muchas características, como el color de fondo, elegir si tiene o no borde que englobe el frame, dónde colocar la etiqueta que define la variable, el tamaño del frame, etc. En nuestra aplicación, nosotros hemos elegido una serie de características fijas y otras modificables. Las características fijas son las siguientes: • Tamaño: Un frame puede ser definido por el número de columnas que puede haber en su interior. Cada columna es del tamaño de un carácter, por lo que se utiliza un formato monoespaciado de letra para mantener la proporción. La mayoría de los frames en QAD son de 80 columnas porque en sus inicios las pantallas que utilizaban los ordenadores no admitían un tamaño mayor. Hoy en día se permite tener más tamaño, pero el estándar sigue siendo 80 columnas de ancho por lo que dejamos esta característica fija a este valor. • Posición de las etiquetas: Las etiquetas son un atributo de las variables que permiten una breve descripción de la variable a la que van asociadas. Es decir, si tenemos una variable llamada “a”, le podemos poner la etiqueta “Número de coches” y así permitimos al usuario que utilice la interfaz comprender qué dato está modificando, independientemente del nombre que utilice esa variable en el código. Para los frames de entrada hemos elegido que esta etiqueta se posicione a la izquierda del valor que va a mostrar ya que cumple con el estándar. Otras opciones son: mostrar por encima del valor, o que no exista. Los frames de salida están pensados como reportes que muestran mucha información en forma de lista, por lo que no hemos seleccionado la posibilidad de ajustar la posición de la etiqueta en estos casos. Cada atributo se representa como una columna, debajo de la cual aparece la información de todas las variables mostradas sin repetirse la etiqueta. Más adelante veremos un ejemplo para clarificar este punto. Las características modificables de un frame son: • Nombre: Nombre que vamos a dar al frame en el código. • Tipo: Indica si el frame es de entrada o de salida. • Título: Al frame se le puede agregar una descripción que indique para qué servirá el frame si así se desea. Dejamos esta característica a elección del usuario. Diseño interactivo de interfaces gráficas de usuario para Progress 23/75 2.- Formulario de Frame 4.1.4.- Formulario de Variable En una variable tenemos una serie de características que el usuario define al crearla: • Nombre: nombre de la variable a utilizar en el código. • Tipo: Progress ofrece muchos más tipos a elegir que los descritos en la sección 4.1.2.-, pero para simplificar la creación de las variables nos hemos quedado con los tipos básicos: integer, character, decimal, logical y date. • Label o etiqueta: como comentábamos anteriormente, en Progress se permite tener asociada a una variable un nombre o descripción que se muestra en el frame como sustituto del nombre de la variable en el código. Si esta característica se deja vacía toma por defecto el nombre de la variable. • Valor Inicial: Valor que queremos que tenga por defecto nuestra variable al ser creada. • Formato: el formato es una característica que nos indica cómo será mostrada la variable en el frame. En función del tipo de variable tenemos diferentes formatos. Por ejemplo, si la variable es de tipo decimal podemos elegir cuantos decimales debe mostrar la variable; si es de tipo Diseño interactivo de interfaces gráficas de usuario para Progress 24/75 character, podemos elegir cuántos caracteres se visualizan El ejemplo más claro sería el de las variables tipo date, en el que podemos mostrar las fechas en diversos formatos. Hablaremos más en detalle de los diferentes formatos en el CAPITULO 6.-. 3.- Formulario de Variable 4.2.- FRAME DE ENTRADA Este apartado lo vamos a dedicar a describir el funcionamiento y la vista del frame de entrada. Como se ha comentado en el punto anterior, usaremos el frame de entrada para introducir los datos con los que queremos trabajar, y con ello crearemos una vista de mantenimiento del ERP. 4.2.1.- Zonas principales Una vez creado el frame, debemos proceder a crear las variables necesarias tal y como se ha indicado en la sección 4.1.4.-. En este apartado podemos diferenciar a grandes rasgos cuatro zonas dentro de la vista del frame de entrada: • Zona 1, en la cual se crean las variables. Si creamos varias variables se van posicionando una debajo de la otra. Diseño interactivo de interfaces gráficas de usuario para Progress 25/75 • Zona 2 o frame, es la zona limitada en la cual se pueden situar las variables cuando las arrastramos. • Zona 3, zona en la cual podemos ver un resumen de los datos de la variable actualmente seleccionada. • Zona 4, controles de selección, edición y creación de frames. 4.-Vista del frame de entrada 4.2.2.- Posicionamiento de Variables Uno de los puntos clave de este proyecto es la facilidad que damos al posicionamiento de las variables. Estas se pueden mover sobre el frame creado, bien sea arrastrando con el ratón o bien una vez dentro del frame, moviéndolas con las flechas del teclado. Al moverlas con el ratón restringimos su movilidad gracias a la funcionalidad de Interact.js: interact.modifiers.restrict({ restriction: document.getElementById("inner-dropzone"), endOnly: false } ), Se aprecian dos restricciones: Diseño interactivo de interfaces gráficas de usuario para Progress 32/75 } } 4.2.3.- Modificación de variables Una vez creadas las variables podemos editarlas en caso de necesidad. En el panel de la derecha (Zona 3) podemos ver los datos de la variable seleccionada, que será la última en crearse o la última en seleccionarse. En la parte superior de este panel vemos el identificador de la variable seleccionada y la posición en la que se encontraría en el frame. Si la posición es columna 0 y fila 0, entendemos que esta variable únicamente ha sido creada y aún no se ha movido dentro del frame. Este dato se modifica una vez se ha situado la variable en una zona válida dentro del frame. En la parte media de esta zona podemos ver los datos de la variable que hemos creado: etiqueta, tipo de variable, valor inicial y formato. En la parte inferior del panel hay dos botones, uno para modificar la variable y otro para eliminarla. Si editamos la variable se nos abrirá una ventana idéntica a la de creación de variables, en la que podemos modificar los datos que deseemos. Una vez guardados estos datos la variable se modifica automáticamente. 8.- Panel visualización de variable Diseño interactivo de interfaces gráficas de usuario para Progress 33/75 4.2.4.- Elementos del Frame. En la Zona 4 explicada al principio de este capítulo nos encontramos con todas las opciones correspondientes al frame, tanto a nivel de configuración como a nivel visual. Vamos a explicar las diferentes opciones de izquierda a derecha. 9.- Zona 4 ( Elementos del Frame) • Lista desplegable en la cual podemos seleccionar el frame en el que queremos trabajar. En esta lista se nos mostrarán todos los frames creados en el proyecto actual, tanto de entrada como de salida. • Botón “Editar Frame”. Si seleccionamos esta opción se nos mostrará una ventana con la configuración del frame en el que nos encontramos. Esta información se puede modificar y los cambios se aplicarán en cuanto los aceptemos. La ventana que se abre es muy parecida a la que se nos abre al crear Frame, explicado en puntos anteriores. La diferencia con este, es que ahora no podemos modificar si el frame es de entrada o salida: 10.- Ventana Editar Frame • Borrar Frame. Si seleccionamos esta opción el frame se elimina por completo, no pudiendo recuperar nada de lo que teníamos creado dentro de este frame. • Cambiar a vista Display o cambiar a vista Update. Este botón tiene la funcionalidad de cambiar la vista del frame. Su texto cambia en función de la vista en la que nos encontremos, mostrando el cambio hacia la vista contraria. La vista que tenemos por defecto es la vista Update, en la que se nos muestran las variables con los campos editables. Si, por el contrario, deseamos que estos campos no se puedan editar, deberemos cambiar la vista a “display”, en la que los campos dejan Diseño interactivo de interfaces gráficas de usuario para Progress 34/75 de ser editables. A continuación, dejamos dos imágenes en las que se puede apreciar la diferencia entre ambas vistas: 11.- Vista Update 12.- Vista Display 4.2.5.- Código generado A continuación, podemos ver un ejemplo del código creado en un frame de entrada. Según la figura 11.- Vista Update /* BEGIN VARS Autogenerated */ define variable var1 as integer init 156 format "->,>>>,>>9" no-undo . define variable var2 as date init "12/05/2020" format "mm/dd/yy" no-undo . define variable var3 as logical init true no-undo . /* END VARS Autogenerated */ Diseño interactivo de interfaces gráficas de usuario para Progress 35/75 /* BEGIN INPUT Frame Autogenerated */ define frame f1 var1 label "Cantidad" at row 3 column 17 var2 label "Fecha" at row 3 column 64 var3 label "Stock" at row 3 column 40 with side-labels title "frame_prueba". /* END INPUT Frame Autogenerated */ 4.3.- FRAME DE SALIDA Tal como hemos comentado, el frame de salida es un frame que será utilizado para hacer listas de reportes de información. En términos de diseño, son mucho más sencillos que los frames de entrada. Para entender mejor esta interfaz es necesario introducir un nuevo concepto: las tablas temporales de Progress. En Progress, existen unas estructuras, llamadas temp-tables, que son similares a un struct en C++. Es un tipo de dato compuesto que permite almacenar un conjunto de datos de diferente tipo. En lenguaje natural lo podríamos definir como una súper-variable que engloba diferentes campos, que son a su vez variables. Cuando elegimos un frame de salida, utilizamos este tipo de estructura para agrupar las variables. Ejemplo: si creamos un frame de salida para los productos que vendemos en un almacén, podríamos crear varias variables que corresponden a un mismo producto, pero que definen diferentes características, como, por ejemplo: identificador, cantidad, precio unitario y un valor booleano que nos diga si hay o no stock disponible en estos momentos. En QAD nos mostraría el resultado de la siguiente forma: 13.-QAD Es por ello que, en esta interfaz (14.- Ejemplo Frame de Salida), las variables se crean como elementos de una lista. Y son intercambiables entre sí para elegir el orden en el que aparecen en el reporte. Diseño interactivo de interfaces gráficas de usuario para Progress 36/75 Para permitir al usuario arrastrar y soltar los elementos de una lista con el fin de disponerlos en un determinado orden, hemos utilizado la función sortable de la librería jQuery UI. Esta librería permite al usuario ordenar de manera sencilla los elementos visuales de una lista de HTML y transformar esa información en un array. De esta forma, cuando el usuario intercambia visualmente las posiciones relativas de dos variables, este cambio se refleja en las posiciones de dichas variables dentro del array. Siguiendo con el ejemplo anterior, la creación del frame en nuestra aplicación quedaría de la siguiente forma: 14.- Ejemplo Frame de Salida El código generado para este frame es el siguiente: /* BEGIN TemporalTable Autogenerated */ define temp-table tt_frame_ejemplo no-undo field var1 as character format "x(20)" field var2 as integer init 0 format "->,>>>,>>9" field var3 as decimal init 0.00 format "->,>>>,>>9.99<<<<<<<<" field var4 as logical init true . /* END TemporalTable Autogenerated */ /* BEGIN OUTPUT Frame Autogenerated */ define frame frame_ejemplo var1 label "Identificador" var2 label "Cantidad (ud)" var3 label "Precio Unitario" var4 label "Stock Disponible" with title "Productos". Diseño interactivo de interfaces gráficas de usuario para Progress 37/75 /* END OUTPUT Frame Autogenerated */ En esta tabla temporal se pueden crear diferentes registros, para luego ser mostrados con el frame frame_ejemplo del código anterior, tal como se muestra en la figura (13.-QAD) 4.4.- VISTA DE CÓDIGO Como sabemos, nuestro objetivo es crear código Progress que nos permita hacer una interfaz visual para QAD, pero de una forma menos tediosa y mucho más rápida que si escribiéramos el código directamente. En parte, esto viene derivado de que Progress no estaba pensado en un principio para tener interfaces visuales amigables para el usuario, ya que es un lenguaje concebido para el manejo rápido y sencillo de grandes volúmenes de datos guardados en el sistema. Es por ello que hemos creado una vista de cómo quedaría el código Progress generado en el momento en el que lo estamos desarrollando. Así podemos ver rápidamente cómo quedará nuestro código antes de guardarlo realmente en un archivo. Esta utilidad ayuda incluso a entender qué consecuencias en código tiene la acción que el usuario está realizando visualmente. 15.- Vista de Código Diseño interactivo de interfaces gráficas de usuario para Progress 38/75 CAPITULO 5.- GENERACIÓN Y ANÁLISIS SINTÁCTICO DE CÓDIGO PROGRESS En este capítulo hablaremos de la conversión de código Progress a JavaScript y viceversa. Como ya sabemos, nuestra aplicación nos permite crear interfaces visuales de una manera simple y obtener el código Progress correspondiente. Hablaremos primero de la estructura de datos, en JavaScript, que utilizamos para guardar esta información y más tarde de cómo se transforma esta estructura a código Progress. 5.1.- ESTRUCTURA DE DATOS EN JAVASCRIPT Como elementos principales en el modelo de datos de la aplicación tenemos los frames y las variables. Cabe recordar que un frame en Progress nos permite dar un formato visual a las variables a la hora de presentarlas al usuario., es decir, nos dice cómo se verán las variables. Nuestra estructura consta de tres entidades: los frames, las variables y una clase auxiliar que hemos denominado Progress. 5.1.1.- Clase Progress Esta clase es la que creamos cuando el usuario elige crear una nueva plantilla o al cargar un archivo. Es la que guarda toda la información de variables y frames con los que estamos trabajando. Esta clase tiene como atributos: • idFrames: es un contador que utilizamos como identificador cuando creamos los diferentes frames. • frames: es un Map de objetos Frame. • fileName: atributo en el que guardamos el nombre del archivo en el que guardaremos el código Progress generado o en el que está guardado. En cuanto a las funciones, podemos destacar las siguientes: • addFrame: esta función recibe como parámetros las características del frame, crea un objeto de la clase Frame con el identificador correspondiente y lo guarda en el Map frames. Finalmente, actualiza el contador de frames. • addVartoFrame: recibe como parámetro la información de una variable y el frame al que debe añadirse. Busca el frame correspondiente y llama a la función addVariable de éste. Diseño interactivo de interfaces gráficas de usuario para Progress 39/75 • addVartoOutputFrame: es similar a la anterior, pero además de añadir la variable al frame de salida, añade la información de la variable en el array de posiciones. Esto se debe, a que como hemos hablado anteriormente, un frame de salida y uno de entrada son diferentes. El frame de salida guarda las posiciones en las que están las variables en un array, mientras que el frame de entrada no guarda las posiciones, sino que son las variables las que guardan dicha información. Aquí podemos ver en detalle la clase Progress: class Progress{ constructor(){ this.idFrames = 1; //inicializamos ids a 1 this.frames = new Map(); //inicializamos map de frames this.fileName = "Sin título.p" //inicializamos el nombre del archivo } //LLamamos al constructor de la clase frame para crear un nuevo frame, lo metemos en nuestro array y actualizamos idFrames addFrame(name, title, type){ let newFrame=new classFrame.Frame(this.idFrames,name,title,type); this.frames.set(this.idFrames,newFrame); this.idFrames ++; return this.idFrames -1; } addVartoFrame(idFrame,varInfo){ let frame = this.frames.get(parseInt(idFrame)); return frame.addVariable(varInfo['name'],varInfo['type'], varInfo['format'],varInfo['label'],varInfo['initial'], varInfo['tam']); } addVartoFrameRead(idFrame,varInfo){ let frame = this.frames.get(parseInt(idFrame)); /* console.log("variable que me llega: ", varInfo); */ return frame.addVariableRead(varInfo['name'], varInfo['type'], varInfo['format'],varInfo['label'],varInfo['initial'], varInfo['col'],varInfo['ro w'],varInfo['movido']); } addVartoOutputFrame(idFrame,varInfo){ let frame = this.frames.get(parseInt(idFrame)); let id = frame.addVariable(varInfo['name'],varInfo['type'], varInfo['f ormat'],varInfo['label'],varInfo['initial'],0); frame.addVariableOutput(id); return id; Diseño interactivo de interfaces gráficas de usuario para Progress 40/75 } getFrames(){ return this.frames; } getFrame(idFrame){ return this.frames.get(parseInt(idFrame)); } getFileName(){ return this.fileName; } setFileName(fileName){ this.fileName = fileName; } deleteFrame(idFrame){ this.frames.delete(parseInt(idFrame)); } deleteVariable(idFrame, idVar){ this.frames.get(parseInt(idFrame)).deleteVariable(idVar); } editFrame(idFrame, newData){ let frame = this.frames.get(parseInt(idFrame)); frame.editData(newData); } getVariableByKey(idFrame,keyVar){ let frame=this.frames.get(parseInt(idFrame)); return frame.getVariable(keyVar); } } 5.1.2.- Clase Frame Utilizamos esta clase para guardar la información de cada frame, con sus características y las variables que mostrará. Sus atributos son los siguientes: • idVar: contador que utilizaremos de identificador para las variables asignadas a este frame. • id: el identificador con el que localizar a este frame en la clase Progress. Viene inicializado por esta última clase al crear un objeto de clase Frame. • name: nombre del frame con el que será identificado en el código Progress. • title: característica title que utilizaremos en el código Progress. • type: atributo que nos indica si el frame es de entrada o de salida. Diseño interactivo de interfaces gráficas de usuario para Progress 41/75 • vars: Map que contendrá las variables asignadas a este frame. • view: a la hora de visualizar el frame en la aplicación, nos indica si se está visualizando en modo update o en modo display. Esto está explicado con más detalle en el punto 4.2.4.-. Utilizamos esta característica para ir cambiando de una vista a otra. • varsOutFrame: este atributo es sólo utilizado por los frames de salida. Se trata de un array de identificadores de variables asignadas a este frame. Este array se ordena en función de la posición en la que queramos que se vean las variables en la salida. Para entender mejor esta característica revisar el punto 4.3.-. El código de esta clase es el siguiente: class Frame { /*Type = 0 entrada = 1 salida */ constructor(id,name,title,type){ this.idVar=1; // inicializamos ids variables this.id=id; // mi id me viene dado de la clase Progress this.name=name; this.title=title; if (type == "0") this.type="input"; if (type == "1") this.type="output"; this.vars= new Map(); //inicializamos map de variables this.view = "update"; this.varsOutFrame = new Array(0); //inicializamos array para variables de salida } addVariable(name, type, format, label, initial, tam){ let newVar = new classVar.Variable(this.idVar,name, type, format, label, initial, tam); this.vars.set(this.idVar,newVar); this.idVar ++; return this.idVar -1; } addVariableRead(name, type, format, label, initial,col,row,movido){ let newVar = new classVar.Variable(this.idVar,name, type, format, label, initial); if(movido==1){ Diseño interactivo de interfaces gráficas de usuario para Progress 48/75 • /* BEGIN TemporalTable Autogenerated */ y /* END TemporalTable Autogenerated */ que son colocadas en cada definición de tabla temporal que es utilizada en un frame de salida. • /* BEGIN INPUT Frame Autogenerated */ y /* END INPUT Frame Autogenerated */ nos marcan los frames de entrada. • /* BEGIN OUTPUT Frame Autogenerated */ y /* END OUTPUT Frame Autogenerated */ nos señalan cada frame de salida. Con estas marcas sabemos qué parte de código mandar a cada uno de los analizadores sintácticos que utilizamos para obtener los datos del código como se comenta en la próxima sección. 5.3.- ANALIZADOR SINTÁCTICO DE PROGRESS Una de las funcionalidades de la aplicación es poder leer código Progress y cargar los frames y variables correspondientes en nuestra aplicación para ser modificados. Una vez entendida la representación de las estructuras en los diferentes lenguajes podemos meternos en profundidad en el análisis de código Progress. Como se menciona en el CAPITULO 3.- utilizamos el analizador sintáctico PEG.js. 5.3.1.- Gramática y Semántica de PEG.js Una gramática en PEG.js consiste en una serie de reglas. Cada regla tiene un nombre que identifica esa regla y una expresión de análisis que define el patrón que debe cumplir la entrada. También se puede introducir código en JavaScript para definir acciones cuando la entrada cumple el patrón, es decir, al pasar la regla satisfactoriamente. Una regla puede contener también una etiqueta que puede ser usada para la gestión de errores. El análisis comienza en la primera regla, que también es llamada la regla de inicio. La regla de inicio puede ser precedida por un inicializador, esto no es más que código JavaScript entre llaves “{” “}”. Este código se ejecuta antes de que el generador de análisis comience. Todas las variables y funciones definidas en el inicializador son accesibles en las reglas. Tipos de expresiones de análisis: • "literal" o 'literal': Comprueba que los siguientes caracteres de la entrada se ajustan exactamente al string indicado y lo devuelve. Añadiendo i a la derecha del literal hacemos el ajuste insensible a mayúsculas. • . : Ajusta exactamente con un carácter y lo devuelve como string. Diseño interactivo de interfaces gráficas de usuario para Progress 49/75 • [characters]: Ajusta la entrada con un carácter del conjunto dado y lo devuelve como string. La lista de caracteres puede contener también rangos (por ejemplo, [a-z] significa “todas las letras en minúscula”). Poner delante del carácter “^” niega la condición (ej: [^a-z] significa “todos los caracteres que no sean letras minúsculas”). Añadiendo i a la derecha lo hacemos insensible a mayúsculas. • regla: Ajusta la entrada con el análisis de una expresión o una regla recursivamente y devuelve su resultado. • ( expresión ): Ajusta con una subexpresión y devuelve el resultado. • expresión *: Ajusta con cero o más repeticiones de la expresión y devuelve sus resultados en un array. • expresión +: Ajusta con una o más repeticiones de la expresión y devuelve su resultado en un array. • expresión ?: Intenta ajustar con la expresión dada. Si lo hace con éxito, devuelve el resultado, en otro caso, devuelve null. • & expresión : Intenta ajustar la entrada con la expresión dada. Si lo hace con éxito, devuelve undefined y no consume ninguna entrada, en otro caso, considera la verificación fallida. • ! expresión : Intenta ajustar con la expresión dada. Si falla devuelve undefined y no consume ninguna entrada. • { predicado}: El predicado es una parte de código JavaScript que se ejecuta dentro de una función. • $ expresión: Ajusta con la expresión dada y si el ajuste tiene éxito devuelve el texto parseado como resultado. • etiqueta: expresión: Devuelve el resultado bajo la etiqueta especificada. La etiqueta debe ser un identificador de JavaScript. • expresión1 expresión2... expresiónN: Ajusta con una secuencia de expresiones y devuelve el resultado en un array. • expresión{ acción}: Ajusta la entrada con la expresión dada, si el ajuste tiene éxito, ejecuta la acción. • expresión1 / expresión2 / ... / expresiónN: Intenta ajustar con la primera expresión. Si falla, sigue con la siguiente y así sucesivamente. Diseño interactivo de interfaces gráficas de usuario para Progress 50/75 5.3.2.- Reglas utilizadas A continuación, veremos un ejemplo de uno de los analizadores sintácticos que hemos utilizado en el proyecto. Hemos realizado tres analizadores diferentes. Uno para frames, otro para temp-tables y otro para las variables. En este ejemplo vemos como analizamos sintácticamente las variables: variables = variable+ variable = _ defineVar __ line:line _ noUndo _ "."_{ return {vars: line} } defineVar = "define variable" noUndo = "no-undo" line = v:var _ opciones:Opcion+ _{ return {name: v, opciones: opciones} } var = !(reservedWords __) ("_" / [a-zA-Z0-9] / "-")* { return text() } reservedWords = "field" / defType / "temp-table" / noUndo / "as " / "init " / "format " Opcion = _ opcion:(type/OpcionLabel/OpcionInit/OpcionFormat) { return opcion } type = "as" __ t:$defType { return { type:"type", value: t} } defType = "integer" / "character" / "date" / "logical" / "decimal" OpcionLabel = "label" __ cadena:LiteralCadena { return { type: "label", label: cadena } } OpcionInit = "init" __ result:(LiteralCadena/Integer) { return { type: "init", value: result } } Diseño interactivo de interfaces gráficas de usuario para Progress 51/75 OpcionFormat = "format" __ cadena:LiteralCadena { return { type: "format", format: cadena } } LiteralCadena = "\"" texto:([^\"]*) "\"" { return texto.join("") } Integer "integer" = _ [0-9]+ { return parseInt(text(), 10); } _ "whitespace" = [ \t\n\r]* __ "whitespace_mandatory" = [ \t\n\r]+ A continuación, vamos a analizar las reglas utilizadas. Para hacerlo más cómodo obviamos las reglas “_” y “__” que permiten los espacios y saltos de línea. Como primera regla tenemos “variables”, que comprueba que puede haber una o más apariciones de la regla “variable”. La regla “variable” es una sucesión de reglas, por lo que debe cumplir cada una de ellas. Dentro de ésta, tenemos la regla defineVar, la regla noUndo y la expresión “.”, todas ellas comprueban un literal. Después nos encontramos con la regla line. Esta regla consta de la regla var que comprueba que el identificador de una variable sea cualquier carácter. Aquí tenemos que tener en cuenta la regla reservedWords que comprueba que el identificador no sea una palabra reservada. También tenemos la regla Opciones, en esta regla comprobamos si aparecen cada una de las características que esperamos en una variable y devuelve el resultado como texto con la característica correspondiente. Como ejemplo de una de las características tendríamos label. Con la regla OpcionLabel comprobamos el literal label y el literal que lo acompañe entre comillas. De esta forma, devolvemos un objeto con dos campos: el campo type es igual label y el campo label es igual al texto entre comillas que lo acompañe. De esta forma conseguimos tener una estructura de datos que nos devuelve la información en un objeto JavaScript que posteriormente utilizaremos a la hora de abrir el archivo. Diseño interactivo de interfaces gráficas de usuario para Progress 52/75 CAPITULO 6.- OTRAS FUNCIONALIDADES Para poder conseguir un correcto funcionamiento de toda la aplicación hemos tenido que ser muy rigurosos con ciertos parámetros, como, por ejemplo, la validación de datos. Una gran debilidad de seguridad de una aplicación web es la falta de validación de datos asociada a la entrada de datos por parte del cliente. Nunca debemos confiar en los datos que introduce el cliente, sino que tenemos que garantizar que la aplicación sea robusta frente a la obtención de datos por parte del usuario. La validación de datos es muy importante para que no haya problemas con la funcionalidad de nuestro proyecto. En los siguientes puntos vamos a comentar como se ha desarrollado el control de los datos de entrada. 6.1.- VALIDACIÓN DE DATOS Este punto lo debemos tratar desde dos puntos de vista diferentes. En primer lugar, vamos a comentar la validación de datos desde la parte de creación de código por el usuario, y la segunda parte nos vamos a centrar en la validación de datos a la hora de cargar un archivo de Progress. Toda validación de datos se ejecuta en la parte del servidor. Como comentamos antes, nuestra aplicación está creada con JavaScript, pero si validamos los datos en la parte cliente podríamos seguir estando expuestos a un ataque por parte del usuario, ya que se puede usar software para la desactivación de esta validación. 6.1.1.- Validación de datos en la creación de código. Comenzamos comentando las validaciones de datos que realizamos a la hora de generar código con la aplicación. • Validación de tamaño: Tenemos que controlar que el tamaño entre el label y los formatos introducidos no superen las 80 columnas del Frame • Validación de nombre de Frame: No permitimos que se puedan crear dos frames con el mismo nombre, además de no poder crear un Frame con nombre vacío. Esto lo conseguimos recorriendo toda la clase del proyecto en el que estamos trabajando y revisamos que no exista una clase Frame que contenga el mismo nombre. A la hora de editar dicho Frame ejecutamos el código igual que el que se muestra a continuación, pero con la diferencia que comprobamos si el nombre ha cambiado: exports.validateNewFrame = function validateNewFrame(frameInfo, callback){ Diseño interactivo de interfaces gráficas de usuario para Progress 53/75 let encontrado = false; if (frameInfo["nombre"] == ""){ callback("Nombre de frame vacío, debe rellenar este campo"); } else{ nuevaPlantilla.getFrames().forEach(function (elemF, indexF, array) { if (elemF.getNombre() == frameInfo["nombre"]){ encontrado = true; } } ); if (encontrado){ callback("Nombre de frame ya existente, elija otro"); } else callback("Ok"); } } Diferencia a la hora de editar el Frame. if(frameInfoNew["name"] !== frameInfoOld["name"]){ //Si ha cambiado el nombre, compruebo que no sea uno existente nuevaPlantilla.getFrames().forEach(function (elemF, indexF, array){ if (elemF.getNombre() == frameInfoNew["name"]){ encontrado = true; } } ); } if (encontrado){ callback("Nombre de frame ya existente, elija otro"); } else callback("Ok"); • Validación en la creación de variables: cuando se crean variables no sólo debemos comprobar el nombre, sino que debemos comprobar que todos los formatos y campos introducidos coincidan entre sí con el formato definido. Por lo tanto, la validación de datos de variables podemos separarla en dos apartados diferentes: o Validación del nombre: Como en el paso anterior con el Frame, revisamos que la variable no se encuentre creada en todo el proyecto, es decir, no puede existir la variable en dos frames diferentes. Diseño interactivo de interfaces gráficas de usuario para Progress 54/75 nuevaPlantilla.getFrame(idFrame).getVariables().forEach(function (elemF, index F, array) { if (elemF.getNombre() == varInfo["name"]){ validaciones["nombre"]="repetido" } } ); o Validación y consolidación de formatos: Con los formatos debemos ser más cautelosos para que realmente los datos que se introduzcan correspondan con los valores que se pueden poner. ▪ Enteros: comprobamos que el valor introducido es un número. Si es correcto el tamaño del div de la variable corresponderá con el valor mayor entre 8 y la longitud del número introducido. if(varInfo["type"]=="integer"){ //integer validaciones["ini"]=!isNaN(varInfo["initial"]); if(validaciones["ini"]){ varInfo["tam"]=Math.max(8,varInfo["initial"].length); varInfo["initial"]=parseInt(varInfo["initial"]).toFixed(); } } ▪ Fecha: La fecha se puede introducir con varios formatos diferentes como: • dd/mm/yyyy - mm/dd/yyyy - yyyy/mm/dd Además, se puede introducir la fecha de forma manual, o seleccionando en un calendario. Si la fecha es manual podría haber problemas de consistencia de datos, como días que no existen en cierto mes, por ejemplo. Aun así, siempre comprobamos que la fecha sea correcta y válida, por lo que hemos creado una función para comprobar estos datos: function isValidDate(dateString,format){ var parts = dateString.split("/"); if(format=="dd/mm/yyyy"){ if(!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(dateString) ) return false; var day = parseInt(parts[0], 10); var month = parseInt(parts[1], 10); var year = parseInt(parts[2], 10); }else if(format=="mm/dd/yyyy"){ if(!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(dateString) ) return false; Diseño interactivo de interfaces gráficas de usuario para Progress 55/75 var day = parseInt(parts[1], 10); var month = parseInt(parts[0], 10); var year = parseInt(parts[2], 10); }else if(format=="yyyy/mm/dd"){ if(!/^\d{4}\/\d{1,2}\/\d{1,2}$/.test(dateString)) return false; var day = parseInt(parts[2], 10); var month = parseInt(parts[1], 10); var year = parseInt(parts[0], 10); }else return false; // Creamos rangos para años y meses if(year < 1000 || year > 3000 || month == 0 || month > 12) return false; var monthLength = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; // Ajustamos años bisisestos if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) monthLength[1] = 29; // Comprobamos el día con el mes return day > 0 && day <= monthLength[month - 1]; }; ▪ Decimales: Cuando creamos una variable de tipo decimal debemos comprobar que la parte decimal obligatoria sea un número entero mayor que 0 y el valor inicial sea un número entero o decimal. Si este número es decimal y se introducen más decimales de los que hemos indicado en la “parte decimal obligatoria” el número se redondea a los decimales que hemos indicado. if(varInfo["type"]=="decimal"){ //decimal let initial=!isNaN(varInfo["initial"]); let decimal=!isNaN(varInfo["decimal"]); if(initial && decimal){ if(parseInt(decimal)<=0){ varInfo["decimal"]=1; } else{ varInfo["decimal"]=parseInt(varInfo["decimal"]); } varInfo["initial"]=parseFloat(varInfo["initial"]).toFixed(parseInt( varInfo["decimal"])); varInfo["format"]=getFormatDecimal(parseInt(varInfo["decimal"])); varInfo["tam"]=varInfo["initial"].toString().length; } else if(initial==false && decimal){ Diseño interactivo de interfaces gráficas de usuario para Progress 56/75 validaciones["ini"]="decimalInitial"; } else if(initial==false && decimal==false){ validaciones["ini"]="ini&decimal"; } else{ validaciones["ini"]="decimal" } } ▪ Caracteres: En este caso sólo verificamos que el formato, es decir la longitud, sea un formato válido, un número. Si está vacío o es 0 este formato se crea con valor X(8). Una vez que comprobamos que es un formato válido, creamos el formato para Progess de la forma X( nº caracteres ). if(varInfo["type"]=="character"){ if(!isNaN(varInfo["format"])){ if(parseInt(varInfo["format"])<=0){ varInfo["format"]='x(8)'; } else{ varInfo["tam"]=parseInt(varInfo["format"]); varInfo["format"]='x('+parseInt(varInfo["format"])+')'; } } else validaciones["ini"]="character"; } 6.1.2.- Validación de datos en la carga de archivo. A la hora de cargar un archivo de Progress, lo analizamos a través del analizador sintáctico como explicamos en la sección 5.3.-Analizador sintáctico de Progress, con lo que obtenemos los datos estructurados en un formato JSON, en el que podemos diferenciar tres tipos de datos: • Datos de las ‘temp-tables’: en estos datos recogemos las variables que se han inicializado para poder crear los frames de salida. • Datos de las variables: almacenamos las definiciones de las variables de los frames de entrada. • Datos de los frames: se recoge toda la información de los frames creados, además de sus variables correspondientes. Diseño interactivo de interfaces gráficas de usuario para Progress 57/75 Una vez tenemos todos los datos estructurados es la hora de tratarlos para poder convertir ese código a las vistas de nuestro proyecto. Cabe destacar que la validación de datos es muy parecida que la comentada anteriormente incluso llegamos a utilizar las mismas funciones: • Comenzamos recorriendo la estructura de datos de los frames. Por cada frame que nos encontramos comprobamos sus datos básicos: nombre, tipo y título. • Continuamos con el tratamiento de las variables que contiene cada frame. Para esto es necesario saber el tipo de frame, ya que si es de entrada o de salida este tratamiento es diferente. o Frame de Entrada: como hemos comentado anteriormente, estos datos están divididos en la parte de definición de variables en la cual nos encontramos con el tipo, formato y valor inicial (estos datos se encuentran en la estructura de datos de variables), y por otra parte tenemos la label y la posición en el frame (estos datos se encuentran en los datos de los frames). Recorremos estas estructuras e inicializamos o corregimos ciertos valores que nos vamos encontrando. Por ejemplo, cuando el valor de la variable no coincide con el formato de la inicialización. Más adelante comentamos la lista de valores corregidos que son compartidos con los frames de salida. o Frame de Salida: estos datos se encuentran divididos en dos partes. Una de ellas es la definición de las variables en la estructura de las temp-tables y la otra se encuentra en la estructura de los frames. • Lista de valores corregidos en los frames: o Integer: si el valor de la variable no es un número lo inicializamos a 0. Además, en cualquier caso, le aplicamos el formato indicado en el fichero Progress. o Decimal: si al leer el documento la variable tipo decimal no contiene formato rectificamos el valor de la parte obligatoria decimal a 1. De no ser vacío tratamos el formato para saber cuántos decimales son necesarios. Además, al igual que con los Integer, si el valor inicial no es un número lo inicializamos a 0. o Character: recogemos el valor del formato para saber el tamaño de la variable. o Date: comprobamos que la fecha correcta al igual que en la sección 6.1.1.- A continuación, se puede observar el fragmento de código que realiza esta corrección de valores: function preparaDatos(varInfo){ if(varInfo["type"]=="integer"){ if( isNaN(parseInt(varInfo["initial"]))) varInfo["initial"]=0; else Diseño interactivo de interfaces gráficas de usuario para Progress 64/75 7.3.2.- Efectos visuales. Se podrían generar diversos efectos visuales a la hora de arrastrar variables, como, por ejemplo, marcar las variables seleccionadas, o poder seleccionar varias variables y moverlas a la vez. 7.3.3.- Alineaciones por defecto. Otra ampliación interesante sería agregar diferentes botones para alinear todas las variables de un mismo modo. Por ejemplo, que se coloquen todas a la izquierda, a la derecha o centradas. 7.3.4.- Añadir rejilla Se podría añadir un efecto de rejillas para ver diferenciadas las filas y columnas en el frame, para facilitar su alineación. 7.3.5.- Ordenar visualización de frames. Se puede agregar la funcionalidad de ordenar el orden en el que queremos que se vayan mostrando los frames en el ERP. 7.3.6.- Ampliar características del frame. Como hemos comentado, hemos elegido una serie de características muy concretas con las que personalizar el frame, pero hay muchas más posibilidades, como permitir cambiar color de fondo, la transparencia del borde, la colocación de las etiquetas de cada variable, etc. Una ampliación interesante sería tener en cuenta algunas de estas características. 7.3.7.- Ampliación de lectura de documentos. Nos hemos centrado en poder leer un documento Progress con las variables y formatos que hemos creado en el proyecto. Un punto muy fuerte como ampliación sería que fuéramos capaces de poder leer un código Progress bastante más completo, además de poder hacer una revisión por si hubiera problemas con esta nueva lectura. 7.3.8.- Vista simulada del frame de salida. Como hemos comentado en el apartado 4.3.- los frames de salida se visualizan como columnas con información ya que están pensados para hacer reportes. Para simplificar la creación de estos frames en la aplicación, nosotros creamos una lista en la que se muestra el orden en el que aparecerán a la hora de ser mostradas. Podríamos añadir una funcionalidad para que el usuario pudiera visualizar cómo quedaría realmente la representación de este frame en el ERP. Diseño interactivo de interfaces gráficas de usuario para Progress 65/75 CAPITULO 8.- CONCLUSIONS AND FUTURE WORK Throughout the development of our project we have encountered difficulties, which we have addressed as well as we could, but finally reaching the expected result. We have also achieved a development broader than the one initially planned. In this section we are going to focus on the problems encountered and explain to what extent the objectives of the project have been meet. in the last section we shall talk about the extensions that can be made in the future. 8.1.- ACHIEVEMENT OF GOALS As we have commented in section 2.2.- at the beginning of this project, we set some acceptable objectives to be able to finish it in the scheduled time. At this point we will summarize the main objective and the secondary ones. Build an application to create input frames for Progress. This was the main objective of the project: to create an application which would allow us to create a Progress graphical user interface simply by dragging the objects we want on a frame. This objective has been met, as we have developed an application with which we create a frame and variable structure. This is the key point of the project, in which we could summarize all the other objectives, but we will divide them into three other parts. • Creation of graphical user interface: we can consider this point the most important of the project. We are able to create variables and we are able to interact with them with gestures and movements. We have created an application with which the end user can feel very comfortable when moving and placing the created variables within a panel that has previously been generated in a few simple steps. The user can interact visually with the variables, the user can see in real time the Progress code that is being generated with each movement or creation of frames or variables. • Code import: we wanted to ensure that once the code was created with our application we were able to import it again. This point has been achieved. In addition, if the user continues creating code with the same guidelines that we use in our application, the code could be loaded into the application successfully. At the moment it is not possible to load a Progress file with different labels than the ones we deal with in the project. The Progress language is too broad to deal with in a first phase, so we discuss this point later in section. Diseño interactivo de interfaces gráficas de usuario para Progress 66/75 • Data validation: this is one of the most complex points of this project. The data processing as we discussed in section 6.1.-was quite complex. We can process data that user enters through our forms and control the errors that we find when code is imported from an input file. 8.2.- DIFFICULTIES ENCOUNTERED The goals of the project were difficult to achieve due to the lack of knowledge of Progress language by one of the team members and the lack of knowledge of some of the tools used. The first problem we encountered was how to develop a desktop application using web development tools. This was one of our main objectives, which was resolved fairly quickly as soon as we had a meeting with the project director, Manuel. He presented us several options to develop our application as we wanted. Once the technologies and the problem approach had been decided, we started with the development itself. When developing we have encountered the problems that we discuss below: • How to enable drag and drop functionality? This was one of the main problems we had. Once we started to investigate on this topic, we found a fairly easy to use library, so we decided to use Interact.JS and not native code. • Situation of the variables once moved. When we created the variables and dragged them, the gap that this variable occupied still was shown in the bottommost pane because during the drag the corresponding ‘div’ object did not really move. We found a solution by cloning this object and moving it to a higher section. Also, this way we could differentiate the variables that we had moved from those that we had not. This process is explained in detail in section 4.2.1.- • Calculate distances from the origin of the variable. In our initial tests with Interact.JS we did not know how to get the distance that the variable had been moved with respect to its initial position. Reading the documentation, we find the solution to our problems. Once we had these distances we had to develop on paper how a variable moved and calculate its new coordinates to be able to solve which row and which column it corresponds to. We have detailed this point in the section 4.2.2.- • Letter fit for size. We had a problem with the letters of the variables, since each one occupied a different amount of pixels. We needed a typeface in which all of its characters took up exactly the same amount of horizontal space. We focus on the use of monospaced letters, so we decided to use "Courier New Monospace". • Creation of complementary windows. At the beginning of the project we encountered the problem of requesting data from the user, so we decided to create complementary windows for this proposal. We ran into a lot of problems when working with web technologies, as it involved spending a great deal of time creating services that could communicate with the Electron.JS main process, where the application was running. So, we decided to use modal windows, which are Diseño interactivo de interfaces gráficas de usuario para Progress 67/75 dialog boxes that appear on the main page, blocking the rest of the interface in order to focus on this particular action. • Control div sizes to fit the format. Once we generated the divs of the variables, they occupied a whole line, so we had to adjust them to solve problems when dragging or moving the variables so that they could be placed in the frame correctly. • How to represent the output frames so they are easily editable. As we have commented, the output frames are reports of information in columns. To represent them in our application we finally choose a list with the variables ordered in the order in which the columns would be displayed. In this way, the editing and viewing is much more comfortable. 8.3.- FUTURE WORK In this section we will discuss the possible improvements or extensions that could be made. We will focus exclusively on what we believe could be done in the short term. 8.3.1.- Type extension We have mainly focused on a series of types that are the most common, but one point that could be extended is to incorporate more data types for the created variables, such as: datetime, recid, int64, etc. You can also define the type of a variable in Progress through a field in a table in a database, so it would also be an extension to consider. 8.3.2.- Visual effects Various visual effects could be generated when dragging variables, such as marking selected variables, or being able to select several variables and move them at the same time. 8.3.3.- Default alignments Another interesting extension would be to add different buttons to align all the variables in the same way. For example, they can be aligned to the left, right, or centered. 8.3.4.- Add grid A grid effect could be added to see the rows and columns in the frame differentiated, to facilitate their alignment. 8.3.5.- Order display of frames We can add the functionality of specifying the order in which we want the frames to be displayed in the ERP. Diseño interactivo de interfaces gráficas de usuario para Progress 68/75 8.3.6.- Expand characteristics of the frame As we have commented, we have chosen some specific properties to customize the frame, but there are many others, such as the background color, the transparency of the border or the placement of the labels of each variable. An interesting extension would be to take into account some of these properties. 8.3.7.- Extension of document reading We have focused on being able to read a Progress document with the variables and formats that we have created in the project. An extension could be to be able to read a much more complete Progress code, in addition to being able to do a review in case there were issues with this new reading process. 8.3.8.- Simulated view of the output frame As we have commented in section 4.3.- the output frames are visualized as columns with information, since they are intended to make reports. To simplify the creation of these frames in the application, we created a list showing the order in which they will appear when they are displayed. We could add a functionality to visualize the representation of how this frame would actually look in the ERP. Diseño interactivo de interfaces gráficas de usuario para Progress 69/75 CAPITULO 9.- CONTRIBUCIONES DE CADA PARTICIPANTE 9.1.- CONTRIBUCIÓN RICARDO CABALLERO SÁNCHEZ • Propuesta de trabajo. Como hemos comentado en la introducción, la propuesta de este proyecto nace al tener un problema con el lenguaje nuevo que estaba utilizando en el trabajo, Progress. En un principio tomé de referencia Netbeans, programa que había utilizado en cursos anteriores en la carrera, como en la asignatura Modelado de Software en la que implementamos aplicaciones de escritorio con Java. Partiendo de esta base, comencé a investigar un poco más sobre las interfaces en Progress, qué se podía hacer y qué no, ya que las interfaces que solíamos crear en el trabajo eran bastante simples, pero quería saber hasta qué punto se podía llegar. Después hablé con mi jefe, ya que él tiene mucha más experiencia con el lenguaje y sabe de las ventajas y las carencias de éste. Hicimos unos bocetos de cómo podría ser la interfaz para que fuese cómoda de utilizar, a la vez que simple y también de las funcionalidades que estábamos buscando. La mayor de estas funcionalidades era utilizar la aplicación para crear pantallas de mantenimiento, lo que llamamos en el trabajo frames de entrada. Estas pantallas son bastante utilizadas en un ERP y nos permiten acceder a ciertos datos e ir modificándolos. Por ejemplo: una pantalla de mantenimiento de órdenes de ventas está compuesta de muchos campos que se van rellenando para hacer la venta. Tenemos datos en la cabecera, como fecha efectiva, cliente al que va dirigida, datos sobre impuestos, etc. Después en cada línea tenemos el producto, la cantidad, el precio, descuentos y otras características. Como vemos, son muchos datos y se van presentando en distintos frames para que el usuario vaya rellenando los datos de forma cómoda o que se rellenen por defecto en base a otros datos introducidos anteriormente. Programar estas pantallas en Progress es muy tedioso. Al ver este problema pensé que podríamos aportar una solución a partir de un Trabajo de Fin de Grado y así hacer un proyecto que sea útil y que no sea simplemente un proyecto con el que cumplir con los créditos, sin motivación y sin un propósito real. Por esta razón, opino que nuestro proyecto tiene un gran valor al estar basado en un problema real y al resolverlo de una manera eficiente. • Estudio de herramientas y tecnologías. Al tener una idea de la interfaz que queríamos construir nos pusimos a investigar sobre librerías de JavaScript que nos permitieran arrastrar y soltar elementos en la pantalla. Encontré una librería, jQuery UI, que finalmente descartamos para este propósito pero que utilizamos para mostrar un calendario a la hora de elegir el valor inicial en variables de tipo fecha. De esta misma librería también utilizamos la función sortable en los frames de salida. Diseño interactivo de interfaces gráficas de usuario para Progress 70/75 También estuve investigando el uso de otros lenguajes en lugar de JavaScript, como TypeScript. La parte que más tiempo de estudio me llevó fue el uso de PEG.JS como analizador sintáctico. En la carrera no había visto nunca cómo se definían unas reglas para analizar un lenguaje y construir un objeto con los datos que nos interesan, por lo que al principio me costó algo más entender el funcionamiento, pero utilizando el parseador online con algunos ejemplos que nos ofrecían y la ayuda de Manuel, ha sido más llevadero. • Desarrollo de interfaces visuales. He desarrollado en este proyecto las interfaces de los formularios de creación y edición de variables y frames, el menú principal, la cabecera, la vista de código y los frames de salida. La parte visual que no he desarrollado es de la que se ha encargado mi compañero, en los frames de entrada, la visualización de las variables y el movimiento de éstas. El cambio entre pantallas y la ocultación de ciertas partes de las vistas en función de la pantalla en la que nos encontremos también han sido parte de mi trabajo en este apartado. Para la parte visual como hemos comentado he utilizado librerías con las que ya había trabajado anteriormente, como Bootstrap y otras nuevas, como jQuery UI. El uso de estas librerías me ha permitido crear las interfaces de una manera bastante sencilla y cómoda de ampliar. En la pantalla de frames de salida he utilizado la función sortable de jQueryUI que tiene una función para transformar el elemento ordenado en un array, lo cual ha hecho bastante cómodo el trabajo con la interfaz y la capa de datos. • Desarrollo de backend. En este punto podemos destacar el desarrollo de la creación de las variables y frames a partir de los datos obtenidos en los formularios y la edición de los datos ya introducidos. De la validación de estos datos se ha encargado mi compañero. • Analizador sintáctico de código Progress. En este apartado he desarrollado las reglas utilizadas para obtener las variables y los frames de salida. Los analizadores sintácticos se generan automáticamente en base a estas reglas y utilizarlos es muy sencillo. Simplemente se llama a su método parse y te devuelve un objeto con la información obtenida. • Lectura del archivo. En relación a este apartado he desarrollado el flujo completo: la lectura del archivo en sí, el uso de los parseadores para obtener los datos y finalmente la transformación del objeto devuelto por los parseadores a mis objetos de las clases Frame y Variable. De nuevo, la validación de éstos datos ha sido desarrollada por Adrián. Diseño interactivo de interfaces gráficas de usuario para Progress 71/75 • Definición de estructura de datos. Como hemos comentado en la memoria, utilizamos clases de JavaScript para definir nuestra estructura de datos, compuesta de una clase Progress, que contendrá un Map de clases Frame y que cada uno de éstos tiene otro Map de clases Variable. La definición de estas clases ha sido llevada en gran medida por mí, exceptuando algunos atributos y funciones que se utilizan para la visualización de las variables en los frames de entrada. • Generación de Código Progress. La generación de código Progress la he desarrollado yo completamente, ya que Adrián no conocía el lenguaje previamente. A la hora de generar este código hay ciertas características que no son elegidas por el usuario. Estas características fijas se pueden encontrar en la sección 4.1.1.-Frames y en la sección 4.1.2.- Variables y son usadas para simplificar la creación de código y ajustarnos a los estándares que define el ERP para sus pantallas. • Pruebas de código Progress. En este punto cabe mencionar que la empresa en la que trabajo, Devel C11, nos cedió un entorno de desarrollo del ERP, en el que poder hacer pruebas con el código Progress que íbamos generando y ver si compilaba y el resultado de la pantalla en el ERP era el esperado. El desarrollo de estas pruebas ha sido parte de mi trabajo en el proyecto. Diseño interactivo de interfaces gráficas de usuario para Progress 72/75 9.2.- CONTRIBUCIÓN ADRIÁN DÍAZ JIMÉNEZ • Estudio de tecnologías. En cuanto se planteó el proyecto al director y fue aprobado, la primera tarea que debíamos hacer era el estudio de tecnologías para llevarlo a cabo. Esta fue mi primera contribución: pensar cuales iban a ser las tecnologías más importantes que podríamos usar para este proyecto, por lo que puedo enumerar las principales: o Electron.JS: estudio e investigación sobre cómo desarrollar una aplicación con este Framework, además estaría pensado para usarlo con JavaScript, aunque mi compañero estudió la posibilidad de utilizar TypeScript. o Elección del analizador sintáctico: revisar varios analizadores sintácticos, ANTLR y PEG.js, al final opté por elegir PEG.js. Por otro lado, este paso se decidió definitivamente en una parte más adelantada del proyecto, ya que mi compañero Ricardo fue el que finalmente estudió este analizador. o Elección de librerías para poder arrastrar y soltar: tenía dudas sobre la conveniencia de utilizar JavaScript nativo o, en su lugar, facilitar el trabajo usando una librería. Al final me decanté por la elección de Interact.JS ya que una vez consultada la documentación y su utilización, me resultó bastante más sencilla que utilizar directamente el código nativo en JavaScript. • Planteamiento del desarrollo del proyecto En este apartado cabe destacar la planificación y planteamiento del desarrollo del proyecto. Este punto es consecuencia del punto anterior. Una vez tenía elegidas las tecnologías que se utilizarían en este proyecto, tuve que plantear cómo se iba a desarrollar, por ejemplo, organización mediante clases, elegir cómo se iban a mostrar los formularios al usuario (ventana nueva o modal), etc. Comencé a generar la aplicación, un proyecto desde cero, y creé las ventanas básicas para poder ver el funcionamiento de Electron.JS, la importación de Bootstrap, y experimentar con jQuery, mediante pruebas muy sencillas. • Desarrollo de la vista de Frames arrastrar-soltar con el ratón / mover con el teclado. Este es el apartado en el cual invertí mayor parte del tiempo, tanto en el estudio de la librería Interact.JS como en la correcta implantación y funcionamiento de la misma. Lo puedo dividir en varias fases ya que como he comentado ha sido la parte más amplia: o Comienzo de movilidad de variables: Estructurar el código HTML, además de comprender las funciones para arrastrar las variables. Desarrollo de las funciones de Diseño interactivo de interfaces gráficas de usuario para Progress 73/75 cálculo de traslación de las variables. En este punto las variables se podían mover a lo largo de toda la ventana. o Movimiento y reposicionamiento de varias variables: volver a estructurar el código HTML y volver a calcular las distancias de traslación respecto al origen, ya que ahora teníamos la fila y la columna en la que se encontraba, pero al clonar los divs y reubicarlos cambiaban las distancias de traslación. Esto se explica en la sección 4.2.1.- Zonas principales. o Restringir el movimiento de las variables: en este apartado puedo comentar que quise restringir el movimiento a ciertas coordenadas, pero no era capaz, por lo que después de muchos intentos opté por restringir el movimiento al ‘div’ del frame: ‘restriction: document.getElementById("inner-dropzone")’ Una vez tenía una pequeña restricción tuve que crear ciertas reglas para que aun así la variable no se saliera de su zona. o Movimiento con teclado: cuando terminé con el movimiento con el ratón, comencé a crear el código para que podamos mover las variables con el teclado. Después de intentar centrar el foco en la variable sin éxito conseguí crear el código centrándome en los datos de la variable que tenemos seleccionada en la vista del Frame. Una vez conseguimos mover las variables con el teclado tuve que crear unas nuevas restricciones para estos movimientos. • Creación de analizadores sintácticos de temp-tables y frames de entrada: he desarrollado el código para poder analizar sintácticamente el código Progress tanto de las ‘temp-tables’ como de los frames de entrada. A raíz de la explicación de Ricardo sobre el funcionamiento de PEG.JS me resultó más sencillo este desarrollo, generando unas reglas muy sencillas siguiendo una serie de pasos. • Validación de datos de entrada: una vez creada toda la funcionalidad del proyecto, era hora de conseguir adaptarnos a las reglas necesarias para que no hubiera problemas a la hora de crear código Progress, por lo que tuve que crear una validación de los datos de entrada del usuario, de modo que se cumplieran ciertas restricciones, por ejemplo: o Comprobar que hay consistencia entre los datos introducidos y el tipo seleccionado para cada variable. o Avisar al usuario de problemas con los datos introducidos. o No permitir ciertos valores vacíos como el nombre de la variable o frame, además de intentar corregir automáticamente los valores omitidos por el usuario como, por ejemplo, los valores iniciales.