From 8ff742c0fe0970d43339b8931054d63b1029591d Mon Sep 17 00:00:00 2001 From: timmy Date: Fri, 10 Jul 2026 17:46:19 +0000 Subject: [PATCH] chore: creative AI-imbued dashboard UI + fallback context endpoint --- docs/ops-fundamentals.md | 25 ++ frontend/index.html | 381 ++++++++++-------- frontend/static/index.html | 309 ++++++++++++++ src/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 151 bytes src/__pycache__/gitea_proxy.cpython-311.pyc | Bin 0 -> 2616 bytes src/__pycache__/main.cpython-311.pyc | Bin 0 -> 6042 bytes src/__pycache__/models.cpython-311.pyc | Bin 0 -> 2808 bytes .../suggestion_engine.cpython-311.pyc | Bin 0 -> 3414 bytes src/__pycache__/views.cpython-311.pyc | Bin 0 -> 700 bytes src/main.py | 24 +- tests/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 153 bytes ...estion_engine.cpython-311-pytest-9.1.1.pyc | Bin 0 -> 2620 bytes 12 files changed, 555 insertions(+), 184 deletions(-) create mode 100644 docs/ops-fundamentals.md create mode 100644 frontend/static/index.html create mode 100644 src/__pycache__/__init__.cpython-311.pyc create mode 100644 src/__pycache__/gitea_proxy.cpython-311.pyc create mode 100644 src/__pycache__/main.cpython-311.pyc create mode 100644 src/__pycache__/models.cpython-311.pyc create mode 100644 src/__pycache__/suggestion_engine.cpython-311.pyc create mode 100644 src/__pycache__/views.cpython-311.pyc create mode 100644 tests/__pycache__/__init__.cpython-311.pyc create mode 100644 tests/__pycache__/test_suggestion_engine.cpython-311-pytest-9.1.1.pyc diff --git a/docs/ops-fundamentals.md b/docs/ops-fundamentals.md new file mode 100644 index 0000000..a499a79 --- /dev/null +++ b/docs/ops-fundamentals.md @@ -0,0 +1,25 @@ +# Release Engineering & Continuous Delivery +- Treat every commit as a deployable artifact. +- Use CI to run tests and build artifacts; use CD to push to staging/production. +- Pin versions, sign artifacts, and audit changes. +- Release trains > hero deploys: small batches, fast feedback. + +# 11 Factor Apps (12 Factor methodology adapted) +1. Codebase: one repo per service, tracked in version control. +2. Dependencies: explicit manifests, lockfiles, isolated environments. +3. Config: env vars/secrets outside code. +4. Backing services: attach databases/queues as resources. +5. Build/run separation: immutable artifacts, separate runtime. +6. Processes: stateless, share nothing, push state out. +7. Port binding: self-contained HTTP service. +8. Concurrency: scale by process model. +9. Disposability: fast startup, graceful shutdown. +10. Dev/prod parity: avoid one-off configs. +11. Logs/logging: treat logs as event streams. + +# Microservices Architecture +- bounded context per service +- async communication where possible +- API contracts + versioning +- independent deployability +- observability: metrics, traces, structured logs diff --git a/frontend/index.html b/frontend/index.html index f0d2c81..b57c92e 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -2,75 +2,86 @@ - + Stackchain Dashboard +
-
Stackchain Dashboard
+
Stackchain Dashboard
Live
- - + +
-
@@ -107,42 +126,28 @@ textarea { resize: vertical; min-height: 120px; } Whiteboard
Click & drag to draw - +
- - + +
-
- -
+ diff --git a/frontend/static/index.html b/frontend/static/index.html new file mode 100644 index 0000000..f0d2c81 --- /dev/null +++ b/frontend/static/index.html @@ -0,0 +1,309 @@ + + + + + +Stackchain Dashboard + + + +
+
Stackchain Dashboard
+
+
Live
+ + + +
+
+ +
+ + +
+
+

Issues

+
Loading…
+
+
+

Pull Requests

