124 lines
4.8 KiB
Plaintext
124 lines
4.8 KiB
Plaintext
# cockpit_stats.dspy - Returns dashboard stat cards as Bricks widget JSON
|
|
dbname = get_module_dbname('pipeline-sdlc')
|
|
|
|
async with DBPools().sqlorContext(dbname) as sor:
|
|
# Active projects
|
|
proj = await sor.sqlExe(
|
|
"SELECT COUNT(*) as active FROM sd_projects WHERE status='active'", {})
|
|
active_projects = proj[0].active if proj else 0
|
|
|
|
# Active iterations
|
|
iters = await sor.sqlExe(
|
|
"SELECT COUNT(*) as cnt FROM sd_iterations WHERE status='in_progress'", {})
|
|
active_iters = iters[0].cnt if iters else 0
|
|
|
|
# Open bugs
|
|
bugs = await sor.sqlExe(
|
|
"SELECT COUNT(*) as cnt FROM sd_bugs WHERE status NOT IN ('closed','resolved')", {})
|
|
open_bugs = bugs[0].cnt if bugs else 0
|
|
|
|
# Pending reviews (human tasks)
|
|
reviews = await sor.sqlExe(
|
|
"SELECT COUNT(*) as cnt FROM pipeline_human_tasks WHERE status='pending'", {})
|
|
pending_reviews = reviews[0].cnt if reviews else 0
|
|
|
|
return {
|
|
"widgettype": "ResponsableBox",
|
|
"options": {"gap": "16px", "minWidth": "180px", "width": "100%"},
|
|
"subwidgets": [
|
|
{
|
|
"widgettype": "VBox",
|
|
"options": {
|
|
"css": "card", "cwidth": 23, "cheight": 12,
|
|
"padding": "20px", "bgcolor": "#fff",
|
|
"borderRadius": "8px", "border": "1px solid #e2e8f0",
|
|
"alignItems": "center", "gap": "6px", "cursor": "pointer"
|
|
},
|
|
"binds": [{
|
|
"wid": "self", "event": "click",
|
|
"actiontype": "urlwidget",
|
|
"target": "app.main_content",
|
|
"options": {"url": entire_url("/pipeline-sdlc/sd_projects/")},
|
|
"mode": "replace"
|
|
}],
|
|
"subwidgets": [
|
|
{"widgettype": "Text", "options": {
|
|
"text": f"{active_projects}", "cfontsize": 2.2,
|
|
"color": "#3b82f6", "fontWeight": "bold"
|
|
}},
|
|
{"widgettype": "Text", "options": {
|
|
"text": "活跃项目", "cfontsize": 0.9, "color": "#64748b"
|
|
}}
|
|
]
|
|
},
|
|
{
|
|
"widgettype": "VBox",
|
|
"options": {
|
|
"css": "card", "cwidth": 23, "cheight": 12,
|
|
"padding": "20px", "bgcolor": "#fff",
|
|
"borderRadius": "8px", "border": "1px solid #e2e8f0",
|
|
"alignItems": "center", "gap": "6px", "cursor": "pointer"
|
|
},
|
|
"binds": [{
|
|
"wid": "self", "event": "click",
|
|
"actiontype": "urlwidget",
|
|
"target": "app.main_content",
|
|
"options": {"url": entire_url("/pipeline-sdlc/sd_iterations/")},
|
|
"mode": "replace"
|
|
}],
|
|
"subwidgets": [
|
|
{"widgettype": "Text", "options": {
|
|
"text": f"{active_iters}", "cfontsize": 2.2,
|
|
"color": "#22c55e", "fontWeight": "bold"
|
|
}},
|
|
{"widgettype": "Text", "options": {
|
|
"text": "进行中迭代", "cfontsize": 0.9, "color": "#64748b"
|
|
}}
|
|
]
|
|
},
|
|
{
|
|
"widgettype": "VBox",
|
|
"options": {
|
|
"css": "card", "cwidth": 23, "cheight": 12,
|
|
"padding": "20px", "bgcolor": "#fff",
|
|
"borderRadius": "8px", "border": "1px solid #e2e8f0",
|
|
"alignItems": "center", "gap": "6px", "cursor": "pointer"
|
|
},
|
|
"binds": [{
|
|
"wid": "self", "event": "click",
|
|
"actiontype": "urlwidget",
|
|
"target": "app.main_content",
|
|
"options": {"url": entire_url("/pipeline-sdlc/sd_bugs/")},
|
|
"mode": "replace"
|
|
}],
|
|
"subwidgets": [
|
|
{"widgettype": "Text", "options": {
|
|
"text": f"{open_bugs}", "cfontsize": 2.2,
|
|
"color": "#f59e0b", "fontWeight": "bold"
|
|
}},
|
|
{"widgettype": "Text", "options": {
|
|
"text": "待处理Bug", "cfontsize": 0.9, "color": "#64748b"
|
|
}}
|
|
]
|
|
},
|
|
{
|
|
"widgettype": "VBox",
|
|
"options": {
|
|
"css": "card", "cwidth": 23, "cheight": 12,
|
|
"padding": "20px", "bgcolor": "#fff",
|
|
"borderRadius": "8px", "border": "1px solid #e2e8f0",
|
|
"alignItems": "center", "gap": "6px", "cursor": "pointer"
|
|
},
|
|
"subwidgets": [
|
|
{"widgettype": "Text", "options": {
|
|
"text": f"{pending_reviews}", "cfontsize": 2.2,
|
|
"color": "#8b5cf6", "fontWeight": "bold"
|
|
}},
|
|
{"widgettype": "Text", "options": {
|
|
"text": "待审批", "cfontsize": 0.9, "color": "#64748b"
|
|
}}
|
|
]
|
|
}
|
|
]
|
|
}
|