oasis-dashboard-js-patterns
GitHubOASIS仪表盘前端JS开发规范,涵盖模块化组织、逻辑去重、助手聊天UI、进度状态管理及API调用约定,确保代码一致性与可维护性。
Trigger Scenarios
Install
npx skills add psyray/oasis --skill oasis-dashboard-js-patterns -g -y
SKILL.md
Frontmatter
{
"name": "oasis-dashboard-js-patterns",
"description": "Dashboard JavaScript patterns for OASIS. Use when editing oasis\/static\/js\/dashboard\/*.js, dashboard-app.js, dashboard CSS\/templates, or any frontend\/backend contract (progress, stats, filters, report modal, audit comparison, assistant chat UI)."
}
OASIS Dashboard JS Patterns
- No duplicated logic: Never repeat the same DOM, fetch, formatting, or state-handling logic in multiple files. Extract to the appropriate module (
utils,api, etc.) and import—same rule as Python: one canonical behavior, zero parallel copies. - Keep dashboard code modular by concern (
bootstrap,api,filters,interactions,modal,views,utils,assistant). - Assistant: Chat UI and client logic live in
assistant.jswith shared constants inassistant-constants.js; HTTP calls go throughapi.js(same pattern as other dashboard APIs—no duplicatedfetchwiring inmodal.js). Changing assistant request/response shapes requires updating both JS andoasis/web.pyhandlers together. - Extend the shared
DashboardAppnamespace instead of introducing parallel globals. - Centralize formatting, display helpers, and repeated request/response handling in utility modules; adding a second inline copy of an existing pattern is not acceptable—extend the shared helper instead.
- When fixing UI bugs, update both interaction scripts and matching templates if the issue spans behavior and markup.
- Prefer compatibility-safe fixes that preserve existing dashboard data contracts (
reportfields and optional defaults). - Vulnerability stats come from
statsonformat: "json"rows (total_findings,high_risk, etc.). Reload must passforce=1to both/api/statsand/api/reportswhen refreshing the filesystem-backed index. The same applies to/api/progresswhen forcing a refresh of progress from the index (useDashboardApp.fetchProgress(true)or equivalent so the request includesforce=1). - Scan progress (REST + Socket.IO): Poll
GET /api/progressand map the JSON throughDashboardApp.applyProgressPayloadintoDashboardApp.progressState—do not scatter ad-hoc progress field reads across views. For realtime updates, listen for the Socket.IO eventscan_progress(server emits the same shape as the REST payload). Ifwindow.__OASIS_DASHBOARD__.realtimeEnabled === false(set from the server inoasis/templates/dashboard.html), skip opening the socket and rely on REST only. - Stale progress guard:
applyProgressPayloadignores an incoming payload whenupdated_atis lexicographically older than the currentprogressState.updated_at(valid for UTC ISO-8601 strings fromoasis.report.progress_timestamp_iso()). If the server timestamp format changes, update both Python and this guard (or switch both sides to a comparable numeric epoch). - Shared progress helpers (in
api.js, not duplicated inviews.js):DashboardApp.normalizeProgressNumber,DashboardApp.htmlProgressPhaseLabelWithStatus, andDashboardApp.PhaseRowStatus(frozen object, wire strings aligned withoasis.enums.PhaseRowStatus). - Progress visibility scope: Dashboard progress UI keeps only high-level summary phases (embeddings/scan/deep/graph pipeline). Low-level per-file/per-vulnerability rows (e.g. adaptive subphases) must stay hidden from dashboard payload rendering.
- UI surfaces: Reuse existing progress-related styles in
oasis/static/css/dashboard.cssbefore adding new class names. - Modal preview:
jsonuses/api/report-json/...;mduses/api/report-content/...only for legacy reports (no siblingjson/<stem>.json). - Model filtering UX: Model-tag filtering is multi-select; persist selection state on the card dataset (
selectedModels), reuse shared model helpers fromutils.js, and keep date chips + audit comparison table filtered consistently. - Audit comparison contract: Audit card comparison rows depend on parsed
audit_metricsfrom/api/reports; preferjson/audit_report.jsonmetrics when the sibling file exists (fallback: Markdown parsing). When changing metrics keys (count,avg_score,median_score,max_score,min_score,high,medium,low), updateweb.pyextraction and dashboard table rendering together. Keepaudit-report-paths.js/auditReportJsonSiblingPathaligned with Pythonjson_sibling_for_format_artifact(audit_reportstem). - Severity filter: Tier-band severity filtering must stay aligned with
/api/reports//api/statsquery params; stats payloads exposeseverity_finding_totals(not the legacyseveritieskey). Updatefilters.js,views.js,api.js, andweb.pytogether. - Filtered previews: Wrap preview and metadata fetches with
DashboardApp.urlWithActiveFilters(or equivalent) so/api/report-json,/api/report-html,/api/report-contentrequests cannot bypass the active dashboard filter set—server-side guards inweb.pyare authoritative. - Theme:
bootstrap.jsdefinesTHEME_CHANGE_EVENT(oasis:theme-change),getDashboardChartThemeColors, and theme persistence helpers. Chart.js dashboards (views.js,executive-preview.js) must refresh axis/grid colors when the theme changes—subscribe to the shared event; do not duplicate theme palettes ad hoc.
Report modal architecture (canonical — all report types)
Goal: Every report opened in #report-modal (vulnerability JSON preview, executive MD/HTML, audit MD/HTML, future canonical JSON types) follows one UX/code architecture: compact body, section navigation (TOC buttons or equivalent with stable anchor IDs), optional Chart.js summaries fed by structured data or a small read-only meta endpoint, and one assistant integration path with mode variants (e.g. file/chunk/finding selectors only for vulnerability JSON; scan-wide vs single-report context for executive / audit) — avoid parallel modal pipelines per report kind.
- CSS: Scope under
#report-modal-content; extendoasis/static/css/report_preview.cssand reuse shared classes (report-toc, chart wrappers, section spacing) before adding unrelated class names indashboard.css. - JS: Report “kind” detection and one-shot setup (TOC wiring, chart init, which assistant variant to show) live in one initializer invoked from
modal.js(_finalizeReportModalViewpath) — do not scatter stem/report_typechecks across unrelated modules. - Server: HTML preview composition and meta endpoints belong in
oasis/web.pywith parsing/helpers underoasis/helpers/so executive, audit, and vulnerability stay DRY unless a genuinely different document shape requires a separate template. - Assistant: Any new request field or UI mode is implemented in
assistant.js,api.js, andweb.pytogether; copy strings and labels go throughassistant-constants.js.
Audit (and future modals) should adopt this same skeleton when brought in line — reuse TOC/chart/assistant patterns rather than cloning a second modal stack.
Version History
- ed3afbb Current 2026-09-11 14:59


