Skip to content

Commit

Permalink
Merge pull request #76 from grafana/refactor/update-report-to-typescript
Browse files Browse the repository at this point in the history
[refactor] Update report package to use TS
  • Loading branch information
szkiba authored Oct 17, 2023
2 parents afb8e12 + 5717ad5 commit fb6c358
Show file tree
Hide file tree
Showing 29 changed files with 332 additions and 127 deletions.
3 changes: 2 additions & 1 deletion dashboard/assets/packages/report/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"browser": true,
"es2021": true
},
"extends": ["eslint:recommended", "plugin:react/recommended", "prettier"],
"extends": ["eslint:recommended", "plugin:react/recommended", "plugin:@typescript-eslint/recommended", "prettier"],
"ignorePatterns": ["dist", ".eslintrc.json"],
"plugins": ["react", "prettier"],
"parserOptions": {
"ecmaVersion": "latest",
Expand Down
6 changes: 6 additions & 0 deletions dashboard/assets/packages/report/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# SPDX-FileCopyrightText: 2023 Raintank, Inc. dba Grafana Labs
#
# SPDX-License-Identifier: AGPL-3.0-only

dist/
*.md
50 changes: 26 additions & 24 deletions dashboard/assets/packages/report/dist/index.html

Large diffs are not rendered by default.

32 changes: 17 additions & 15 deletions dashboard/assets/packages/report/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@
SPDX-License-Identifier: AGPL-3.0-only
-->

<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link
rel="icon"
type="image/svg+xml"
href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2IiB2aWV3Qm94PSIwIDAgNjcuNzMzIDY3LjczMyIgZmlsbD0iIzdiNjVmYSIgeG1sbnM6dj0iaHR0cHM6Ly92ZWN0YS5pby9uYW5vIj48cGF0aCBkPSJNMy45MDIgNjMuODMxVjEwLjI2NiIvPjxwYXRoIGQ9Ik0zLjAwNSAxMC4yNjZWNjMuODNoMS43OTNWMTAuMjY2eiIvPjxwYXRoIGQ9Ik0zLjkwMiAzLjA5NWwyLjM5MyA3LjE3MUgxLjUwOXoiLz48cGF0aCBkPSJNMy45MDEuMjY0TC4yNjUgMTEuMTYySDcuNTR6bS0uOTM4IDYzLjU2N2g1NC41MDQiLz48cGF0aCBkPSJNMi45NjQgNjIuOTI2djEuODA5aDU0LjUwNHYtMS44MDl6Ii8+PHBhdGggZD0iTTY0LjYzOCA2My44MzFsLTcuMTcxIDIuMzkzdi00Ljc4NnoiLz48cGF0aCBkPSJNNTYuNTcxIDYwLjE5M3Y3LjI3NUw2Ny40NyA2My44M2wtMTAuODk4LTMuNjM3eiIvPjxwYXRoIGQ9Ik01NC4xOTMgNjMuNjg1SDQuNjhsMTYuNDgzLTM1LjE2IDkuOTI5IDcuMjk5IDEyLjk1MS0yMC4xOTJ6IiBmaWxsLW9wYWNpdHk9Ii41MDIiIHN0cm9rZT0iIzdiNjVmYSIgc3Ryb2tlLXdpZHRoPSIxLjg3MyIvPjwvc3ZnPg==" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>k6 report</title>
</head>

<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml"
href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2IiB2aWV3Qm94PSIwIDAgNjcuNzMzIDY3LjczMyIgZmlsbD0iIzdiNjVmYSIgeG1sbnM6dj0iaHR0cHM6Ly92ZWN0YS5pby9uYW5vIj48cGF0aCBkPSJNMy45MDIgNjMuODMxVjEwLjI2NiIvPjxwYXRoIGQ9Ik0zLjAwNSAxMC4yNjZWNjMuODNoMS43OTNWMTAuMjY2eiIvPjxwYXRoIGQ9Ik0zLjkwMiAzLjA5NWwyLjM5MyA3LjE3MUgxLjUwOXoiLz48cGF0aCBkPSJNMy45MDEuMjY0TC4yNjUgMTEuMTYySDcuNTR6bS0uOTM4IDYzLjU2N2g1NC41MDQiLz48cGF0aCBkPSJNMi45NjQgNjIuOTI2djEuODA5aDU0LjUwNHYtMS44MDl6Ii8+PHBhdGggZD0iTTY0LjYzOCA2My44MzFsLTcuMTcxIDIuMzkzdi00Ljc4NnoiLz48cGF0aCBkPSJNNTYuNTcxIDYwLjE5M3Y3LjI3NUw2Ny40NyA2My44M2wtMTAuODk4LTMuNjM3eiIvPjxwYXRoIGQ9Ik01NC4xOTMgNjMuNjg1SDQuNjhsMTYuNDgzLTM1LjE2IDkuOTI5IDcuMjk5IDEyLjk1MS0yMC4xOTJ6IiBmaWxsLW9wYWNpdHk9Ii41MDIiIHN0cm9rZT0iIzdiNjVmYSIgc3Ryb2tlLXdpZHRoPSIxLjg3MyIvPjwvc3ZnPg==" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>k6 report</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
<script id="data" type="application/json; charset=utf-8; gzip; base64">{{{ testdata }}}</script>
<body>

<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<script id="data" type="application/json; charset=utf-8; gzip; base64">
{{{ testdata }}}
</script>
</body>
</html>
18 changes: 14 additions & 4 deletions dashboard/assets/packages/report/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@
"scripts": {
"dev": "vite",
"build": "vite build --emptyOutDir",
"preview": "vite preview"
"preview": "vite preview",
"lint:eslint": "eslint \"./src/**/*.{js,jsx,ts,tsx}\"",
"lint:format": "prettier --ignore-unknown --check \"./**/*\"",
"lint:types": "tsc --noEmit",
"lint": "yarn lint:eslint && yarn lint:types && yarn lint:format"
},
"dependencies": {
"@xk6-dashboard/config": "0.0.1",
"@xk6-dashboard/model": "0.0.1",
"@xk6-dashboard/view": "0.0.1",
"bootstrap": "^5.3.1",
"bootstrap": "^5.3.2",
"preact": "^10.16.0",
"react": "npm:@preact/compat",
"react-dom": "npm:@preact/compat",
Expand All @@ -22,9 +26,15 @@
},
"devDependencies": {
"@preact/preset-vite": "^2.5.0",
"@typescript-eslint/eslint-plugin": "^6.7.5",
"@typescript-eslint/parser": "^6.7.5",
"eslint": "^8.51.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
"sass": "^1.65.1",
"vite": "^4.4.5",
"vite": "^4.4.11",
"vite-plugin-handlebars": "^1.6.0",
"vite-plugin-singlefile": "^0.13.5"
"vite-plugin-singlefile": "^0.13.5",
"vite-tsconfig-paths": "^4.2.1"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
// SPDX-License-Identifier: MIT

import React from "react"
import { Digest } from "@xk6-dashboard/model"

import Tab from "components/Tab"
import "./App.css"

import Tab from "./Tab"
interface AppProps {
digest: Digest
}

export default function App({ digest }) {
export default function App({ digest }: AppProps) {
return (
<article className="container-fluid report">
<h1>k6 report</h1>
Expand Down
5 changes: 5 additions & 0 deletions dashboard/assets/packages/report/src/components/App/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-FileCopyrightText: 2023 Raintank, Inc. dba Grafana Labs
//
// SPDX-License-Identifier: AGPL-3.0-only

export { default } from "./App"
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,39 @@
//
// SPDX-License-Identifier: AGPL-3.0-only

import React from "react"
import React, { Ref } from "react"
import { useRef, useState, useLayoutEffect } from "preact/hooks"

import "uplot/dist/uPlot.min.css"
import UplotReact from "uplot-react"
import uPlot from "uplot"
import uPlot, { AlignedData, Options, Series } from "uplot"

import { SeriesPlot, tooltipPlugin, dateFormats, format } from "@xk6-dashboard/view"
import { Digest } from "@xk6-dashboard/model"
import { Panel, SeriesPlot, tooltipPlugin, dateFormats, format } from "@xk6-dashboard/view"

import colors from "utils/colors"
import "./Chart.css"

import colors from "./colors"

const sync = uPlot.sync("chart")

export default function Chart({ panel, digest }) {
interface ChartProps {
panel: Panel
digest: Digest
}

export default function Chart({ panel, digest }: ChartProps) {
const plot = new SeriesPlot(digest, panel, colors)
const ref = useRef(null)
const ref = useRef<HTMLSpanElement | HTMLDivElement>(null)

const [width, setWidth] = useState(0)

useLayoutEffect(() => {
let updateWidth = () => setWidth(ref.current.offsetWidth)
const updateWidth = () => {
if (ref.current) {
setWidth(ref.current.offsetWidth)
}
}

updateWidth()
window.addEventListener("resize", updateWidth)

Expand All @@ -35,13 +45,13 @@ export default function Chart({ panel, digest }) {
return <span ref={ref} />
}

let options = {
const options: Options = {
width: width,
height: 250,
title: panel.title,
cursor: { sync: { key: sync.key } },
legend: { live: false },
series: plot.series,
series: plot.series as Series[],
axes: [{}],
plugins: [tooltipPlugin("#fafafa")]
}
Expand All @@ -51,7 +61,7 @@ export default function Chart({ panel, digest }) {
stroke: "#808080",
grid: { stroke: "#f0f0f0" },
ticks: { stroke: "#f0f0f0" },
values: (self, ticks) => ticks.map((val) => format(unit, val)),
values: (_, ticks) => ticks.map((val) => format(unit, val)),
size: 70,
scale: unit
}
Expand All @@ -65,8 +75,8 @@ export default function Chart({ panel, digest }) {
}

return (
<div ref={ref} className="chart panel">
<UplotReact options={options} data={plot.data} />
<div ref={ref as Ref<HTMLDivElement>} className="chart panel">
<UplotReact options={options} data={plot.data as AlignedData} />
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-FileCopyrightText: 2023 Raintank, Inc. dba Grafana Labs
//
// SPDX-License-Identifier: AGPL-3.0-only

export { default } from "./Chart"
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
// SPDX-License-Identifier: AGPL-3.0-only

import React from "react"
import { Digest } from "@xk6-dashboard/model"
import { Panel as PanelClass, PanelKind } from "@xk6-dashboard/view"

import { PanelKind } from "@xk6-dashboard/view"
import Chart from "components/Chart"
import Summary from "components/Summary"

import Chart from "./Chart"
import Summary from "./Summary"
interface PanelProps {
panel: PanelClass
digest: Digest
}

export default function Panel({ panel, digest }) {
export default function Panel({ panel, digest }: PanelProps) {
if (panel.kind == PanelKind.chart) {
return <Chart panel={panel} digest={digest} />
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@
// SPDX-License-Identifier: AGPL-3.0-only

import React from "react"

import { SummaryTable, isEmptySection } from "@xk6-dashboard/view"
import { Digest } from "@xk6-dashboard/model"
import { Panel as PanelClass, Section as SectionClass, SummaryTable, isEmptySection } from "@xk6-dashboard/view"

import Panel from "./Panel"

export default function Section({ section, digest }) {
interface SectionProps {
section: SectionClass
digest: Digest
}

export default function Section({ section, digest }: SectionProps) {
const empty = isEmptySection(section, digest)

if (empty) {
return <></>
}

const foo = (panel) => {
const createClassName = (panel: PanelClass) => {
if (panel.kind == "chart") {
return "col-lg-6 rcol-md-12"
}
Expand All @@ -40,8 +45,8 @@ export default function Section({ section, digest }) {
<p>{section.summary}</p>
<div className="row row-cols-1 row-cols-sm-1 row-cols-md-1 row-cols-lg-2" key={section.id + "row"}>
{section.panels.map((panel) => (
<div key={panel.id + "col"} className={"col " + foo(panel)}>
<Panel key={panel.id} panel={panel} digest={digest} columns={section.columns} />
<div key={panel.id + "col"} className={"col " + createClassName(panel)}>
<Panel key={panel.id} panel={panel} digest={digest} />
</div>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
// SPDX-License-Identifier: AGPL-3.0-only

import React from "react"
import { Digest } from "@xk6-dashboard/model"
import { Panel, SummaryTable } from "@xk6-dashboard/view"

import "./Summary.css"

import { SummaryTable } from "@xk6-dashboard/view"
interface SummaryProps {
panel: Panel
digest: Digest
}

export default function Summary({ panel, digest }) {
export default function Summary({ panel, digest }: SummaryProps) {
const table = new SummaryTable(panel, digest)

if (table.empty) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-FileCopyrightText: 2023 Raintank, Inc. dba Grafana Labs
//
// SPDX-License-Identifier: AGPL-3.0-only

export { default } from "./Summary"
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@
// SPDX-License-Identifier: AGPL-3.0-only

import React from "react"
import { Digest } from "@xk6-dashboard/model"

import { Tab as TabType } from "types/config"
import Section from "./Section"

export default function Tab({ tab, digest }) {
interface TabProps {
tab: TabType
digest: Digest
}

export default function Tab({ tab, digest }: TabProps) {
return (
<section className="chapter" id="tab.id">
<h2 id={tab.id}>{tab.title}</h2>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

import React from "react"
import { render } from "preact"
import digest from "./digest"

import "uplot/dist/uPlot.min.css"
import "./styles.scss"

import App from "./App.jsx"
import digest from "utils/digest"
import App from "components/App"
import "theme/styles.scss"

digest().then((d) => render(<App digest={d} />, document.getElementById("root")))
const rootElement = document.getElementById("root") as HTMLDivElement
digest().then((d) => render(<App digest={d} />, rootElement))
Loading

0 comments on commit fb6c358

Please sign in to comment.