Vertical carousel still rendered horizontal chevrons (< / >) for the prev / next triggers, which read as wrong-direction even though the click handlers worked correctly. The user complaint "varios clicks" was the visual mismatch making each click look like it did nothing — value WAS advancing index 0→1→2 on each click but the icons pointed sideways in a vertical rail. - Added `orientation` to the eidos carousel context so the prev / next trigger wrappers can pick the right chevron without passing props. - Re-exported `Direction` + `Orientation` from soma's carousel module so the eidos context can type-check them. - Prev trigger now uses `direction='up'` in vertical, `'left'` in horizontal. Next trigger mirrors with `'down'` / `'right'`. Verified: index goes 0→1→2 on successive clicks; chevrons now show `^` (top) and `v` (bottom) in vertical orientation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>active-uix
parent
a6baae0cf1
commit
b1b1e39dc0
@ -0,0 +1,388 @@
|
|||||||
|
# Auditoria Codex de Eidos / UIX demos
|
||||||
|
|
||||||
|
Fecha: 2026-05-23
|
||||||
|
Rama auditada: `active-uix`
|
||||||
|
Ambito principal: `src/uix/eidos/components/*` y demos publicas en
|
||||||
|
`web/routes/uix/components/*`
|
||||||
|
|
||||||
|
## Resumen ejecutivo
|
||||||
|
|
||||||
|
El ecosistema Eidos/UIX ya tiene una base visual y documental amplia: todas las
|
||||||
|
83 demos publicas bajo `web/routes/uix/components` cargan, renderizan `canvas`,
|
||||||
|
`stage` y seis tabs de documentacion; no se detectaron errores de consola en la
|
||||||
|
pasada Playwright de escritorio. Tambien hay coherencia visual general: stage
|
||||||
|
comun, trace strip, controles agrupados, tokens Eidos, props visuales
|
||||||
|
homogeneas y un patron compound bastante estable.
|
||||||
|
|
||||||
|
Pero el resultado no puede considerarse cerrado. La auditoria automatica del
|
||||||
|
repo marca 12 componentes como `NEEDS-WORK`, hay demos que incumplen el contrato
|
||||||
|
obligatorio de snippets, existen gaps de Sema/playback en componentes
|
||||||
|
interactivos y el shell `/uix` no es usable en viewport movil: todas las rutas
|
||||||
|
auditadas desbordan horizontalmente a 390px por un problema del marco de docs.
|
||||||
|
|
||||||
|
El area de mayor riesgo sigue siendo la familia de pickers/calendarios. Han
|
||||||
|
mejorado respecto a los fallos anteriores: hay controles visibles para
|
||||||
|
min/max, minDays/maxDays, modal/inline, footer por composicion, clear/cancel/close
|
||||||
|
y numberOfMonths. Aun asi, DatePicker, DateRangePicker, Tooltip, MonthGrid y
|
||||||
|
YearGrid no cumplen del todo el contrato de playback Sema/demo y necesitan tests
|
||||||
|
funcionales especificos para apertura, seleccion, cierre, limites y navegacion.
|
||||||
|
|
||||||
|
## Evidencia usada
|
||||||
|
|
||||||
|
Comandos y recorridos ejecutados:
|
||||||
|
|
||||||
|
- `npm run component:audit`
|
||||||
|
- Recorrido Playwright desktop `1440x1000` sobre las 83 demos publicas.
|
||||||
|
- Recorrido Playwright mobile `390x844` para detectar overflow del shell.
|
||||||
|
- Capturas del stage de todas las demos en `tmp/uix-audit/screens/*.png`.
|
||||||
|
- Hojas de contacto visuales en:
|
||||||
|
- `tmp/uix-audit/contact-sheet-1.png`
|
||||||
|
- `tmp/uix-audit/contact-sheet-2.png`
|
||||||
|
- `tmp/uix-audit/contact-sheet-3.png`
|
||||||
|
- Resumen estructural en `tmp/uix-audit/quick-summary.json`.
|
||||||
|
- Reporte canonico generado en `tmp/component-audit.md`.
|
||||||
|
|
||||||
|
Nota: habia cambios previos en `src/uix/soma/components/carousel/*`. Esta
|
||||||
|
auditoria observa el estado actual sin revertir ni tocar esos cambios.
|
||||||
|
|
||||||
|
## Resultado cuantitativo
|
||||||
|
|
||||||
|
### `npm run component:audit`
|
||||||
|
|
||||||
|
| Metrica | Resultado |
|
||||||
|
| --- | ---: |
|
||||||
|
| Componentes auditados por contrato | 92 |
|
||||||
|
| PASS | 80 |
|
||||||
|
| NEEDS-WORK | 12 |
|
||||||
|
| BROKEN | 0 |
|
||||||
|
|
||||||
|
### Recorrido visual/funcional Playwright
|
||||||
|
|
||||||
|
| Metrica | Resultado |
|
||||||
|
| --- | ---: |
|
||||||
|
| Demos publicas recorridas | 83 |
|
||||||
|
| Rutas con error HTTP/consola | 0 |
|
||||||
|
| Demos sin `data-uix-canvas-inner` | 0 |
|
||||||
|
| Demos sin `data-uix-stage` | 0 |
|
||||||
|
| Demos sin seis tabs declaradas | 0 |
|
||||||
|
| Overflow desktop | 0 |
|
||||||
|
| Overflow mobile | 83 |
|
||||||
|
| Demos con menos de 2 bloques de snippet en Live | 5 |
|
||||||
|
|
||||||
|
El dato de overflow mobile es sistemico: los valores se repiten en todas las
|
||||||
|
rutas, por lo que apunta al shell `/uix` y no a un componente concreto.
|
||||||
|
|
||||||
|
## Hallazgos P1
|
||||||
|
|
||||||
|
### P1.1 — 12 componentes no pasan el auditor canonico
|
||||||
|
|
||||||
|
Estos componentes no deberian declararse cerrados:
|
||||||
|
|
||||||
|
| Componente | Errores principales |
|
||||||
|
| --- | --- |
|
||||||
|
| `alert-dialog` | Falta selector root `[data-alert-dialog]` en recipe. |
|
||||||
|
| `button` | Verbo Sema `action` invalido, mismatch `commit.action`, falta README. |
|
||||||
|
| `carousel` | Falta README y falta `somaSnippet` en demo. |
|
||||||
|
| `command` | Falta README, no hay `:focus-visible`, falta APG, tipografia literal. |
|
||||||
|
| `grid-list` | Falta README, color raw `#fff`, falta `somaSnippet`, readonly sin estilo. |
|
||||||
|
| `link-preview` | Falta README, tipografia literal. |
|
||||||
|
| `listbox` | Falta README, readonly sin estilo, tipografia literal. |
|
||||||
|
| `menubar` | Falta README, tipografia literal. |
|
||||||
|
| `navigation-menu` | Falta README, falta `somaSnippet`, falta APG. |
|
||||||
|
| `range-calendar` | Falta README, falta `somaSnippet`, readonly sin estilo. |
|
||||||
|
| `search-field` | No hay `:focus-visible`, falta APG, readonly sin estilo. |
|
||||||
|
| `time-range-field` | Falta README, falta `somaSnippet`, readonly/invalid sin estilo. |
|
||||||
|
|
||||||
|
Accion: cerrar primero estos 12 antes de seguir ampliando componentes. El
|
||||||
|
script ya da la lista exacta de reglas incumplidas.
|
||||||
|
|
||||||
|
### P1.2 — El shell `/uix` no es responsive en mobile
|
||||||
|
|
||||||
|
En viewport `390x844`, todas las demos desbordan horizontalmente. El overflow
|
||||||
|
detectado es practicamente constante (`+495` a `+529px`), lo que indica un
|
||||||
|
problema del layout documental: rail/sidebar/canvas con anchura minima fija o
|
||||||
|
grid no colapsado.
|
||||||
|
|
||||||
|
Impacto:
|
||||||
|
|
||||||
|
- No se puede auditar mobile por componente con fiabilidad.
|
||||||
|
- Los overlays, popovers y pickers quedan condicionados por un marco que ya
|
||||||
|
esta roto.
|
||||||
|
- La web de docs no cumple un minimo de consumo movil.
|
||||||
|
|
||||||
|
Accion:
|
||||||
|
|
||||||
|
- Revisar `web/routes/uix/+layout@.svelte` y `web/routes/uix/uix.css`.
|
||||||
|
- Definir breakpoint real para ocultar/convertir sidebar en drawer.
|
||||||
|
- Asegurar que `data-uix-canvas-inner`, tabs, stage y tablas no fuerzan
|
||||||
|
`min-width` por encima del viewport.
|
||||||
|
- Repetir auditoria mobile tras corregir el shell.
|
||||||
|
|
||||||
|
### P1.3 — Demos con contrato Live incompleto: falta `somaSnippet`
|
||||||
|
|
||||||
|
El contrato de `DEMO_AUTHORING_GUIDE.md` exige snippets Soma y Eidos en Live.
|
||||||
|
Faltan en:
|
||||||
|
|
||||||
|
- `carousel`
|
||||||
|
- `grid-list`
|
||||||
|
- `navigation-menu`
|
||||||
|
- `range-calendar`
|
||||||
|
- `time-range-field`
|
||||||
|
|
||||||
|
Impacto:
|
||||||
|
|
||||||
|
- La demo no enseña el contrato headless real.
|
||||||
|
- El consumidor ve la capa Eidos pero no la composicion Soma equivalente.
|
||||||
|
- Rompe la promesa de separacion por capas del ecosistema.
|
||||||
|
|
||||||
|
Accion: añadir `somaSnippet` reactivo y comprobar que refleja los controles
|
||||||
|
visibles del stage.
|
||||||
|
|
||||||
|
### P1.4 — Gaps de Sema/playback en componentes interactivos
|
||||||
|
|
||||||
|
Varias demos interactivas no tienen playback Sema normalizado con
|
||||||
|
`data-uix-play` o el auditor avisa que no hay `uix.events.emit(...)`.
|
||||||
|
|
||||||
|
Casos relevantes:
|
||||||
|
|
||||||
|
- `date-picker`: PASS con warning `D-4.3`; no hay `uix.events.emit(...)`.
|
||||||
|
- `date-range-picker`: PASS con warning `D-4.3`; no hay `uix.events.emit(...)`.
|
||||||
|
- `tooltip`: PASS con warning `D-4.3`; no hay playback claro.
|
||||||
|
- `month-grid` y `year-grid`: eventos `nav-step` no siguen la forma
|
||||||
|
`{verb}-X` o `{family}-X`; el play usa chip/boton no estandar.
|
||||||
|
- `button`: usa verbo Sema invalido `action`.
|
||||||
|
- `alert-dialog`: aparece como pasivo aunque la demo muestra acciones de
|
||||||
|
dialogo heredadas; hay que aclarar si el evento pertenece al wrapper o al
|
||||||
|
compuesto.
|
||||||
|
|
||||||
|
Impacto:
|
||||||
|
|
||||||
|
- El usuario no puede verificar eventos desde la tab Sema de forma uniforme.
|
||||||
|
- La documentacion vuelve ambiguo que eventos son propios, heredados o
|
||||||
|
compuestos.
|
||||||
|
- Se rompe la trazabilidad Morfo -> Soma -> Sema -> Eidos.
|
||||||
|
|
||||||
|
Accion:
|
||||||
|
|
||||||
|
- Normalizar todos los botones de playback a `data-uix-play`.
|
||||||
|
- Para componentes compuestos, documentar y listar eventos heredados sin decir
|
||||||
|
que la superficie es 0 si el stage permite acciones visibles.
|
||||||
|
- Corregir nombres de eventos que no respetan el vocabulario Sema.
|
||||||
|
|
||||||
|
### P1.5 — Pickers y calendarios siguen siendo zona de alto riesgo
|
||||||
|
|
||||||
|
Estado visual observado:
|
||||||
|
|
||||||
|
- `calendar` renderiza uno/dos meses con heading centrado y trace funcional.
|
||||||
|
- `range-calendar` renderiza seleccion y rango, pero falla auditor por README y
|
||||||
|
`somaSnippet`.
|
||||||
|
- `date-picker` muestra field + popover + calendar + footer de acciones.
|
||||||
|
- `date-range-picker` muestra dos inputs, dos meses, footer y controles de
|
||||||
|
limites/rango.
|
||||||
|
- `time-picker` y `time-range-picker` muestran popover con sliders y footer.
|
||||||
|
|
||||||
|
Riesgos abiertos:
|
||||||
|
|
||||||
|
- DatePicker/DateRangePicker no tienen playback Sema normalizado.
|
||||||
|
- La apertura por trigger necesita test E2E estable; en una pasada automatizada
|
||||||
|
el selector `data-date-picker-trigger` no dejo el provider en `open`, aunque
|
||||||
|
la captura visual previa si lo muestra abierto.
|
||||||
|
- RangePicker debe tener regresiones automatizadas para:
|
||||||
|
- seleccionar start sin desplazar al mes siguiente de forma inesperada,
|
||||||
|
- seleccionar end sin auto-navegar,
|
||||||
|
- deseleccionar solo endpoint afectado,
|
||||||
|
- mantener start/end con colores diferenciados,
|
||||||
|
- respetar `minValue`, `maxValue`, `minDays`, `maxDays`,
|
||||||
|
- validar min/max invalidos y surfacing via UI/logger,
|
||||||
|
- clear sin cierre accidental,
|
||||||
|
- cancel revirtiendo snapshot de apertura,
|
||||||
|
- modal bloqueando outside click y manteniendo escape/cierre compuesto.
|
||||||
|
|
||||||
|
Accion: crear suite Playwright especifica para `calendar`, `range-calendar`,
|
||||||
|
`date-picker`, `date-range-picker`, `time-picker` y `time-range-picker`.
|
||||||
|
|
||||||
|
## Hallazgos P2
|
||||||
|
|
||||||
|
### P2.1 — Warnings de CSS/token contract
|
||||||
|
|
||||||
|
Hay warnings que no rompen render, pero indican drift con Eidos:
|
||||||
|
|
||||||
|
- Literales tipograficos en `command`, `link-preview`, `listbox`, `menubar`,
|
||||||
|
`code-block`, `field`, `kbd`, `combobox`, `time-range-picker`.
|
||||||
|
- Raw color en `grid-list` (`#fff`).
|
||||||
|
- Estados declarados pero no estilados: `readonly`, `invalid`, segun
|
||||||
|
componente.
|
||||||
|
- `:focus-visible` ausente en `command` y `search-field`.
|
||||||
|
|
||||||
|
Accion:
|
||||||
|
|
||||||
|
- Sustituir literales por tokens o justificar con comentario `/* literal: ... */`.
|
||||||
|
- Eliminar raw color.
|
||||||
|
- Estilar `readonly`/`invalid` donde Morfo los declara.
|
||||||
|
- Añadir focus ring visible a componentes interactivos.
|
||||||
|
|
||||||
|
### P2.2 — Demos con controles presentes pero valor pedagogico desigual
|
||||||
|
|
||||||
|
La plantilla se aplica de forma amplia, pero no siempre con el mismo nivel de
|
||||||
|
claridad:
|
||||||
|
|
||||||
|
- Componentes complejos (`file-upload`, `stepper`, `listbox`, `grid-list`,
|
||||||
|
`range-calendar`, `date-range-picker`) quedan comprimidos en un stage pequeno.
|
||||||
|
- Algunas demos muestran mucho estado en trace, pero el stage no evidencia de
|
||||||
|
un vistazo que cambio produjo cada control.
|
||||||
|
- Los controles de segmentos en `date-range-picker` existen, pero necesitan
|
||||||
|
copy y ejemplo visual mas directo para que se entienda por que start/end
|
||||||
|
segments importan si el usuario tambien elige fechas en calendario.
|
||||||
|
- `pagedNavigation` existe como control, pero deberia acompañarse de estado
|
||||||
|
observable: mes actual antes/despues, step esperado y diferencia cuando hay
|
||||||
|
dos meses.
|
||||||
|
|
||||||
|
Accion:
|
||||||
|
|
||||||
|
- Para componentes compuestos, ampliar el stage o usar escenarios separados
|
||||||
|
dentro de Live.
|
||||||
|
- Añadir microestado visible cuando un control no modifica visualmente de forma
|
||||||
|
obvia el componente.
|
||||||
|
- Evitar controles que solo cambian el snippet o una prop interna sin evidencia
|
||||||
|
visual inmediata.
|
||||||
|
|
||||||
|
### P2.3 — Componentes pasivos con 0 eventos necesitan justificacion visible
|
||||||
|
|
||||||
|
El ecosistema ya acepta componentes pasivos, pero cada demo debe justificarlo.
|
||||||
|
Se ven casos correctos en varias paginas, pero hay que revisar que el README de
|
||||||
|
cada componente pasivo lo deje explicitamente cerrado.
|
||||||
|
|
||||||
|
Watchlist:
|
||||||
|
|
||||||
|
- `avatar`
|
||||||
|
- `breadcrumb`
|
||||||
|
- `field`
|
||||||
|
- `meter`
|
||||||
|
- `progress`
|
||||||
|
- `tooltip`
|
||||||
|
- `time-range-field`
|
||||||
|
|
||||||
|
Accion: cada README debe explicar si el componente es pasivo, estructural o si
|
||||||
|
sus acciones pertenecen a otro componente compuesto.
|
||||||
|
|
||||||
|
## Coherencia visual del ecosistema
|
||||||
|
|
||||||
|
### Lo que esta bien
|
||||||
|
|
||||||
|
- La shell de demo es consistente: header, meta pills, stage, trace y seis tabs.
|
||||||
|
- El lenguaje visual Eidos es reconocible: superficies limpias, bordes suaves,
|
||||||
|
tokens de color, foco morado/primary, estados discretos.
|
||||||
|
- Los componentes compound respetan en general la forma root + hijos attached.
|
||||||
|
- El trace strip ayuda a ver eventos y estado en componentes interactivos.
|
||||||
|
- La mayoria de componentes tienen controles suficientes para explorar size,
|
||||||
|
variant, color, estado y comportamiento.
|
||||||
|
- No hay rutas rotas ni errores de consola en desktop.
|
||||||
|
|
||||||
|
### Lo que baja el nivel
|
||||||
|
|
||||||
|
- El layout movil de docs esta roto.
|
||||||
|
- La auditoria canonica aun marca 12 componentes como no cerrados.
|
||||||
|
- Hay demos que no cumplen la plantilla obligatoria.
|
||||||
|
- Falta una politica cerrada para eventos compuestos/heredados.
|
||||||
|
- Algunos componentes grandes se ven mas como prueba tecnica que como demo
|
||||||
|
pedagogica de producto.
|
||||||
|
- La capa visual depende demasiado de que el usuario sepa interpretar trace y
|
||||||
|
controles; en varios casos el stage deberia explicar por si mismo el cambio.
|
||||||
|
|
||||||
|
## Inventario de demos publicas auditadas
|
||||||
|
|
||||||
|
Renderizan sin error y con stage:
|
||||||
|
|
||||||
|
`accordion`, `alert-dialog`, `aspect-ratio`, `auto-grid`, `avatar`, `banner`,
|
||||||
|
`box`, `breadcrumb`, `button`, `calendar`, `carousel`, `checkbox`, `code`,
|
||||||
|
`code-block`, `collapsible`, `color-field`, `color-picker`, `combobox`,
|
||||||
|
`command`, `container`, `context-menu`, `date-field`, `date-picker`,
|
||||||
|
`date-range-field`, `date-range-picker`, `dialog`, `display`, `drawer`,
|
||||||
|
`dropdown-menu`, `editable`, `field`, `file-upload`, `flex`, `float`, `form`,
|
||||||
|
`grid`, `grid-list`, `group`, `heading`, `highlight`, `icon`, `kbd`, `link`,
|
||||||
|
`link-preview`, `listbox`, `mark`, `menubar`, `meter`, `month-grid`,
|
||||||
|
`navigation-menu`, `number-field`, `pagination`, `pin-input`, `popover`,
|
||||||
|
`progress`, `radio-group`, `range-calendar`, `rating-group`, `scroll-area`,
|
||||||
|
`search-field`, `section`, `select`, `separator`, `slider`, `splitter`,
|
||||||
|
`stack`, `stepper`, `switch`, `tabs`, `tag-group`, `tags-input`, `text`,
|
||||||
|
`time-field`, `time-picker`, `time-range-field`, `time-range-picker`, `toast`,
|
||||||
|
`toggle`, `toggle-group`, `toolbar`, `tooltip`, `wrap`, `year-grid`.
|
||||||
|
|
||||||
|
## Componentes/contratos sin demo publica en `/uix/components`
|
||||||
|
|
||||||
|
El auditor de contratos ve componentes que no tienen demo publica Eidos:
|
||||||
|
|
||||||
|
- `announce`
|
||||||
|
- `clipboard`
|
||||||
|
- `drag-drop`
|
||||||
|
- `feed`
|
||||||
|
- `table`
|
||||||
|
- `tree-grid`
|
||||||
|
- `tree-view`
|
||||||
|
- `virtual-grid`
|
||||||
|
- `virtual-list`
|
||||||
|
|
||||||
|
Esto puede ser correcto si son headless, internos, pendientes o no publicos,
|
||||||
|
pero debe constar explicitamente en el mapa de componentes de la web.
|
||||||
|
|
||||||
|
Tambien existen piezas Eidos internas sin demo publica directa:
|
||||||
|
|
||||||
|
- `_layout`
|
||||||
|
- `picker-shell`
|
||||||
|
- `svg`
|
||||||
|
|
||||||
|
`svg` ya esta documentado como helper interno; `picker-shell` deberia quedar
|
||||||
|
marcado como interno en README/indice para evitar que parezca una omision.
|
||||||
|
|
||||||
|
## Matriz de saneamiento recomendada
|
||||||
|
|
||||||
|
### Fase 1 — Bloqueantes de contrato
|
||||||
|
|
||||||
|
1. Corregir los 12 `NEEDS-WORK` del `component:audit`.
|
||||||
|
2. Añadir READMEs faltantes.
|
||||||
|
3. Añadir `somaSnippet` en las cinco demos incompletas.
|
||||||
|
4. Corregir `button` Sema verb y eventos `nav-step`.
|
||||||
|
5. Añadir `:focus-visible` en `command` y `search-field`.
|
||||||
|
6. Eliminar raw color y literales tipograficos no justificados.
|
||||||
|
|
||||||
|
### Fase 2 — Shell de docs
|
||||||
|
|
||||||
|
1. Hacer responsive `web/routes/uix`.
|
||||||
|
2. Repetir auditoria mobile.
|
||||||
|
3. Asegurar que tablas, snippets y stages se desplazan internamente sin romper
|
||||||
|
el viewport.
|
||||||
|
|
||||||
|
### Fase 3 — Semantica y demos
|
||||||
|
|
||||||
|
1. Normalizar `data-uix-play` y `uix.events.emit(...)`.
|
||||||
|
2. Documentar eventos heredados en componentes compuestos.
|
||||||
|
3. Revisar todos los componentes marcados como 0 eventos.
|
||||||
|
4. Convertir los controles no evidentes en cambios observables.
|
||||||
|
|
||||||
|
### Fase 4 — Pickers/calendarios
|
||||||
|
|
||||||
|
1. Tests E2E para DatePicker y DateRangePicker.
|
||||||
|
2. Tests E2E para Calendar y RangeCalendar.
|
||||||
|
3. Tests E2E para TimePicker y TimeRangePicker.
|
||||||
|
4. Casos obligatorios: uno/dos meses, modal/no-modal, min/max, minDays/maxDays,
|
||||||
|
clear, cancel, close, seleccion/deseleccion parcial, navegacion paged y
|
||||||
|
granularidad `date/month/year` o `hour/minute/second`.
|
||||||
|
|
||||||
|
### Fase 5 — Visual QA repetible
|
||||||
|
|
||||||
|
1. Mantener un script de capturas del stage por componente.
|
||||||
|
2. Generar hoja de contacto por batch.
|
||||||
|
3. Comparar desktop y mobile tras cada tanda.
|
||||||
|
4. No declarar cerrado un componente compuesto sin captura abierta de su
|
||||||
|
overlay/popup/menu.
|
||||||
|
|
||||||
|
## Veredicto
|
||||||
|
|
||||||
|
Eidos/UIX esta en una fase avanzada de cobertura, pero todavia no en una fase
|
||||||
|
cerrada de calidad. La base visual es coherente y la arquitectura por capas se
|
||||||
|
ve en las demos, pero los gaps actuales son de contrato, demo y semantica, no
|
||||||
|
solo de CSS.
|
||||||
|
|
||||||
|
El siguiente trabajo correcto no es crear mas componentes: es cerrar los 12
|
||||||
|
`NEEDS-WORK`, arreglar el shell mobile, normalizar Sema/playback y blindar los
|
||||||
|
pickers con pruebas visuales y funcionales especificas.
|
||||||
Loading…
Reference in new issue