xonecode 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -0
- package/dist/agent/authEnDisco.js +56 -0
- package/dist/agent/authEnDisco.js.map +1 -0
- package/dist/agent/configEnDisco.js +109 -0
- package/dist/agent/configEnDisco.js.map +1 -0
- package/dist/agent/crearProyecto.js +34 -0
- package/dist/agent/crearProyecto.js.map +1 -0
- package/dist/agent/entorno.js +124 -0
- package/dist/agent/entorno.js.map +1 -0
- package/dist/agent/guionizado.js +53 -0
- package/dist/agent/guionizado.js.map +1 -0
- package/dist/agent/instantanea.js +129 -0
- package/dist/agent/instantanea.js.map +1 -0
- package/dist/agent/interrupts.js +83 -0
- package/dist/agent/interrupts.js.map +1 -0
- package/dist/agent/mensajes.js +24 -0
- package/dist/agent/mensajes.js.map +1 -0
- package/dist/agent/modelos.js +42 -0
- package/dist/agent/modelos.js.map +1 -0
- package/dist/agent/normalizar.js +20 -0
- package/dist/agent/normalizar.js.map +1 -0
- package/dist/agent/perfiles.js +103 -0
- package/dist/agent/perfiles.js.map +1 -0
- package/dist/agent/proyecto.js +107 -0
- package/dist/agent/proyecto.js.map +1 -0
- package/dist/agent/puente.js +142 -0
- package/dist/agent/puente.js.map +1 -0
- package/dist/agent/resumenDeTool.js +48 -0
- package/dist/agent/resumenDeTool.js.map +1 -0
- package/dist/agent/skills.js +65 -0
- package/dist/agent/skills.js.map +1 -0
- package/dist/agent/textoDeTool.js +113 -0
- package/dist/agent/textoDeTool.js.map +1 -0
- package/dist/agent/turnoReal.js +173 -0
- package/dist/agent/turnoReal.js.map +1 -0
- package/dist/agent/verificador.js +65 -0
- package/dist/agent/verificador.js.map +1 -0
- package/dist/agent/xoneAgent.js +106 -0
- package/dist/agent/xoneAgent.js.map +1 -0
- package/dist/bin.js +9 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/aprobar.js +82 -0
- package/dist/cli/aprobar.js.map +1 -0
- package/dist/cli/config.js +133 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/consola.js +346 -0
- package/dist/cli/consola.js.map +1 -0
- package/dist/cli/describe.js +53 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/doctor.js +45 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/main.js +520 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/markdown.js +90 -0
- package/dist/cli/markdown.js.map +1 -0
- package/dist/cli/run.js +164 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/spinner.js +89 -0
- package/dist/cli/spinner.js.map +1 -0
- package/dist/cli/stdio.js +193 -0
- package/dist/cli/stdio.js.map +1 -0
- package/dist/cli/tema.js +40 -0
- package/dist/cli/tema.js.map +1 -0
- package/dist/cli/verify.js +62 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/core/bitacora.js +30 -0
- package/dist/core/bitacora.js.map +1 -0
- package/dist/core/config.js +236 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/contextos.js +56 -0
- package/dist/core/contextos.js.map +1 -0
- package/dist/core/deps.js +51 -0
- package/dist/core/deps.js.map +1 -0
- package/dist/core/diff.js +79 -0
- package/dist/core/diff.js.map +1 -0
- package/dist/core/esqueleto.js +366 -0
- package/dist/core/esqueleto.js.map +1 -0
- package/dist/core/events.js +2 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/modelos.js +85 -0
- package/dist/core/modelos.js.map +1 -0
- package/dist/core/notify.js +106 -0
- package/dist/core/notify.js.map +1 -0
- package/dist/core/ports.js +114 -0
- package/dist/core/ports.js.map +1 -0
- package/dist/core/turno.js +127 -0
- package/dist/core/turno.js.map +1 -0
- package/dist/vendor/hitl.js +103 -0
- package/dist/vendor/hitl.js.map +1 -0
- package/dist/vendor/skillLoaders/catalog.js +74 -0
- package/dist/vendor/skillLoaders/catalog.js.map +1 -0
- package/dist/vendor/tokenTracking.js +58 -0
- package/dist/vendor/tokenTracking.js.map +1 -0
- package/package.json +41 -0
- package/skills/xone-debugging/SKILL.md +52 -0
- package/skills/xone-debugging/references/faq.md +561 -0
- package/skills/xone-debugging/references/troubleshooting-y-glosario.md +429 -0
- package/skills/xone-development/SKILL.md +105 -0
- package/skills/xone-development/references/anti-patrones.md +94 -0
- package/skills/xone-development/references/css/atributos-por-categoria.md +509 -0
- package/skills/xone-development/references/css/buenas-practicas-y-parser.md +419 -0
- package/skills/xone-development/references/css/dinamicos-cascada-y-componentes.md +550 -0
- package/skills/xone-development/references/css/patrones-material-y-temas.md +1140 -0
- package/skills/xone-development/references/css/propiedades-y-herencia.md +885 -0
- package/skills/xone-development/references/css/selectores-unidades-colores.md +840 -0
- package/skills/xone-development/references/datos/appdata-referencia-ampliada.md +457 -0
- package/skills/xone-development/references/datos/appdata.md +611 -0
- package/skills/xone-development/references/datos/http-sqlmanager-y-crypto.md +720 -0
- package/skills/xone-development/references/datos/http.md +366 -0
- package/skills/xone-development/references/datos/oauth2-y-replica.md +156 -0
- package/skills/xone-development/references/device/biometria-imagedrawing-y-otros.md +544 -0
- package/skills/xone-development/references/device/objetos-de-dispositivo.md +583 -0
- package/skills/xone-development/references/device/systemsettings-referencia-ampliada.md +396 -0
- package/skills/xone-development/references/device/systemsettings-y-permisos.md +342 -0
- package/skills/xone-development/references/fundamentos/conceptos-clave.md +695 -0
- package/skills/xone-development/references/fundamentos/configuracion-app-xml-ini-mappings.md +668 -0
- package/skills/xone-development/references/fundamentos/errores-comunes.md +312 -0
- package/skills/xone-development/references/fundamentos/navegacion-convenciones-y-primer-proyecto.md +576 -0
- package/skills/xone-development/references/fundamentos/plataforma-y-anatomia-de-proyecto.md +387 -0
- package/skills/xone-development/references/indice-completo.md +77 -0
- package/skills/xone-development/references/javascript/coleccion-error-y-usuario.md +260 -0
- package/skills/xone-development/references/javascript/debugging-y-best-practices.md +245 -0
- package/skills/xone-development/references/javascript/metodos-de-los-controles.md +556 -0
- package/skills/xone-development/references/javascript/metodos-nativos-de-la-vista.md +114 -0
- package/skills/xone-development/references/javascript/motor-js-y-contexto-de-ejecucion.md +319 -0
- package/skills/xone-development/references/javascript/objeto-ai-llm-en-dispositivo.md +358 -0
- package/skills/xone-development/references/javascript/objetos-creables-a-m.md +527 -0
- package/skills/xone-development/references/javascript/objetos-creables-n-z.md +385 -0
- package/skills/xone-development/references/javascript/patrones-criticos-seguridad-y-rendimiento.md +595 -0
- package/skills/xone-development/references/javascript/patrones-de-navegacion-datos-y-codigo.md +751 -0
- package/skills/xone-development/references/javascript/patrones-de-ui-voz-integracion-y-seguridad.md +701 -0
- package/skills/xone-development/references/javascript/plantillas-y-funciones-utilitarias.md +647 -0
- package/skills/xone-development/references/javascript/self-y-dataobject.md +449 -0
- package/skills/xone-development/references/javascript/singletons-globales.md +361 -0
- package/skills/xone-development/references/javascript/ui-catalogo-de-metodos.md +464 -0
- package/skills/xone-development/references/javascript/ui-gps-camara-y-multimedia.md +506 -0
- package/skills/xone-development/references/javascript/ui-navegacion-mensajes-y-vista.md +422 -0
- package/skills/xone-development/references/resumen-js-datos-dispositivo.md +80 -0
- package/skills/xone-development/references/resumen-xml-y-css.md +74 -0
- package/skills/xone-development/references/tipos-de-prop.md +28 -0
- package/skills/xone-development/references/xml-ui/asfilter-visibilidad-eventos-y-macros.md +576 -0
- package/skills/xone-development/references/xml-ui/atributos-coll-group-frame.md +235 -0
- package/skills/xone-development/references/xml-ui/atributos-method-macro-script-event-app.md +244 -0
- package/skills/xone-development/references/xml-ui/atributos-prop.md +439 -0
- package/skills/xone-development/references/xml-ui/contents-y-macros.md +392 -0
- package/skills/xone-development/references/xml-ui/errores-comunes-xml.md +245 -0
- package/skills/xone-development/references/xml-ui/estructura-y-nodo-coll.md +326 -0
- package/skills/xone-development/references/xml-ui/eventos-ciclo-de-vida-e-interaccion.md +704 -0
- package/skills/xone-development/references/xml-ui/eventos-sistema-login-y-personalizados.md +944 -0
- package/skills/xone-development/references/xml-ui/layouts-herencia-y-buenas-practicas.md +618 -0
- package/skills/xone-development/references/xml-ui/mapas.md +685 -0
- package/skills/xone-development/references/xml-ui/mappings-y-colecciones-separadas.md +148 -0
- package/skills/xone-development/references/xml-ui/nodos-group-y-frame.md +666 -0
- package/skills/xone-development/references/xml-ui/patrones-de-pantalla.md +643 -0
- package/skills/xone-development/references/xml-ui/prop-atributos-y-condiciones.md +298 -0
- package/skills/xone-development/references/xml-ui/prop-tipos-basicos.md +493 -0
- package/skills/xone-development/references/xml-ui/prop-tipos-combos-y-controles.md +664 -0
- package/skills/xone-development/references/xml-ui/prop-tipos-listas-y-mapas.md +412 -0
- package/skills/xone-plan-builder/SKILL.md +183 -0
- package/skills/xone-plan-builder/agents/openai.yaml +5 -0
- package/skills/xone-plan-builder/references/TASKS-FORMAT.md +132 -0
- package/skills/xone-project-generator/SKILL.md +111 -0
- package/skills/xone-project-generator/references/canonical-sizes.md +292 -0
- package/skills/xone-project-generator/references/colecciones-base.md +16 -0
- package/skills/xone-project-generator/references/convenciones-de-nombres.md +16 -0
- package/skills/xone-project-generator/references/ejemplos-por-sector-y-prohibiciones.md +140 -0
- package/skills/xone-project-generator/references/fase-3-estilos-css.md +597 -0
- package/skills/xone-project-generator/references/fase-6-colecciones.md +762 -0
- package/skills/xone-project-generator/references/fase-7-asfilter-e-integraciones.md +142 -0
- package/skills/xone-project-generator/references/fase-7-entidades-y-estructura-de-pantalla.md +494 -0
- package/skills/xone-project-generator/references/fase-7-plantilla-consola.md +477 -0
- package/skills/xone-project-generator/references/fase-7-plantillas-de-pantalla.md +302 -0
- package/skills/xone-project-generator/references/fase-7-viewmodes-graficos-y-listas.md +681 -0
- package/skills/xone-project-generator/references/fase-7-viewmodes-mapa-y-calendario.md +479 -0
- package/skills/xone-project-generator/references/fases-0-2-analisis-y-modelo-de-datos.md +350 -0
- package/skills/xone-project-generator/references/fases-10-12-readmes-y-validacion.md +194 -0
- package/skills/xone-project-generator/references/fases-4-5-estructura-y-configuracion.md +587 -0
- package/skills/xone-project-generator/references/fases-8-9-eventos-y-javascript.md +861 -0
- package/skills/xone-project-generator/references/flujo-de-generacion.md +67 -0
- package/skills/xone-project-generator/references/plantillas-estandar.md +98 -0
- package/skills/xone-project-generator/references/tamanos-canonicos.md +49 -0
- package/skills/xone-review/SKILL.md +189 -0
- package/skills/xone-spec-builder/SKILL.md +235 -0
- package/skills/xone-spec-builder/agents/openai.yaml +5 -0
- package/skills/xone-spec-builder/references/ADR-FORMAT.md +55 -0
- package/skills/xone-spec-builder/references/CONTEXT-FORMAT.md +42 -0
- package/skills/xone-spec-builder/references/PLAN-FORMAT.md +120 -0
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
# XOne XML — Patrones de pantalla completos
|
|
2
|
+
|
|
3
|
+
> Fuente: `xone/v2/xone-help-docs/topics/02c-xml-contents-patrones.md` §8. Referencia de la skill; el índice está en [../../SKILL.md](../../SKILL.md).
|
|
4
|
+
|
|
5
|
+
Contenido: §8 plantillas completas: login, menú con tarjetas, lista con filtros, formulario de detalle, tabs, mapa, chat, dashboard, maestro-detalle, edición en línea y multi-selección
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 8. Patrones de Pantalla Comunes
|
|
10
|
+
|
|
11
|
+
### 8.1 Pantalla de Login
|
|
12
|
+
|
|
13
|
+
Basado en el proyecto UseCars y el patron del wiki:
|
|
14
|
+
|
|
15
|
+
```xml
|
|
16
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
17
|
+
<coll name="Login" title="Iniciar Sesion"
|
|
18
|
+
special="true" notab="true" show-toolbar="false">
|
|
19
|
+
|
|
20
|
+
<group name="grpPrincipal" id="1" class="groupNoTab">
|
|
21
|
+
<frame name="frmLogin" width="100%" height="100%" bgcolor="#FFFFFF"
|
|
22
|
+
align="center">
|
|
23
|
+
|
|
24
|
+
<!-- Logo -->
|
|
25
|
+
<prop name="imgLogo" type="IMG" visible="1"
|
|
26
|
+
path="logo.png" width="150p" height="150p"
|
|
27
|
+
align="center" tmargin="80p"
|
|
28
|
+
keep-aspect-ratio="true" />
|
|
29
|
+
|
|
30
|
+
<!-- Usuario -->
|
|
31
|
+
<prop name="MAP_USUARIO" type="T" visible="1"
|
|
32
|
+
floating-tooltip="true"
|
|
33
|
+
tooltip="Usuario"
|
|
34
|
+
width="80%" tmargin="60p"
|
|
35
|
+
expanded-hint-color="#1565C0" />
|
|
36
|
+
|
|
37
|
+
<!-- Contraseña -->
|
|
38
|
+
<prop name="MAP_PASSWORD" type="X" visible="1"
|
|
39
|
+
floating-tooltip="true"
|
|
40
|
+
tooltip="Contraseña"
|
|
41
|
+
width="80%" tmargin="30p"
|
|
42
|
+
show-password-visibility-toggle="true" />
|
|
43
|
+
|
|
44
|
+
<!-- Mensaje de error (oculto por defecto) -->
|
|
45
|
+
<frame name="frmError" width="80%"
|
|
46
|
+
disablevisible="MAP_ERROR=''"
|
|
47
|
+
tmargin="10p">
|
|
48
|
+
<prop name="MAP_ERROR" type="L" visible="1"
|
|
49
|
+
forecolor="#F44336" fontsize="12" />
|
|
50
|
+
</frame>
|
|
51
|
+
|
|
52
|
+
<!-- Botón Entrar -->
|
|
53
|
+
<prop name="btnEntrar" type="B" visible="1"
|
|
54
|
+
title="Entrar"
|
|
55
|
+
width="80%" height="56p" tmargin="40p"
|
|
56
|
+
bgcolor="#1565C0" forecolor="#FFFFFF"
|
|
57
|
+
border-corner-radius="28"
|
|
58
|
+
method="executenode(aceptar)" />
|
|
59
|
+
</frame>
|
|
60
|
+
</group>
|
|
61
|
+
|
|
62
|
+
<prop name="MAP_ERROR" type="T" visible="0" />
|
|
63
|
+
|
|
64
|
+
<aceptar>
|
|
65
|
+
<action name="runscript">
|
|
66
|
+
<script language="javascript">
|
|
67
|
+
hacerLogin(self.MAP_USUARIO, self.MAP_PASSWORD);
|
|
68
|
+
</script>
|
|
69
|
+
</action>
|
|
70
|
+
</aceptar>
|
|
71
|
+
|
|
72
|
+
<onback>
|
|
73
|
+
<action name="runscript">
|
|
74
|
+
<script language="javascript">
|
|
75
|
+
appData.exit();
|
|
76
|
+
</script>
|
|
77
|
+
</action>
|
|
78
|
+
</onback>
|
|
79
|
+
</coll>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 8.2 Menu Principal con tarjetas
|
|
83
|
+
|
|
84
|
+
```xml
|
|
85
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
86
|
+
<coll name="MenuPrincipal" special="true"
|
|
87
|
+
notab="true" show-toolbar="false" bgcolor="#F5F5F5">
|
|
88
|
+
|
|
89
|
+
<group name="grpPrincipal" id="1" class="groupNoTab">
|
|
90
|
+
<!-- Header -->
|
|
91
|
+
<frame name="frmHeader" width="100%" height="120p"
|
|
92
|
+
bgcolor="#1565C0" align="center|center">
|
|
93
|
+
<prop name="lblTitulo" type="L" visible="1"
|
|
94
|
+
title="Mi Aplicación"
|
|
95
|
+
forecolor="#FFFFFF" fontsize="20" fontbold="true" />
|
|
96
|
+
</frame>
|
|
97
|
+
|
|
98
|
+
<!-- Cuerpo con tarjetas -->
|
|
99
|
+
<frame name="frmBody" width="100%" height="100%" scroll="true">
|
|
100
|
+
<!-- Tarjeta 1 -->
|
|
101
|
+
<frame name="frmCard1" width="90%" height="100p"
|
|
102
|
+
lmargin="5%" tmargin="20p"
|
|
103
|
+
bgcolor="#FFFFFF" border-corner-radius="8" elevation="3"
|
|
104
|
+
onclick="abrirOpcion('Pedidos');">
|
|
105
|
+
<prop name="imgCard1" type="IMG" visible="1"
|
|
106
|
+
path="ic_pedidos.png"
|
|
107
|
+
width="48p" height="48p" lmargin="20p" tmargin="26p" />
|
|
108
|
+
<prop name="lblCard1" type="L" visible="1"
|
|
109
|
+
title="Pedidos"
|
|
110
|
+
fontsize="16" fontbold="true"
|
|
111
|
+
lmargin="20p" tmargin="30p" newline="false" />
|
|
112
|
+
</frame>
|
|
113
|
+
|
|
114
|
+
<!-- Tarjeta 2 -->
|
|
115
|
+
<frame name="frmCard2" width="90%" height="100p"
|
|
116
|
+
lmargin="5%" tmargin="15p"
|
|
117
|
+
bgcolor="#FFFFFF" border-corner-radius="8" elevation="3"
|
|
118
|
+
onclick="abrirOpcion('Clientes');">
|
|
119
|
+
<prop name="imgCard2" type="IMG" visible="1"
|
|
120
|
+
path="ic_clientes.png"
|
|
121
|
+
width="48p" height="48p" lmargin="20p" tmargin="26p" />
|
|
122
|
+
<prop name="lblCard2" type="L" visible="1"
|
|
123
|
+
title="Clientes"
|
|
124
|
+
fontsize="16" fontbold="true"
|
|
125
|
+
lmargin="20p" tmargin="30p" newline="false" />
|
|
126
|
+
</frame>
|
|
127
|
+
</frame>
|
|
128
|
+
</group>
|
|
129
|
+
|
|
130
|
+
<onback>
|
|
131
|
+
<action name="runscript">
|
|
132
|
+
<script language="javascript">
|
|
133
|
+
appData.exit();
|
|
134
|
+
</script>
|
|
135
|
+
</action>
|
|
136
|
+
</onback>
|
|
137
|
+
</coll>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 8.3 Lista con filtros
|
|
141
|
+
|
|
142
|
+
Basado en el patron del wiki (EspecialContents.xne):
|
|
143
|
+
|
|
144
|
+
```xml
|
|
145
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
146
|
+
<coll name="ListaFiltrada"
|
|
147
|
+
sql="SELECT * FROM ##PREF##Datos"
|
|
148
|
+
objname="Datos" loadall="true"
|
|
149
|
+
notab="true" show-toolbar="false">
|
|
150
|
+
|
|
151
|
+
<group name="Lista" id="1">
|
|
152
|
+
<!-- Barra de busqueda -->
|
|
153
|
+
<prop name="MAP_FILTRO" type="T" visible="1"
|
|
154
|
+
tooltip="Escriba para buscar..."
|
|
155
|
+
labelwidth="0" width="70%"
|
|
156
|
+
ontextchanged="javascript:filtrarLista(e);" />
|
|
157
|
+
|
|
158
|
+
<prop name="BTN_BUSCAR" type="B" visible="1"
|
|
159
|
+
img="lupa.png" labelwidth="0" width="75p"
|
|
160
|
+
method="ExecuteNode(buscar)" newline="false" />
|
|
161
|
+
|
|
162
|
+
<prop name="BTN_ORDENAR" type="B" visible="1"
|
|
163
|
+
img="##FLD_MAP_BTORDEN##" labelwidth="0" width="75p"
|
|
164
|
+
method="ExecuteNode(ordenar)" newline="false" />
|
|
165
|
+
|
|
166
|
+
<!-- Lista con RecyclerView -->
|
|
167
|
+
<frame name="frmLista" width="98%" height="80%"
|
|
168
|
+
framebox="true" border-corner-radius="10" lmargin="1%">
|
|
169
|
+
<prop name="@listaContent" type="Z" visible="1"
|
|
170
|
+
contents="listaContent"
|
|
171
|
+
height="96%"
|
|
172
|
+
viewmode="recyclerview"
|
|
173
|
+
bgcolor="#FFFFFF" />
|
|
174
|
+
<contents name="listaContent" src="DatosLista" />
|
|
175
|
+
</frame>
|
|
176
|
+
</group>
|
|
177
|
+
|
|
178
|
+
<prop name="MAP_BTORDEN" type="T" visible="0" />
|
|
179
|
+
<prop name="MAP_ORDEN" type="T" visible="0" />
|
|
180
|
+
|
|
181
|
+
<selecteditem>
|
|
182
|
+
<action name="runscript">
|
|
183
|
+
<script>
|
|
184
|
+
ui.openEditView(self);
|
|
185
|
+
</script>
|
|
186
|
+
</action>
|
|
187
|
+
</selecteditem>
|
|
188
|
+
</coll>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 8.4 Formulario de detalle/edición
|
|
192
|
+
|
|
193
|
+
```xml
|
|
194
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
195
|
+
<coll name="DetalleCliente"
|
|
196
|
+
sql="SELECT * FROM ##PREF##Clientes"
|
|
197
|
+
objname="Clientes" updateobj="Clientes"
|
|
198
|
+
notab="true" show-toolbar="false">
|
|
199
|
+
|
|
200
|
+
<group name="Detalle" id="1">
|
|
201
|
+
<!-- Header con botones -->
|
|
202
|
+
<frame name="frmHeader" width="100%" height="60p" bgcolor="#1565C0">
|
|
203
|
+
<prop name="BTN_VOLVER" type="B" visible="1"
|
|
204
|
+
img="ic_back.png" labelwidth="0"
|
|
205
|
+
width="48p" height="48p"
|
|
206
|
+
method="executenode(onback)" />
|
|
207
|
+
<prop name="LBL_TITULO" type="L" visible="1"
|
|
208
|
+
title="Detalle Cliente"
|
|
209
|
+
forecolor="#FFFFFF" fontsize="18"
|
|
210
|
+
newline="false" lmargin="10p" />
|
|
211
|
+
</frame>
|
|
212
|
+
|
|
213
|
+
<!-- Formulario -->
|
|
214
|
+
<frame name="frmFormulario" width="100%" height="100%"
|
|
215
|
+
scroll="true" tmargin="10p">
|
|
216
|
+
<prop name="NOMBRE" type="T" visible="1"
|
|
217
|
+
title="Nombre" width="90%" lmargin="5%"
|
|
218
|
+
floating-tooltip="true" tooltip="Nombre del cliente" />
|
|
219
|
+
|
|
220
|
+
<prop name="EMAIL" type="T" visible="1"
|
|
221
|
+
title="Email" width="90%" lmargin="5%" tmargin="10p" />
|
|
222
|
+
|
|
223
|
+
<prop name="TELEFONO" type="N" visible="1"
|
|
224
|
+
title="Teléfono" width="90%" lmargin="5%" tmargin="10p"
|
|
225
|
+
phone="true" />
|
|
226
|
+
|
|
227
|
+
<prop name="DIRECCION" type="T" visible="1"
|
|
228
|
+
title="Dirección" width="90%" lmargin="5%" tmargin="10p"
|
|
229
|
+
lines="3" fixed-lines="true" />
|
|
230
|
+
|
|
231
|
+
<prop name="ACTIVO" type="NC" visible="1"
|
|
232
|
+
title="Cliente activo" width="90%" lmargin="5%" tmargin="10p" />
|
|
233
|
+
|
|
234
|
+
<!-- Botón guardar -->
|
|
235
|
+
<prop name="BTN_GUARDAR" type="B" visible="1"
|
|
236
|
+
title="Guardar" width="90%" height="56p"
|
|
237
|
+
lmargin="5%" tmargin="30p"
|
|
238
|
+
bgcolor="#4CAF50" forecolor="#FFFFFF"
|
|
239
|
+
border-corner-radius="28"
|
|
240
|
+
method="executenode(guardar)" />
|
|
241
|
+
</frame>
|
|
242
|
+
</group>
|
|
243
|
+
|
|
244
|
+
<guardar>
|
|
245
|
+
<action name="runscript">
|
|
246
|
+
<script language="javascript">
|
|
247
|
+
self.save();
|
|
248
|
+
ui.showToast("Cliente guardado correctamente");
|
|
249
|
+
let window = ui.getView(self);
|
|
250
|
+
if (window) window.exit();
|
|
251
|
+
</script>
|
|
252
|
+
</action>
|
|
253
|
+
</guardar>
|
|
254
|
+
|
|
255
|
+
<onback>
|
|
256
|
+
<action name="runscript">
|
|
257
|
+
<script language="javascript">
|
|
258
|
+
let window = ui.getView(self);
|
|
259
|
+
if (window) window.exit();
|
|
260
|
+
</script>
|
|
261
|
+
</action>
|
|
262
|
+
</onback>
|
|
263
|
+
</coll>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 8.5 Pantalla con pestanas (tabs)
|
|
267
|
+
|
|
268
|
+
Basada en el proyecto MiMensajeria:
|
|
269
|
+
|
|
270
|
+
```xml
|
|
271
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
272
|
+
<coll name="AppConTabs" special="true"
|
|
273
|
+
group-theme="material" tab-mode="scrollable">
|
|
274
|
+
|
|
275
|
+
<group name="Chats" id="1" align="center">
|
|
276
|
+
<prop name="LISTA_CHATS" type="Z" visible="1"
|
|
277
|
+
contents="@Chats"
|
|
278
|
+
viewmode="recyclerview"
|
|
279
|
+
width="100%" height="100%"
|
|
280
|
+
show-no-data="true" />
|
|
281
|
+
<contents name="@Chats" src="Conversaciones" />
|
|
282
|
+
</group>
|
|
283
|
+
|
|
284
|
+
<group name="Estados" id="2" align="center">
|
|
285
|
+
<!-- Contenido de estados -->
|
|
286
|
+
</group>
|
|
287
|
+
|
|
288
|
+
<group name="Llamadas" id="3" align="center">
|
|
289
|
+
<!-- Contenido de llamadas -->
|
|
290
|
+
</group>
|
|
291
|
+
|
|
292
|
+
<onback>
|
|
293
|
+
<action name="runscript">
|
|
294
|
+
<script language="javascript">
|
|
295
|
+
appData.exit();
|
|
296
|
+
</script>
|
|
297
|
+
</action>
|
|
298
|
+
</onback>
|
|
299
|
+
</coll>
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### 8.6 Pantalla con mapa
|
|
303
|
+
|
|
304
|
+
Basada en EspecialMapa.xne del wiki:
|
|
305
|
+
|
|
306
|
+
```xml
|
|
307
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
308
|
+
<coll name="PantallaMapa" special="true" notab="true">
|
|
309
|
+
|
|
310
|
+
<group name="Mapa" id="1">
|
|
311
|
+
<frame name="frmMapa" width="100%" height="80%">
|
|
312
|
+
<prop name="MAP_MAPA" type="Z" visible="1"
|
|
313
|
+
viewmode="mapview"
|
|
314
|
+
mapview-embedded="true"
|
|
315
|
+
contents="mapaDatos"
|
|
316
|
+
width="100%" height="100%"
|
|
317
|
+
show-user-location="true" />
|
|
318
|
+
<contents name="mapaDatos" src="ContentMapaDatos" />
|
|
319
|
+
</frame>
|
|
320
|
+
|
|
321
|
+
<!-- Información del punto seleccionado -->
|
|
322
|
+
<frame name="frmInfo" width="100%" height="20%"
|
|
323
|
+
bgcolor="#FFFFFF" tmargin="0">
|
|
324
|
+
<prop name="MAP_NOMBRE" type="T" visible="1"
|
|
325
|
+
title="Nombre" locked="true"
|
|
326
|
+
labelwidth="0" width="96%" lmargin="2%" />
|
|
327
|
+
<prop name="MAP_DIRECCION" type="T" visible="1"
|
|
328
|
+
title="Dirección" locked="true"
|
|
329
|
+
labelwidth="0" width="96%" lmargin="2%" />
|
|
330
|
+
</frame>
|
|
331
|
+
</group>
|
|
332
|
+
|
|
333
|
+
<before-edit refresh="true">
|
|
334
|
+
<action name="runscript">
|
|
335
|
+
<script language="javascript">
|
|
336
|
+
ui.startGps();
|
|
337
|
+
</script>
|
|
338
|
+
</action>
|
|
339
|
+
</before-edit>
|
|
340
|
+
</coll>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### 8.7 Chat
|
|
344
|
+
|
|
345
|
+
Basado en EspecialChat.xne del wiki:
|
|
346
|
+
|
|
347
|
+
```xml
|
|
348
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
349
|
+
<coll name="Chat" title="" special="true" notab="true">
|
|
350
|
+
|
|
351
|
+
<!-- Header con info del contacto -->
|
|
352
|
+
<group name="Header" id="10" fixed="true" orientation="top"
|
|
353
|
+
width="100%" height="120p">
|
|
354
|
+
<frame name="frmHeader" width="100%" height="120p" bgcolor="#1565C0">
|
|
355
|
+
<prop name="BTN_VOLVER" type="B" visible="1"
|
|
356
|
+
img="icon_back.png" width="60p" height="120p"
|
|
357
|
+
method="ExecuteNode(onback)" />
|
|
358
|
+
<prop name="MAP_TITULO" type="L" visible="1"
|
|
359
|
+
forecolor="#FFFFFF" fontbold="true"
|
|
360
|
+
newline="false" lmargin="10p" />
|
|
361
|
+
</frame>
|
|
362
|
+
</group>
|
|
363
|
+
|
|
364
|
+
<!-- Mensajes -->
|
|
365
|
+
<group name="Conversacion" id="1">
|
|
366
|
+
<frame name="frmMensajes" width="100%" height="85%">
|
|
367
|
+
<prop name="Mensajes" type="Z" visible="1"
|
|
368
|
+
contents="Mensajes"
|
|
369
|
+
viewmode="recyclerview"
|
|
370
|
+
bgcolor="#FFFFFF"
|
|
371
|
+
edit-inrow="true"
|
|
372
|
+
width="100%" height="100%" />
|
|
373
|
+
<contents name="Mensajes" src="MensajesChat"
|
|
374
|
+
filter="IDCHAT=##FLD_MAP_CHATSEL##" />
|
|
375
|
+
</frame>
|
|
376
|
+
|
|
377
|
+
<!-- Barra de entrada -->
|
|
378
|
+
<frame name="frmInput" width="100%" height="100p"
|
|
379
|
+
bgcolor="#FFFFFF" align="center">
|
|
380
|
+
<prop name="MAP_TEXTO" type="T" visible="1"
|
|
381
|
+
labelwidth="0" width="80%" height="80p"
|
|
382
|
+
tmargin="10p" lmargin="10p"
|
|
383
|
+
border-corner-radius="20"
|
|
384
|
+
text-border="true" />
|
|
385
|
+
<prop name="BTN_ENVIAR" type="B" visible="1"
|
|
386
|
+
img="icon_send.png"
|
|
387
|
+
labelwidth="0" width="100p" height="100p"
|
|
388
|
+
newline="false"
|
|
389
|
+
method="executenode(enviar)" />
|
|
390
|
+
</frame>
|
|
391
|
+
</group>
|
|
392
|
+
|
|
393
|
+
<prop name="MAP_CHATSEL" type="T" visible="0" />
|
|
394
|
+
</coll>
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### 8.8 Dashboard con estadisticas
|
|
398
|
+
|
|
399
|
+
Basado en EspecialGraficos.xne del wiki:
|
|
400
|
+
|
|
401
|
+
```xml
|
|
402
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
403
|
+
<coll name="Dashboard" special="true"
|
|
404
|
+
group-theme="material" tab-mode="scrollable"
|
|
405
|
+
group-swipe="true">
|
|
406
|
+
|
|
407
|
+
<group name="Ventas" id="1">
|
|
408
|
+
<!-- Gráfico de barras -->
|
|
409
|
+
<frame name="frmBarras" width="98%" height="510p"
|
|
410
|
+
tmargin="14p" lmargin="1%"
|
|
411
|
+
framebox="true" forecolor="#666666" border-width="2">
|
|
412
|
+
<prop name="@GraficoVentas" type="Z"
|
|
413
|
+
classid="XOneCharts"
|
|
414
|
+
viewmode="barchart"
|
|
415
|
+
contents="DatosVentas"
|
|
416
|
+
width="96%" lmargin="2%" height="490p" tmargin="6p" />
|
|
417
|
+
<contents name="DatosVentas" src="ContentGraficoVentas" />
|
|
418
|
+
</frame>
|
|
419
|
+
<prop name="lblVentas" type="L"
|
|
420
|
+
title="Ventas por Mes"
|
|
421
|
+
fontbold="true" lmargin="14p" height="50p" />
|
|
422
|
+
</group>
|
|
423
|
+
|
|
424
|
+
<group name="Categorias" id="2">
|
|
425
|
+
<!-- Gráfico circular -->
|
|
426
|
+
<frame name="frmPie" width="98%" height="510p"
|
|
427
|
+
tmargin="14p" lmargin="1%"
|
|
428
|
+
framebox="true" forecolor="#666666" border-width="2">
|
|
429
|
+
<prop name="@GraficoCategorias" type="Z"
|
|
430
|
+
classid="XOneCharts"
|
|
431
|
+
viewmode="piechart"
|
|
432
|
+
contents="DatosCategorias"
|
|
433
|
+
width="96%" lmargin="2%" height="490p" tmargin="6p" />
|
|
434
|
+
<contents name="DatosCategorias" src="ContentGraficoCategorias" />
|
|
435
|
+
</frame>
|
|
436
|
+
</group>
|
|
437
|
+
|
|
438
|
+
<group name="Tendencia" id="3">
|
|
439
|
+
<!-- Gráfico de lineas -->
|
|
440
|
+
<frame name="frmLineas" width="98%" height="510p"
|
|
441
|
+
tmargin="14p" lmargin="1%"
|
|
442
|
+
framebox="true" forecolor="#666666" border-width="2">
|
|
443
|
+
<prop name="@GraficoTendencia" type="Z"
|
|
444
|
+
classid="XOneCharts"
|
|
445
|
+
viewmode="linechart"
|
|
446
|
+
contents="DatosTendencia"
|
|
447
|
+
width="96%" lmargin="2%" height="490p" tmargin="6p" />
|
|
448
|
+
<contents name="DatosTendencia" src="ContentGraficoTendencia"
|
|
449
|
+
sort="CATEGORIA,VALOR1,VALOR2" />
|
|
450
|
+
</frame>
|
|
451
|
+
</group>
|
|
452
|
+
|
|
453
|
+
<onback>
|
|
454
|
+
<action name="runscript">
|
|
455
|
+
<script language="javascript">
|
|
456
|
+
appData.exit();
|
|
457
|
+
</script>
|
|
458
|
+
</action>
|
|
459
|
+
</onback>
|
|
460
|
+
</coll>
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### 8.9 Patron Maestro-Detalle Completo
|
|
464
|
+
|
|
465
|
+
El patron maestro-detalle combina una coleccion principal (maestro) con un content embebido (detalle). La coleccion maestro muestra una lista de registros; al seleccionar uno, se muestra el formulario de edición con los detalles y sus lineas hijas.
|
|
466
|
+
|
|
467
|
+
```xml
|
|
468
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
469
|
+
<!-- MAESTRO: Lista de pedidos con lineas de detalle -->
|
|
470
|
+
<coll name="Pedidos"
|
|
471
|
+
sql="SELECT p.*, c.NOMBRE AS MAP_CLIENTE
|
|
472
|
+
FROM ##PREF##Pedidos p
|
|
473
|
+
LEFT JOIN ##PREF##Clientes c ON p.IDCLIENTE=c.ID"
|
|
474
|
+
objname="Pedidos" updateobj="Pedidos"
|
|
475
|
+
loadall="true" notab="true" show-toolbar="false"
|
|
476
|
+
autorefresh="true">
|
|
477
|
+
|
|
478
|
+
<group name="Lista" id="1">
|
|
479
|
+
<!-- Campos visibles en grid (visible="4") -->
|
|
480
|
+
<prop name="NUMERO" type="T" visible="4" size="20" />
|
|
481
|
+
<prop name="MAP_CLIENTE" type="T" visible="4" size="100" />
|
|
482
|
+
<prop name="FECHA" type="D" visible="4" />
|
|
483
|
+
<prop name="TOTAL" type="N2" visible="4" />
|
|
484
|
+
|
|
485
|
+
<!-- Campos visibles en edicion (visible="1") -->
|
|
486
|
+
<prop name="MAP_ETIQUETA" type="L" visible="1"
|
|
487
|
+
title="Detalle del Pedido" fontbold="true" fontsize="16"
|
|
488
|
+
tmargin="20p" lmargin="5%" />
|
|
489
|
+
<prop name="NUMERO" type="T" visible="1" title="Número"
|
|
490
|
+
width="90%" lmargin="5%" locked="true" />
|
|
491
|
+
<prop name="MAP_CLIENTE" type="T" visible="1" title="Cliente"
|
|
492
|
+
width="90%" lmargin="5%" locked="true" />
|
|
493
|
+
|
|
494
|
+
<!-- DETALLE: Lineas del pedido embebidas -->
|
|
495
|
+
<prop name="lblLineas" type="L" visible="1"
|
|
496
|
+
title="Lineas del Pedido" fontbold="true"
|
|
497
|
+
tmargin="20p" lmargin="5%" />
|
|
498
|
+
<prop name="@LineasPedido" type="Z" visible="1"
|
|
499
|
+
contents="LineasPedido"
|
|
500
|
+
viewmode="recyclerview"
|
|
501
|
+
width="90%" height="300p" lmargin="5%"
|
|
502
|
+
edit-inrow="true"
|
|
503
|
+
show-no-data="true" />
|
|
504
|
+
</group>
|
|
505
|
+
|
|
506
|
+
<!-- Vinculo content: filtra lineas por ID del pedido padre -->
|
|
507
|
+
<contents name="LineasPedido" src="LineasPedido"
|
|
508
|
+
filter="ID_PEDIDO=##FLD_ID##" />
|
|
509
|
+
|
|
510
|
+
<!-- Al seleccionar un pedido, abrir la vista de edicion -->
|
|
511
|
+
<selecteditem>
|
|
512
|
+
<action name="runscript">
|
|
513
|
+
<script language="javascript">
|
|
514
|
+
ui.openEditView(self);
|
|
515
|
+
</script>
|
|
516
|
+
</action>
|
|
517
|
+
</selecteditem>
|
|
518
|
+
|
|
519
|
+
<create>
|
|
520
|
+
<action name="setval" field="FECHA" value="##NOW##" />
|
|
521
|
+
<action name="setval" field="IDUSUARIO" value="##USERID##" />
|
|
522
|
+
</create>
|
|
523
|
+
</coll>
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
**Puntos clave del patron:**
|
|
527
|
+
- `visible="4"` para campos que solo se ven en el grid (lista).
|
|
528
|
+
- `visible="1"` para campos que solo se ven en edición (formulario).
|
|
529
|
+
- `filter="ID_PEDIDO=##FLD_ID##"` en el contents para vincular las lineas hijas al registro padre.
|
|
530
|
+
- `autorefresh="true"` en la coleccion para que se actualice al volver del detalle.
|
|
531
|
+
|
|
532
|
+
### 8.10 Edición en Linea (edit-inrow)
|
|
533
|
+
|
|
534
|
+
El atributo `edit-inrow="true"` permite editar los campos de una lista directamente dentro de cada fila, sin necesidad de abrir una pantalla de edición aparte. Es ideal para listas de lineas editables (como lineas de pedido o inventario).
|
|
535
|
+
|
|
536
|
+
```xml
|
|
537
|
+
<!-- En la coleccion padre: content con edicion en fila -->
|
|
538
|
+
<prop name="@content2" height="96%" type="Z"
|
|
539
|
+
contents="content2"
|
|
540
|
+
mask="0"
|
|
541
|
+
edit-inrow="true"
|
|
542
|
+
bgcolor="#FFFFFF" />
|
|
543
|
+
<contents name="content2" src="ContentDatosEditRow" autofocus="true" />
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
La coleccion hija (`ContentDatosEditRow`) debe definir dos layouts usando `visible`:
|
|
547
|
+
- `visible="4"` para los campos que se ven en modo **lista** (solo lectura).
|
|
548
|
+
- `visible="7"` para los campos que se ven en modo **edición en fila**.
|
|
549
|
+
|
|
550
|
+
```xml
|
|
551
|
+
<!-- ContentDatosEditRow.xne -->
|
|
552
|
+
<coll name="ContentDatosEditRow" title="Datos Editables"
|
|
553
|
+
sql="SELECT * FROM ##PREF##datosdemo"
|
|
554
|
+
objname="datosdemo" updateobj="datosdemo"
|
|
555
|
+
loadall="true">
|
|
556
|
+
<group name="General" id="1">
|
|
557
|
+
<!-- Layout de grid (solo lectura) -->
|
|
558
|
+
<prop name="IMAGEN" visible="4" type="IMG"
|
|
559
|
+
width="60p" height="60p" lmargin="10p" tmargin="2p" />
|
|
560
|
+
<frame name="frmDatos" newline="false" width="500p" height="100p">
|
|
561
|
+
<prop name="TITULO" visible="4" type="T" size="255"
|
|
562
|
+
class="contentTitulo" lines="1" />
|
|
563
|
+
<prop name="DESCRIPCION" visible="4" type="T" size="255"
|
|
564
|
+
class="contentDescripcion" lines="1" />
|
|
565
|
+
</frame>
|
|
566
|
+
|
|
567
|
+
<!-- Layout de edicion en fila -->
|
|
568
|
+
<prop name="TITULO_EDIT" visible="7" type="T" size="255"
|
|
569
|
+
title="Título" width="90%" />
|
|
570
|
+
<prop name="DESCRIPCION_EDIT" visible="7" type="T" size="255"
|
|
571
|
+
title="Descripción" width="90%" lines="3" />
|
|
572
|
+
</group>
|
|
573
|
+
</coll>
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### 8.11 Multi-selección en Listas
|
|
577
|
+
|
|
578
|
+
Patron para permitir que el usuario seleccione multiples elementos de una lista mediante checkboxes. La coleccion hija incluye un campo `MAP_SELECTED` de tipo `NC` (checkbox) para cada fila.
|
|
579
|
+
|
|
580
|
+
**Coleccion hija con checkbox de selección:**
|
|
581
|
+
|
|
582
|
+
```xml
|
|
583
|
+
<!-- ContentDatosFiltroMultiseleccion.xne -->
|
|
584
|
+
<coll name="ContentMultiseleccion" title="Datos"
|
|
585
|
+
sql="SELECT * FROM ##PREF##datosdemo"
|
|
586
|
+
objname="datosdemo" updateobj="datosdemo"
|
|
587
|
+
loadall="true">
|
|
588
|
+
<group name="General" id="1">
|
|
589
|
+
<frame name="frmDatos" width="100%">
|
|
590
|
+
<prop name="MAP_SELECTED" visible="4" type="NC"
|
|
591
|
+
width="60p" height="60p"
|
|
592
|
+
tmargin="10p" lmargin="10p" />
|
|
593
|
+
<prop name="TITULO" visible="4" type="T"
|
|
594
|
+
newline="false" size="255"
|
|
595
|
+
class="contentTitulo" lines="1" />
|
|
596
|
+
</frame>
|
|
597
|
+
</group>
|
|
598
|
+
</coll>
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
**JavaScript para procesar los elementos seleccionados:**
|
|
602
|
+
|
|
603
|
+
```javascript
|
|
604
|
+
function procesarSeleccionados() {
|
|
605
|
+
var coll = self.getContents("ContentMultiseleccion");
|
|
606
|
+
var n = coll.getCount();
|
|
607
|
+
var seleccionados = [];
|
|
608
|
+
|
|
609
|
+
for (var i = 0; i < n; i++) {
|
|
610
|
+
var obj = coll.getObject(i);
|
|
611
|
+
if (obj.MAP_SELECTED == 1) {
|
|
612
|
+
seleccionados.push(obj.TITULO);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (seleccionados.length > 0) {
|
|
617
|
+
ui.msgBox(seleccionados.join("\n"), "Seleccionados", 0);
|
|
618
|
+
} else {
|
|
619
|
+
ui.showToast("No hay elementos seleccionados");
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
**En la coleccion padre:**
|
|
625
|
+
|
|
626
|
+
```xml
|
|
627
|
+
<!-- Botón para procesar seleccionados -->
|
|
628
|
+
<prop name="BTN_PROCESAR" type="B" visible="1"
|
|
629
|
+
title="Procesar seleccionados"
|
|
630
|
+
onclick="procesarSeleccionados();"
|
|
631
|
+
width="90%" height="56p" lmargin="5%" tmargin="10p"
|
|
632
|
+
bgcolor="#1565C0" forecolor="#FFFFFF"
|
|
633
|
+
border-corner-radius="28" />
|
|
634
|
+
|
|
635
|
+
<!-- Lista con multi-selección -->
|
|
636
|
+
<prop name="@ContentMultiseleccion" type="Z" visible="1"
|
|
637
|
+
contents="ContentMultiseleccion"
|
|
638
|
+
viewmode="recyclerview"
|
|
639
|
+
width="100%" height="70%"
|
|
640
|
+
show-no-data="true" />
|
|
641
|
+
<contents name="ContentMultiseleccion" src="ContentMultiseleccion" />
|
|
642
|
+
```
|
|
643
|
+
|