+
Loading…
+
+
+ + +
+ + + +
+ +
+ +
+ +
+ + + + diff --git a/src/__pycache__/__init__.cpython-311.pyc b/src/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..46ade8dfd9f2243ab4a1bc7a92346d954a05ceba GIT binary patch literal 151 zcmZ3^%ge<81U~*gSs?l`h=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09tOH02fKfgr3 zxFj(-J2@jUGfy`qu{a|sKd~r9zqlw_KR!M)FS8^*Uaz3?7l%!5eoARhs$CH)P%Fsr VVtyd;ftit!@dE>lC}IYR0RRCOAwB>A literal 0 HcmV?d00001 diff --git a/src/__pycache__/gitea_proxy.cpython-311.pyc b/src/__pycache__/gitea_proxy.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..10713673997b7afdc04c749625b2f334d226aeed GIT binary patch literal 2616 zcmcH)O>YxNbY^#Luj92Hhp!YR;5Ja|h{Q>u1VU(&P?{o8kZ4*7U#w+!gEu%{cXk|- zG*p&SRcRHeE<(Z*t&~GWi-3D8wG!eNtdS+Gk&uvjDYsPV0deY^HF0bwN-t$T-oAP7 z&71c%vp)xeEeP8A3+Jb9hzR}37wb)Wg{&zUp<75tI!>bm{|ae5EhGe7rHKhqKn9vx zmq)s&OLqi>?!m0K70)_W|J6NrK=VDA)t2x!>GA5mMm-6iE*rApH~f>r8|&N9q@er1 zk`gU?i{S^pFe&K)SO>T)@D#umz=MX|uqO!g&=&L%(8F8M!$5D<@h2$O`kbFV9>Yu= z$;>hT*x89QBgs!Mo}b^9qBJ`gkN3Yj(Ax*SfAC0OU*Ag{XMw8F#D#Nb#u;K>V$dAP zXf-DQfdsg7?HC{saI6a^zK&>}3<>ID{rWcgQCL8_Gz2mW2u$;gGw+C|8Cg2ts%Eok zQ&XvFW#Ut|m6`Wa>#C87vfxOLrYvI4ySx}CUf6yYGhfP3b%WS8Pf7G;Pn=j5joVb! zu4*aO%=GB0ow{tPM337f3zk z-`tXa{@a}GjoqI6;>C;Y1?)D6*iR!nM+4%cK+EVZ-=lU6Py=eM@nA2)TLt4Y zFfTkbMrHXb~}yZ8B+3Yf2QnO8eKkHxaxEbmXwoa<>V7(^szGf z@JLA+D=TApeGHB!46cw;sJk5M&IeY#65g>y3#W@a3Lh_jxr$)f3_=oaFKC?F zUaWpxybgpg-e3F>exrDQGmtUvEld;-+)QvzZ!-Y)@q%7FdUJ|%jyD6oyEw6O;D@bu J*EG5r`xidXHH`oO literal 0 HcmV?d00001 diff --git a/src/__pycache__/main.cpython-311.pyc b/src/__pycache__/main.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3bfafea3df615ebea06a52eccd824e0d13c7acc4 GIT binary patch literal 6042 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 literal 0 HcmV?d00001 diff --git a/src/__pycache__/models.cpython-311.pyc b/src/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d8876ba44831b5c7c98094ad79a51be557970e3 GIT binary patch literal 2808 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 literal 0 HcmV?d00001 diff --git a/src/__pycache__/views.cpython-311.pyc b/src/__pycache__/views.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08b27a217f235c5073f9ef71cfa5c7dda1492864 GIT binary patch literal 700 zcmZ8eOK;Oa5T4z2odhQ>P%fn6z=5Jr+5Q6v32`YR6jV6nf{b@V0*)Q+Zc5=40TM;x z4#%8=Q28+libSR0azUqN2GhtH|sKqwTQXjjJY`U8oCu# zsIii^h>ayhz(2wyEi%3A%Ough(n0tnYy{2N<$-EEOajS$B}4z9DV{2?{mc{=ez}ep zbI9r%AnFV41I@oKzbGHw=oP!=A#q2<9aBQQ_nTutwG_V@P;VYxy0f|d E0EaN4hyVZp literal 0 HcmV?d00001 diff --git a/src/main.py b/src/main.py index 2e9eec4..1c4679b 100644 --- a/src/main.py +++ b/src/main.py @@ -18,18 +18,30 @@ app.add_middleware( allow_headers=["*"], ) -app.mount("/static", StaticFiles(directory="frontend/static"), name="static") app.include_router(frontend_router) @app.get("/api/v1/context") async def context() -> JSONResponse: - user_data = await current_user() + try: + user_data = await current_user() + repo_data = await repos() + issues_data = await issues() + prs_data = await pull_requests() + except Exception as e: + return JSONResponse({ + "user": {"id": None, "login": "timmy", "full_name": "Timmy Jr", "email": ""}, + "repos": [], + "issues": [], + "pull_requests": [], + "view": "dashboard", + "deltas": [ + {"panel": "auth", "action": "connect", "target": "stackchain-dashboard backend", "priority": "high"}, + {"panel": "gitea", "action": "set GITEA_URL + GITEA_TOKEN", "target": "/root/stackchain-dashboard/.env or systemd env", "priority": "high"}, + ], + "error": str(e), + }) user_model = User(id=user_data["id"], login=user_data["login"], full_name=user_data.get("full_name", ""), email=user_data.get("email", "")) - repo_data = await repos() - issues_data = await issues() - prs_data = await pull_requests() - repo_models = [ Repo(id=r["id"], name=r["name"], full_name=r["full_name"], description=r.get("description", ""), url=r["html_url"], updated_at=r.get("updated_at", "")) for r in repo_data[:50] diff --git a/tests/__pycache__/__init__.cpython-311.pyc b/tests/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a1ba93aead1c819d1f8ab9d04bd79050288cc7bd GIT binary patch literal 153 zcmZ3^%ge<81U~*gSs?l`h=2h`DC095kTIPhg&~+hlhJP_LlF~@{~09tOGm#bKfgr3 zxFj(-J2@jUGfy`qu{a|sKd~r9za+J|q*y;bJ~J<~BtBlRpz;@oO>TZlX-=wL5i3wL X$oOJ@An}2jk&*EO1B@tQ28sayUxFel literal 0 HcmV?d00001 diff --git a/tests/__pycache__/test_suggestion_engine.cpython-311-pytest-9.1.1.pyc b/tests/__pycache__/test_suggestion_engine.cpython-311-pytest-9.1.1.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cfa7f0e2e74e60df74d1bda37f8bddf0ed2b9182 GIT binary patch literal 2620 zcmcgt&2Q936rWjpzwGP=N`WF(RVbmbv}_V2q$)xY0ZK`QC^f>t+o;xiBnJ9kaEkZ@7cTC1ZYduit+g8nKy5~ z-p9}17YYV}a`EGfH;-wA{EnS&Np%{Vm!WZ=IK-hosnGbF3bbm9l0dJdDUPK4OpvW) zgIpyS5(p7pwh&of|<+|@rvfFhg zq|zr@R8#sVg7Fen*=j9_>XKDECyGBgKsYklEK@w51nd@vIw?nU^atq`ose~SlQK^v z&gc}-qE5!if^P0XekB8%@FvBj^Hiq0Jwh79g{MKESuf=n_lV4H(@Qy~OIBc)_1;eB z$Ovu=6^)c$i&(hz+KiOZ=+Mx%xupy*;vSi>9!xQgdr2Q=3TaEG^g6g!X?5;bdlv<5 zbk!bsH;)3`N0XD!`sZnb-h_Tq9C9m;%pVF3`fci)U2q+$GMs(kvDr1M(vcl9e=Vg_ zXxRXYA1OFs4QMlwYgbz8Hf>cM0_Q<{-cV zX_^yBT|D^k%8xfTa=)Iu&^&qJ>v4djZsMI)#$mp+#a7W4U^O{#_-HgYQW8qTPmW{M zaZ~8<#mb8+FJ^>9F z0(oaBmVi!AA(@yUM`u>y?G}0j zT=NhDMioDd@D9QefNrj1Y{j|GktTTw;TXcZ2=4)O^EZ?55HI7v5W+CPvnf0HGN