init: rapid_dashboards app from fn_registry
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
settings:
|
||||
title: "fn_registry — Dashboard Demo"
|
||||
refresh: 5s
|
||||
width: 1280
|
||||
height: 800
|
||||
columns: 12
|
||||
|
||||
theme: "dark"
|
||||
|
||||
connections:
|
||||
registry:
|
||||
driver: sqlite
|
||||
path: ../../../registry.db
|
||||
|
||||
queries:
|
||||
total_functions:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) as value FROM functions"
|
||||
refresh: 30s
|
||||
|
||||
total_types:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) as value FROM types"
|
||||
refresh: 30s
|
||||
|
||||
total_proposals:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) as value FROM proposals"
|
||||
refresh: 30s
|
||||
|
||||
functions_by_domain:
|
||||
connection: registry
|
||||
sql: "SELECT domain, COUNT(*) as count FROM functions GROUP BY domain ORDER BY count DESC"
|
||||
refresh: 30s
|
||||
|
||||
functions_by_kind:
|
||||
connection: registry
|
||||
sql: "SELECT kind, COUNT(*) as count FROM functions GROUP BY kind ORDER BY count DESC"
|
||||
refresh: 30s
|
||||
|
||||
functions_by_purity:
|
||||
connection: registry
|
||||
sql: "SELECT purity, COUNT(*) as count FROM functions GROUP BY purity ORDER BY count DESC"
|
||||
refresh: 30s
|
||||
|
||||
functions_by_lang:
|
||||
connection: registry
|
||||
sql: "SELECT lang, COUNT(*) as count FROM functions GROUP BY lang ORDER BY count DESC"
|
||||
refresh: 30s
|
||||
|
||||
recent_functions:
|
||||
connection: registry
|
||||
sql: "SELECT id, kind, lang, domain, purity, description FROM functions ORDER BY updated_at DESC LIMIT 20"
|
||||
refresh: 10s
|
||||
|
||||
tested_ratio:
|
||||
connection: registry
|
||||
sql: "SELECT tested, COUNT(*) as count FROM functions GROUP BY tested"
|
||||
refresh: 30s
|
||||
|
||||
filters: {}
|
||||
|
||||
sections:
|
||||
- id: kpis
|
||||
title: "Overview"
|
||||
widgets:
|
||||
- id: total_fn
|
||||
type: kpi
|
||||
title: "Functions"
|
||||
query: total_functions
|
||||
mapping: { value: "value" }
|
||||
span: 3
|
||||
|
||||
- id: total_tp
|
||||
type: kpi
|
||||
title: "Types"
|
||||
query: total_types
|
||||
mapping: { value: "value" }
|
||||
span: 3
|
||||
|
||||
- id: total_pr
|
||||
type: kpi
|
||||
title: "Proposals"
|
||||
query: total_proposals
|
||||
mapping: { value: "value" }
|
||||
span: 3
|
||||
|
||||
- id: tested_kpi
|
||||
type: kpi
|
||||
title: "Tested Ratio"
|
||||
query: tested_ratio
|
||||
mapping: { value: "count" }
|
||||
span: 3
|
||||
|
||||
- id: distribution
|
||||
title: "Distribution"
|
||||
columns: 4
|
||||
widgets:
|
||||
- id: by_domain
|
||||
type: bar_chart
|
||||
title: "By Domain"
|
||||
query: functions_by_domain
|
||||
mapping: { x: "domain", y: "count" }
|
||||
options: { show_grid: true }
|
||||
span: 1
|
||||
|
||||
- id: by_lang
|
||||
type: bar_chart
|
||||
title: "By Language"
|
||||
query: functions_by_lang
|
||||
mapping: { x: "lang", y: "count" }
|
||||
span: 1
|
||||
|
||||
- id: by_kind
|
||||
type: bar_chart
|
||||
title: "By Kind"
|
||||
query: functions_by_kind
|
||||
mapping: { x: "kind", y: "count" }
|
||||
span: 1
|
||||
|
||||
- id: by_purity
|
||||
type: bar_chart
|
||||
title: "By Purity"
|
||||
query: functions_by_purity
|
||||
mapping: { x: "purity", y: "count" }
|
||||
span: 1
|
||||
|
||||
- id: detail
|
||||
title: "Recent Functions"
|
||||
collapsible: true
|
||||
widgets:
|
||||
- id: recent_table
|
||||
type: table
|
||||
title: "Last 20 Updated"
|
||||
query: recent_functions
|
||||
mapping:
|
||||
columns:
|
||||
- { key: "id", label: "ID" }
|
||||
- { key: "kind", label: "Kind" }
|
||||
- { key: "lang", label: "Lang" }
|
||||
- { key: "domain", label: "Domain" }
|
||||
- { key: "purity", label: "Purity" }
|
||||
- { key: "description", label: "Description" }
|
||||
span: 12
|
||||
@@ -0,0 +1,202 @@
|
||||
settings:
|
||||
title: "fn-registry Apps"
|
||||
refresh: 30s
|
||||
width: 1440
|
||||
height: 900
|
||||
columns: 12
|
||||
|
||||
theme: "emerald"
|
||||
|
||||
connections:
|
||||
registry:
|
||||
driver: sqlite
|
||||
path: ../../registry.db
|
||||
|
||||
queries:
|
||||
# --- KPIs ---
|
||||
total_apps:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) AS value FROM apps"
|
||||
|
||||
apps_go:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) AS value FROM apps WHERE lang = 'go'"
|
||||
|
||||
apps_python:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) AS value FROM apps WHERE lang = 'py'"
|
||||
|
||||
domains_with_apps:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(DISTINCT domain) AS value FROM apps"
|
||||
|
||||
# --- Distribucion ---
|
||||
apps_by_lang:
|
||||
connection: registry
|
||||
sql: "SELECT lang, COUNT(*) AS cantidad FROM apps GROUP BY lang ORDER BY cantidad DESC"
|
||||
|
||||
apps_by_domain:
|
||||
connection: registry
|
||||
sql: "SELECT domain, COUNT(*) AS cantidad FROM apps GROUP BY domain ORDER BY cantidad DESC"
|
||||
|
||||
apps_by_framework:
|
||||
connection: registry
|
||||
sql: |
|
||||
SELECT
|
||||
CASE WHEN framework = '' OR framework IS NULL THEN '(sin framework)' ELSE framework END AS framework,
|
||||
COUNT(*) AS cantidad
|
||||
FROM apps
|
||||
GROUP BY framework
|
||||
ORDER BY cantidad DESC
|
||||
|
||||
# --- Dependencias ---
|
||||
apps_most_deps:
|
||||
connection: registry
|
||||
sql: |
|
||||
SELECT
|
||||
name || ' (' || lang || ')' AS app,
|
||||
(LENGTH(uses_functions) - LENGTH(REPLACE(uses_functions, ',', ''))
|
||||
+ CASE WHEN uses_functions != '[]' AND uses_functions != '' THEN 1 ELSE 0 END) AS dependencias
|
||||
FROM apps
|
||||
WHERE uses_functions != '[]' AND uses_functions != ''
|
||||
ORDER BY dependencias DESC
|
||||
LIMIT 15
|
||||
|
||||
functions_most_used_in_apps:
|
||||
connection: registry
|
||||
sql: |
|
||||
WITH RECURSIVE split_uses(app_id, rest, val) AS (
|
||||
SELECT id, uses_functions || ',', NULL
|
||||
FROM apps
|
||||
WHERE uses_functions != '[]' AND uses_functions != ''
|
||||
UNION ALL
|
||||
SELECT app_id,
|
||||
SUBSTR(rest, INSTR(rest, ',') + 1),
|
||||
TRIM(SUBSTR(rest, 1, INSTR(rest, ',') - 1), ' "[]')
|
||||
FROM split_uses WHERE rest != ''
|
||||
)
|
||||
SELECT val AS funcion, COUNT(*) AS veces
|
||||
FROM split_uses
|
||||
WHERE val IS NOT NULL AND val != '' AND val != ']'
|
||||
GROUP BY val
|
||||
ORDER BY veces DESC
|
||||
LIMIT 15
|
||||
|
||||
# --- Catalogo ---
|
||||
apps_catalog:
|
||||
connection: registry
|
||||
sql: |
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
lang,
|
||||
domain,
|
||||
CASE WHEN framework = '' THEN '-' ELSE framework END AS framework,
|
||||
description,
|
||||
entry_point,
|
||||
updated_at
|
||||
FROM apps
|
||||
ORDER BY domain, name
|
||||
|
||||
filters: {}
|
||||
|
||||
sections:
|
||||
# ---- KPIs ----
|
||||
- id: kpis
|
||||
title: "Overview"
|
||||
columns: 4
|
||||
widgets:
|
||||
- id: total_apps
|
||||
type: kpi
|
||||
title: "Total Apps"
|
||||
query: total_apps
|
||||
mapping: { value: "value" }
|
||||
span: 1
|
||||
|
||||
- id: apps_go
|
||||
type: kpi
|
||||
title: "Apps Go"
|
||||
query: apps_go
|
||||
mapping: { value: "value" }
|
||||
span: 1
|
||||
|
||||
- id: apps_py
|
||||
type: kpi
|
||||
title: "Apps Python"
|
||||
query: apps_python
|
||||
mapping: { value: "value" }
|
||||
span: 1
|
||||
|
||||
- id: domains
|
||||
type: kpi
|
||||
title: "Dominios"
|
||||
query: domains_with_apps
|
||||
mapping: { value: "value" }
|
||||
span: 1
|
||||
|
||||
# ---- Distribucion ----
|
||||
- id: distribution
|
||||
title: "Distribucion"
|
||||
columns: 3
|
||||
widgets:
|
||||
- id: by_lang
|
||||
type: pie_chart
|
||||
title: "Apps por Lenguaje"
|
||||
query: apps_by_lang
|
||||
mapping: { name: "lang", value: "cantidad" }
|
||||
span: 1
|
||||
|
||||
- id: by_domain
|
||||
type: pie_chart
|
||||
title: "Apps por Dominio"
|
||||
query: apps_by_domain
|
||||
mapping: { name: "domain", value: "cantidad" }
|
||||
span: 1
|
||||
|
||||
- id: by_framework
|
||||
type: bar_chart
|
||||
title: "Apps por Framework"
|
||||
query: apps_by_framework
|
||||
mapping: { x: "framework", y: "cantidad" }
|
||||
span: 1
|
||||
|
||||
# ---- Dependencias ----
|
||||
- id: dependencies
|
||||
title: "Dependencias"
|
||||
columns: 2
|
||||
widgets:
|
||||
- id: most_deps
|
||||
type: bar_chart
|
||||
title: "Apps con Mas Dependencias"
|
||||
query: apps_most_deps
|
||||
mapping: { x: "app", y: "dependencias" }
|
||||
options: { horizontal: true, height: 350 }
|
||||
span: 1
|
||||
|
||||
- id: most_used_fns
|
||||
type: bar_chart
|
||||
title: "Funciones Mas Usadas en Apps"
|
||||
query: functions_most_used_in_apps
|
||||
mapping: { x: "funcion", y: "veces" }
|
||||
options: { horizontal: true, height: 350 }
|
||||
span: 1
|
||||
|
||||
# ---- Catalogo ----
|
||||
- id: catalog
|
||||
title: "Catalogo de Apps"
|
||||
widgets:
|
||||
- id: catalog_table
|
||||
type: table
|
||||
title: "Todas las Apps"
|
||||
query: apps_catalog
|
||||
mapping:
|
||||
columns:
|
||||
- { key: "id", label: "ID" }
|
||||
- { key: "name", label: "Nombre" }
|
||||
- { key: "lang", label: "Lang" }
|
||||
- { key: "domain", label: "Dominio" }
|
||||
- { key: "framework", label: "Framework" }
|
||||
- { key: "description", label: "Descripcion" }
|
||||
- { key: "entry_point", label: "Entry Point" }
|
||||
- { key: "updated_at", label: "Actualizado" }
|
||||
span: 12
|
||||
@@ -0,0 +1,285 @@
|
||||
settings:
|
||||
title: "fn-registry Overview"
|
||||
refresh: 30s
|
||||
width: 1440
|
||||
height: 900
|
||||
columns: 12
|
||||
|
||||
theme: "dark"
|
||||
|
||||
connections:
|
||||
registry:
|
||||
driver: sqlite
|
||||
path: ../../registry.db
|
||||
|
||||
queries:
|
||||
# --- KPIs ---
|
||||
total_functions:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) AS value FROM functions"
|
||||
|
||||
functions_with_tests:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) AS value FROM functions WHERE tested = 1"
|
||||
|
||||
functions_without_tests:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) AS value FROM functions WHERE tested = 0"
|
||||
|
||||
total_types:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) AS value FROM types"
|
||||
|
||||
pending_proposals:
|
||||
connection: registry
|
||||
sql: "SELECT COUNT(*) AS value FROM proposals WHERE status = 'pending'"
|
||||
|
||||
# --- Distribucion general ---
|
||||
by_lang:
|
||||
connection: registry
|
||||
sql: "SELECT lang, COUNT(*) AS cantidad FROM functions GROUP BY lang ORDER BY cantidad DESC"
|
||||
|
||||
by_domain:
|
||||
connection: registry
|
||||
sql: "SELECT domain, COUNT(*) AS cantidad FROM functions GROUP BY domain ORDER BY cantidad DESC"
|
||||
|
||||
by_kind:
|
||||
connection: registry
|
||||
sql: "SELECT kind, COUNT(*) AS cantidad FROM functions GROUP BY kind ORDER BY cantidad DESC"
|
||||
|
||||
# --- Analisis profundo ---
|
||||
purity:
|
||||
connection: registry
|
||||
sql: "SELECT purity, COUNT(*) AS cantidad FROM functions GROUP BY purity ORDER BY cantidad DESC"
|
||||
|
||||
most_used:
|
||||
connection: registry
|
||||
sql: |
|
||||
WITH RECURSIVE split_uses(fn_id, rest, val) AS (
|
||||
SELECT id, uses_functions || ',', NULL FROM functions WHERE uses_functions != '[]' AND uses_functions != ''
|
||||
UNION ALL
|
||||
SELECT fn_id,
|
||||
SUBSTR(rest, INSTR(rest, ',') + 1),
|
||||
TRIM(SUBSTR(rest, 1, INSTR(rest, ',') - 1), ' "[]')
|
||||
FROM split_uses WHERE rest != ''
|
||||
)
|
||||
SELECT val AS funcion, COUNT(*) AS veces
|
||||
FROM split_uses
|
||||
WHERE val IS NOT NULL AND val != '' AND val != ']'
|
||||
GROUP BY val
|
||||
ORDER BY veces DESC
|
||||
LIMIT 15
|
||||
|
||||
most_complex:
|
||||
connection: registry
|
||||
sql: |
|
||||
SELECT
|
||||
name || ' (' || lang || ')' AS funcion,
|
||||
(LENGTH(uses_functions) - LENGTH(REPLACE(uses_functions, ',', ''))
|
||||
+ CASE WHEN uses_functions != '[]' AND uses_functions != '' THEN 1 ELSE 0 END) AS dependencias
|
||||
FROM functions
|
||||
WHERE uses_functions != '[]' AND uses_functions != ''
|
||||
ORDER BY dependencias DESC
|
||||
LIMIT 15
|
||||
|
||||
# --- Cobertura y cross-table ---
|
||||
test_coverage_by_domain:
|
||||
connection: registry
|
||||
sql: |
|
||||
SELECT
|
||||
domain,
|
||||
SUM(CASE WHEN tested = 1 THEN 1 ELSE 0 END) AS con_tests,
|
||||
SUM(CASE WHEN tested = 0 THEN 1 ELSE 0 END) AS sin_tests
|
||||
FROM functions
|
||||
GROUP BY domain
|
||||
ORDER BY domain
|
||||
|
||||
lang_by_domain:
|
||||
connection: registry
|
||||
sql: |
|
||||
SELECT
|
||||
domain,
|
||||
SUM(CASE WHEN lang = 'go' THEN 1 ELSE 0 END) AS go,
|
||||
SUM(CASE WHEN lang = 'py' THEN 1 ELSE 0 END) AS python,
|
||||
SUM(CASE WHEN lang = 'bash' THEN 1 ELSE 0 END) AS bash,
|
||||
SUM(CASE WHEN lang = 'ts' THEN 1 ELSE 0 END) AS typescript,
|
||||
COUNT(*) AS total
|
||||
FROM functions
|
||||
GROUP BY domain
|
||||
ORDER BY total DESC
|
||||
|
||||
# --- Tipos y recientes ---
|
||||
types_by_domain:
|
||||
connection: registry
|
||||
sql: |
|
||||
SELECT domain, algebraic, COUNT(*) AS cantidad
|
||||
FROM types
|
||||
GROUP BY domain, algebraic
|
||||
ORDER BY domain, cantidad DESC
|
||||
|
||||
recent_functions:
|
||||
connection: registry
|
||||
sql: |
|
||||
SELECT name, lang, domain, kind, purity, created_at
|
||||
FROM functions
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 20
|
||||
|
||||
filters: {}
|
||||
|
||||
sections:
|
||||
# ---- Fila 0: KPIs ----
|
||||
- id: kpis
|
||||
title: "Overview"
|
||||
widgets:
|
||||
- id: total_fn
|
||||
type: kpi
|
||||
title: "Total Funciones"
|
||||
query: total_functions
|
||||
mapping: { value: "value" }
|
||||
span: 2
|
||||
|
||||
- id: fn_tested
|
||||
type: kpi
|
||||
title: "Con Tests"
|
||||
query: functions_with_tests
|
||||
mapping: { value: "value" }
|
||||
span: 3
|
||||
|
||||
- id: fn_untested
|
||||
type: kpi
|
||||
title: "Sin Tests"
|
||||
query: functions_without_tests
|
||||
mapping: { value: "value" }
|
||||
span: 2
|
||||
|
||||
- id: total_tp
|
||||
type: kpi
|
||||
title: "Total Tipos"
|
||||
query: total_types
|
||||
mapping: { value: "value" }
|
||||
span: 3
|
||||
|
||||
- id: pending_pr
|
||||
type: kpi
|
||||
title: "Proposals Pendientes"
|
||||
query: pending_proposals
|
||||
mapping: { value: "value" }
|
||||
span: 2
|
||||
|
||||
# ---- Fila 1: Distribucion general ----
|
||||
- id: distribution
|
||||
title: "Distribucion"
|
||||
columns: 3
|
||||
widgets:
|
||||
- id: by_lang
|
||||
type: pie_chart
|
||||
title: "Funciones por Lenguaje"
|
||||
query: by_lang
|
||||
mapping: { name: "lang", value: "cantidad" }
|
||||
span: 1
|
||||
|
||||
- id: by_domain
|
||||
type: pie_chart
|
||||
title: "Funciones por Dominio"
|
||||
query: by_domain
|
||||
mapping: { name: "domain", value: "cantidad" }
|
||||
span: 1
|
||||
|
||||
- id: by_kind
|
||||
type: bar_chart
|
||||
title: "Funciones por Kind"
|
||||
query: by_kind
|
||||
mapping: { x: "kind", y: "cantidad" }
|
||||
span: 1
|
||||
|
||||
# ---- Fila 2: Analisis profundo ----
|
||||
- id: analysis
|
||||
title: "Analisis"
|
||||
columns: 3
|
||||
widgets:
|
||||
- id: purity_chart
|
||||
type: bar_chart
|
||||
title: "Puras vs Impuras"
|
||||
query: purity
|
||||
mapping: { x: "purity", y: "cantidad" }
|
||||
span: 1
|
||||
|
||||
- id: most_used
|
||||
type: bar_chart
|
||||
title: "Funciones Mas Usadas por Otras"
|
||||
query: most_used
|
||||
mapping: { x: "funcion", y: "veces" }
|
||||
options: { horizontal: true, height: 400 }
|
||||
span: 1
|
||||
|
||||
- id: most_complex
|
||||
type: bar_chart
|
||||
title: "Mas Complejas (mas dependencias)"
|
||||
query: most_complex
|
||||
mapping: { x: "funcion", y: "dependencias" }
|
||||
options: { horizontal: true, height: 400 }
|
||||
span: 1
|
||||
|
||||
# ---- Fila 3: Cobertura + cross-table ----
|
||||
- id: coverage
|
||||
title: "Cobertura y Lenguajes"
|
||||
columns: 2
|
||||
widgets:
|
||||
- id: test_coverage
|
||||
type: bar_chart
|
||||
title: "Cobertura de Tests por Dominio"
|
||||
query: test_coverage_by_domain
|
||||
mapping:
|
||||
x: "domain"
|
||||
series:
|
||||
- { key: "con_tests", name: "Con Tests", color: "#10b981" }
|
||||
- { key: "sin_tests", name: "Sin Tests", color: "#ef4444" }
|
||||
options: { show_legend: true }
|
||||
span: 1
|
||||
|
||||
- id: lang_domain_table
|
||||
type: table
|
||||
title: "Funciones por Lenguaje y Dominio"
|
||||
query: lang_by_domain
|
||||
mapping:
|
||||
columns:
|
||||
- { key: "domain", label: "Dominio" }
|
||||
- { key: "go", label: "Go" }
|
||||
- { key: "python", label: "Python" }
|
||||
- { key: "bash", label: "Bash" }
|
||||
- { key: "typescript", label: "TypeScript" }
|
||||
- { key: "total", label: "Total" }
|
||||
options:
|
||||
heatmap_columns: ["go", "python", "bash", "typescript", "total"]
|
||||
span: 1
|
||||
|
||||
# ---- Fila 4: Tipos + recientes ----
|
||||
- id: bottom
|
||||
title: "Tipos y Funciones Recientes"
|
||||
columns: 2
|
||||
widgets:
|
||||
- id: types_table
|
||||
type: table
|
||||
title: "Tipos por Dominio y Algebraic"
|
||||
query: types_by_domain
|
||||
mapping:
|
||||
columns:
|
||||
- { key: "domain", label: "Dominio" }
|
||||
- { key: "algebraic", label: "Algebraic" }
|
||||
- { key: "cantidad", label: "Cantidad" }
|
||||
span: 1
|
||||
|
||||
- id: recent_table
|
||||
type: table
|
||||
title: "Funciones Recientes (ultimas 20)"
|
||||
query: recent_functions
|
||||
mapping:
|
||||
columns:
|
||||
- { key: "name", label: "Nombre" }
|
||||
- { key: "lang", label: "Lang" }
|
||||
- { key: "domain", label: "Dominio" }
|
||||
- { key: "kind", label: "Kind" }
|
||||
- { key: "purity", label: "Purity" }
|
||||
- { key: "created_at", label: "Creado" }
|
||||
span: 1
|
||||
Reference in New Issue
Block a user