feat(home): import doris dashboard from workspace repo
Migrates workspace-only dashboard work from commits 6f0c5cd, c851073, and d04eff3 into the canonical truenas-stacks repo.
This commit is contained in:
105
home/doris-dashboard/bin/dashboard_server.py
Executable file
105
home/doris-dashboard/bin/dashboard_server.py
Executable file
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from functools import partial
|
||||
from http import HTTPStatus
|
||||
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PUBLIC = ROOT / 'public'
|
||||
DIGEST_ROOT = Path(os.environ.get('DORIS_DIGEST_DIR', '/home/fizzlepoof/.openclaw/workspace/doris-digest'))
|
||||
DIGEST_FEEDBACK = DIGEST_ROOT / 'data' / 'feedback.json'
|
||||
PAPERLESS_STATE = ROOT / 'data' / 'paperless_review_state.json'
|
||||
HOST = os.environ.get('HOST', '0.0.0.0')
|
||||
PORT = int(os.environ.get('PORT', '8787'))
|
||||
|
||||
|
||||
def load_json(path: Path, default):
|
||||
try:
|
||||
return json.loads(path.read_text()) if path.exists() else default
|
||||
except Exception:
|
||||
return default
|
||||
|
||||
|
||||
def save_json(path: Path, value) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(value, indent=2) + '\n')
|
||||
|
||||
|
||||
class Handler(SimpleHTTPRequestHandler):
|
||||
def __init__(self, *args, directory=None, **kwargs):
|
||||
super().__init__(*args, directory=str(PUBLIC), **kwargs)
|
||||
|
||||
def do_POST(self):
|
||||
length = int(self.headers.get('Content-Length', '0') or '0')
|
||||
raw = self.rfile.read(length) if length else b'{}'
|
||||
try:
|
||||
payload = json.loads(raw.decode('utf-8') or '{}')
|
||||
except Exception:
|
||||
return self._json(HTTPStatus.BAD_REQUEST, {'ok': False, 'error': 'invalid_json'})
|
||||
|
||||
if self.path == '/api/topic-feedback':
|
||||
return self._topic_feedback(payload)
|
||||
if self.path == '/api/topic-feedback/reset':
|
||||
return self._topic_reset()
|
||||
if self.path == '/api/paperless-action':
|
||||
return self._paperless_action(payload)
|
||||
return self._json(HTTPStatus.NOT_FOUND, {'ok': False, 'error': 'not_found'})
|
||||
|
||||
def _topic_feedback(self, payload: dict):
|
||||
term = str(payload.get('term', '')).strip()
|
||||
vote = str(payload.get('vote', '')).strip().lower()
|
||||
if not term or vote not in {'up', 'down'}:
|
||||
return self._json(HTTPStatus.BAD_REQUEST, {'ok': False, 'error': 'bad_payload'})
|
||||
items = load_json(DIGEST_FEEDBACK, [])
|
||||
items = [x for x in items if not (str(x.get('origin', '')) == 'dashboard' and str(x.get('term', '')).strip().lower() == term.lower())]
|
||||
items.append({
|
||||
'term': term,
|
||||
'vote': vote,
|
||||
'note': f"Dashboard {'hide' if vote == 'down' else 'prefer'} topic: {term}",
|
||||
'origin': 'dashboard',
|
||||
'source': str(payload.get('source', '')).strip(),
|
||||
'domain': str(payload.get('domain', '')).strip(),
|
||||
})
|
||||
save_json(DIGEST_FEEDBACK, items)
|
||||
return self._json(HTTPStatus.OK, {'ok': True, 'count': len(items)})
|
||||
|
||||
def _topic_reset(self):
|
||||
items = load_json(DIGEST_FEEDBACK, [])
|
||||
items = [x for x in items if str(x.get('origin', '')) != 'dashboard']
|
||||
save_json(DIGEST_FEEDBACK, items)
|
||||
return self._json(HTTPStatus.OK, {'ok': True, 'count': len(items)})
|
||||
|
||||
def _paperless_action(self, payload: dict):
|
||||
item_id = str(payload.get('id', '')).strip()
|
||||
action = str(payload.get('action', '')).strip().lower()
|
||||
if not item_id or action not in {'acknowledge', 'dismiss'}:
|
||||
return self._json(HTTPStatus.BAD_REQUEST, {'ok': False, 'error': 'bad_payload'})
|
||||
state = load_json(PAPERLESS_STATE, {})
|
||||
current = state.get(item_id, {}) if isinstance(state, dict) else {}
|
||||
if action == 'acknowledge':
|
||||
new_status = 'active' if current.get('status') == 'acknowledged' else 'acknowledged'
|
||||
else:
|
||||
new_status = 'dismissed'
|
||||
state[item_id] = {'status': new_status}
|
||||
save_json(PAPERLESS_STATE, state)
|
||||
return self._json(HTTPStatus.OK, {'ok': True, 'id': item_id, 'status': new_status})
|
||||
|
||||
def _json(self, status: HTTPStatus, payload: dict):
|
||||
body = json.dumps(payload).encode('utf-8')
|
||||
self.send_response(status)
|
||||
self.send_header('Content-Type', 'application/json; charset=utf-8')
|
||||
self.send_header('Content-Length', str(len(body)))
|
||||
self.end_headers()
|
||||
self.wfile.write(body)
|
||||
|
||||
def log_message(self, fmt, *args):
|
||||
print('%s - - [%s] %s' % (self.address_string(), self.log_date_time_string(), fmt % args))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
handler = partial(Handler, directory=str(PUBLIC))
|
||||
ThreadingHTTPServer((HOST, PORT), handler).serve_forever()
|
||||
Reference in New Issue
Block a user