Esta es una colecci贸n de notas que pretenden explicar el funcionamiento interno de Keira3 con fines de desarrollo.
Si s贸lo quieres usar Keira3, no necesitas nada de lo siguiente. Si quieres modificar Keira3, por ejemplo para mejorarlo o a帽adirle nuevas funciones, puede que esta p谩gina te resulte 煤til.
Keira3 se basa en las siguientes tecnolog铆as web de c贸digo abierto:
TypeScript es el lenguaje principal de Keira3. Es un superconjunto de JavaScript. Si conoces JavaScript y tienes algunos conocimientos b谩sicos de lenguajes POO como Java y C#, ya te sentir谩s bastante familiarizado con TypeScript. Si no es as铆, puede que te resulte 煤til este curso. Si no sabes nada de JavaScript, ser谩 mejor que adquieras primero unos conocimientos b谩sicos.
Angular. Este es el framework principal de Keira3. Recomendamos encarecidamente familiarizarse con 茅l antes de meter las manos en el c贸digo de Keira3. Si buscas un curso completo de Angular, te recomendamos este.
Utilizamos SCSS para dar estilo a nuestra interfaz de usuario. Es una extensi贸n de CSS. Es necesario conocer los fundamentos de CSS para poder cambiar la interfaz de Keira3. SCSS deber铆a ser bastante intuitivo para cualquiera que entienda de CSS.
Bootstrap es el framework CSS utilizado como base para el estilo de Keira3. No es necesario que seas un experto en Bootstrap, sin embargo te recomendamos que al menos est茅s familiarizado con su Grid system y utilidades como el spacing.
Electron es el framework que permite construir aplicaciones de escritorio utilizando tecnolog铆as web. No utilizamos muchas funciones nativas de Electron, por lo que normalmente no hay que preocuparse por ello cuando se desarrolla Keira3.
Utilizamos automatizaci贸n de pruebas en Keira3 en nuestro ciclo de desarrollo. Para cada pull request / commit, nuestro CI ejecuta autom谩ticamente un mont贸n de pruebas automatizadas.
Concretamente, tenemos:
Unit tests. Todos los archivos *.spec.ts
se ejecutan con ng test
. Mantenemos el 100% de cobertura. Esto significa que si intentas enviar c贸digo no probado, la construcci贸n CI de tu PR fallar谩. Utilizamos el Angular testing framework para ello.
Integration tests. Es todo el archivo *.integration.spec.ts
, tambi茅n se ejecutan con ng test
, junto con las pruebas unitarias. Puedes ver las pruebas de integraci贸n de Keira3 casi como un conjunto de pruebas e2e, la principal diferencia es que todas las interacciones de la DB son burladas. La diferencia entre las pruebas unitarias y las de integraci贸n es: en las pruebas unitarias probamos las unidades simulando todas sus dependencias, mientras que en las pruebas de integraci贸n probamos las "grandes piezas" de Keira3 juntas (simulando s贸lo la BD). Principalmente se utiliza para probar los editores.
E2E tests. Tenemos un peque帽o conjunto de pruebas e2e basadas en Playwright. Por ejemplo, para comprobar la integraci贸n de sqlite. El comando npm run e2e
servir谩 autom谩ticamente la aplicaci贸n y ejecutar谩 las pruebas e2e.
Porque cada vez que modificas tu aplicaci贸n, nunca sabes si est谩s rompiendo alguna funcionalidad existente a menos que pruebes manualmente todo una y otra vez. Cuando tienes pruebas automatizadas, todav铆a no est谩s 100% seguro de no romper cosas existentes, pero al menos pueden darte alguna garant铆a.
Directorios relevantes:
e2e: todos los casos de prueba e2e, aislados de todo lo dem谩s.
src/assets: im谩genes y archivos de estilo global (los archivos de estilo de los componentes se encuentran en src/app
).
src/app: c贸digo fuente de la aplicaci贸n, as铆 como las pruebas unitarias y de integraci贸n.
src/app/config: archivos de configuraci贸n de la aplicaci贸n, como las configuraciones de enrutamiento y las espec铆ficas de la biblioteca.
src/app/features: c贸digo fuente de las principales caracter铆sticas de Keira3 (cada una aislada de las dem谩s). REGLA: una funci贸n NO puede importar nada de otra funci贸n. Si algo est谩 destinado a ser compartido a trav茅s de las caracter铆sticas, entonces debe ser colocado en src/app/shared
.
src/app/main: componentes que no pertenecen a una funci贸n espec铆fica, pero que est谩n aislados. Por ejemplo, el componente ra铆z AppComponent
, la barra lateral, la ventana de inicio de sesi贸n, etc.
src/app/shared: todo tipo de utilidades, m贸dulos, componentes, servicios, clases abstractas, utilidades de prueba, etc... que est谩n destinados a ser utilizados por m谩s de una funci贸n.
El c贸digo de Keira3 est谩 estructurado utilizando POO con t茅cnicas como herencia y tipos gen茅ricos para maximizar la reutilizaci贸n del c贸digo.
Dentro del directorio src/app/shared/abstract
hay una colecci贸n de clases abstractas que est谩n destinadas a ser extendidas por los Componentes y Servicios concretos de Angular que implementar谩n las caracter铆sticas de Keira3.
Si no est谩 familiarizado con la terminolog铆a utilizada hasta ahora, consulte los hiperv铆nculos anteriores antes de continuar.
Keira3 es modular, puedes verlo como una colecci贸n de caracter铆sticas y utilidades compartidas que se organizan en Arquitectura modular.
Normalmente, las caracter铆sticas de Keira3 se caracterizan por los siguientes elementos.
Todas las definiciones de las tablas de AzerothCore DB est谩n definidas en Keira3 dentro de src/app/shared/types
.
Si quieres crear un nuevo editor, primero tienes que crear su definici贸n all铆.
Por ejemplo, Creature es una entidad principal. Si quieres modificar un vendedor (npc_vendor
) o un bot铆n de una criatura (creature_loot_template
), todav铆a tienes que seleccionar (o crear) una Criatura.
Siempre hay una tabla (y por tanto tambi茅n un Editor) para la Entidad Principal. Para las criaturas es creature_template
.
No puedes tener un vendedor, bot铆n, etc... sin tener una criatura primero. En otras palabras, no puedes tener una fila npc_vendor
sin vincularla a una entrada existente de creature_template
.
Otro ejemplo podr铆a ser: no se puede tener una fila en quest_template_addon
sin vincularla a una fila existente de quest_template
. Porque quest_template
es la entidad principal de los editores de Quest.
Un editor suele estar vinculado a una tabla. Por ejemplo, el editor Creature -> Trainer permite editar la tabla npc_trainer
.
Hay dos tipos principales de editores en Keira3:
Son los editores de tablas que contienen una fila por cada entidad.
Por ejemplo, la tabla creature_template_addon
s贸lo puede tener UNA fila para cada criatura. Nunca puedes tener 2 filas que apunten a la misma criatura en esta tabla.
Cada fila est谩 identificada de forma 煤nica por una clave primaria, que es el ID de la entidad seleccionada. T铆picamente en la BD se llaman id
, ID
, entry
, Entry
, etc... s铆, son completamente inconsistentes, pero es lo que heredamos de MaNGOS/TrinityCore. En Keira3 lo llamamos simplemente entityIdField
.
Son los editores que contienen m煤ltiples filas para cada entidad.
Por ejemplo, la tabla npc_vendor
puede tener varias filas que pertenecen a la misma criatura. Cada fila de npc_vendor
representa un art铆culo espec铆fico que es vendido por una criatura espec铆fica. Y una criatura puede vender 0, 1 o muchos art铆culos. Entonces cada criatura puede tener 0, 1 o muchas filas en la tabla npc_vendor
. 驴Tiene sentido, verdad?
Cada fila tiene 2 claves primarias, t铆picamente (pero no siempre) llamadas id
y guid
. En Keira3 las llamamos siempre entityIdField
y entitySecondIdField
. El entityIdField
es el ID de la entidad seleccionada.
Volvamos al ejemplo de npc_vendor
:
entityIdField
ser铆a el ID de la criatura.entitySecondIdField
ser铆a el ID del item.Cada editor en Keira3 tiene su propio Component y Service, donde:
Puede ver un Componente del Editor como la "parte de la interfaz de usuario". Refleja el estado de la tabla que se est谩 editando y contiene un formulario que permite al usuario cambiar sus propiedades. Los componentes son t铆picamente "tontos" (sin mucho c贸digo l贸gico) y se refieren principalmente al c贸digo HTML. Por supuesto, est谩 vinculado al Servicio del Editor.
El Servicio del Editor contiene toda la l贸gica que alimenta a un Editor, as铆 como el estado de la tabla actual que se est谩 editando. Es responsable de llamar al QueryService
cada vez que el usuario edita alguna propiedad para volver a generar las consultas SQL.
Para maximizar la reutilizaci贸n del c贸digo, se han creado las siguientes clases abstractas:
EditorService
: base de todos los Servicios de Redacci贸n.
SingleRowEditorService
: extiende EditorService
, base de todos los servicios de edici贸n de una fila (por ejemplo, CreatureTemplateService
extiende esta clase).
MultiRowEditorService
: extiende EditorService
, base de todos los servicios de edici贸n de varias filas (por ejemplo, CreatureLootTemplateService
extiende esta clase).
EditorComponent
: base de todos los componentes del editor
SingleRowEditorComponent
: extiende EditorComponent
, base de todos los componentes de edici贸n de una fila (por ejemplo, CreatureTemplateComponent
extiende esta clase).
MultiRowEditorComponent
: extiende EditorComponent
, base de todos los componentes del editor de varias filas (por ejemplo, CreatureLootTemplateComponent
extiende esta clase).
Los Handlers son servicios responsables de mantener estados como:
CreatureHandlerService
).Los grupos de editores que se refieren a la misma entidad principal deben compartir un Handler. Por ejemplo, todos los editores de criaturas se refieren al CreatureHandlerService
, todos los editores de Quest se refieren al QuestHandlerService
, y as铆 sucesivamente...
Todas las clases de Handlers extienden la clase abstracta HandlerService
.
Existen varios tipos de selectores que permiten al usuario seleccionar f谩cilmente un valor para un campo determinado.
Los selectores suelen estar a disposici贸n del usuario haciendo clic en el bot贸n con tres puntos:
Existen tres tipos principales de selectores, que se enumeran a continuaci贸n.
El SingleValueSelectorBtnComponent
es un componente reutilizable que permite al usuario seleccionar un valor 煤nico de una lista de valores, para un campo determinado.
Comprobemos por ejemplo el campo exp
de creature_template
, que permite especificar UN valor:
0 - Classic
1 - TBC
2 - WOTLK
Todo lo que tienes que hacer para implementar dicho selector es definir los valores de la lista creando un array de Opci贸n
:
Todas las opciones se encuentran en src/app/shared/constants/options
, por lo que s贸lo tienes que crear un nuevo archivo como el anterior.
A continuaci贸n, debe importar la matriz de opciones, en este caso EXPANSIONS
, en el archivo .ts
de su componente y declararla como PUBLIC READONLY
para que est茅 disponible para la plantilla del componente:
Ahora puedes usarlo en la plantilla .html
del componente a帽adiendo el elemento html keira-single-value-selector-btn
y pasando las siguientes propiedades:
[control]
el control del formulario, por ejemplo editorService.form.controls.exp
(nota: exp
es el nombre del campo).[config]
un objeto que especifica la propiedad options
y name
.[modalClass]
la clase del modal, para poder cambiar el tama帽o del mismo, por ejemplo modal-md
o modal-lg
(opcional).Este es el resultado:
El FlagsSelectorBtnComponent
es otro componente reutilizable muy 煤til que permite al usuario componer un valor a partir de un conjunto de flags (m谩scara de bits), para un campo determinado. Si t茅rminos como bits, m谩scara de bits, flags, etc. te suenan raros, te recomendamos que leas esta p谩gina para entender completamente c贸mo funcionan los valores de las flags.
Veamos, por ejemplo, c贸mo se implementa el campo dynamicflags
de creature_template
.
Primero hay que definir la lista de valores (de bits) creando un array de Flag
:
Todos los valores de las banderas se encuentran en src/app/shared/constants/flags
por lo que puedes crear un nuevo archivo all铆, por ejemplo dynamic-flags.ts
en nuestro caso.
B谩sicamente tienes que definir cu谩l es el significado de cada bit. No hay que olvidar que los bits suelen empezar por cero.
A continuaci贸n, es necesario importar la matriz DYNAMIC_FLAGS
en el archivo .ts
del componente y hacerla disponible para su plantilla .html
declar谩ndola PUBLIC READONLY
:
Ahora s贸lo tienes que usarlo en el html a帽adiendo el componente keira-flags-selector-btn
all铆:
Los atributos de este componente son:
[control]
el control del formulario, por ejemplo editorService.form.controls.dynamicflags
(nota: dynamicflags
es el nombre del campo).[config]
un objeto que especifica la propiedad options
y name
).[modalClass]
la clase del modal, para poder cambiar el tama帽o del mismo, por ejemplo modal-md
o modal-lg
(opcional).Este es el resultado:
Existen otros selectores que permiten al usuario seleccionar valores haciendo una b煤squeda en la BD o en el contenido DBC del sqlite integrado en Keira3.
Puedes encontrar sus implementaciones en src/app/shared/modules/selectors
as铆 como ejemplos de uso en la aplicaci贸n.
Ejemplo: el selector de items.
Se puede utilizar siempre que se necesite un ID de item: