Skip to content

Commit

Permalink
add language and frameworks query param for result page
Browse files Browse the repository at this point in the history
  • Loading branch information
SuspiciousLookingOwl committed Apr 29, 2021
1 parent e610bda commit 5b13478
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 42 deletions.
55 changes: 33 additions & 22 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import React, { useEffect, useState, lazy, Suspense } from "react";
import chroma from "chroma-js";
import { Benchmark, getBenchmarkData } from "./api";
import randomColor from "randomcolor";
import { BrowserRouter as Router } from "react-router-dom";
import {
QueryParamProvider,
transformSearchStringJsonSafe,
} from "use-query-params";
import { BrowserRouter as Router, Route } from "react-router-dom";
import CacheRoute, { CacheSwitch } from "react-router-cache-route";

import Home from "./views/Home";
Expand Down Expand Up @@ -52,28 +56,35 @@ function App() {

return (
<Router>
<div>
<AppHeader onHistoryChange={fetchBenchmarkData} />
<ScrollToTop />
{isLoading ? <div className="loader">Loading...</div> : undefined}
<div className={`container ${isLoading ? "hidden" : ""}`}>
<Suspense fallback={<div className="loader">Loading...</div>}>
<CacheSwitch>
<CacheRoute exact path="/">
<Home updateDate={updatedAt} />
</CacheRoute>
<CacheRoute exact path="/result">
<BenchmarkResult benchmarks={benchmarks} />
</CacheRoute>
<CacheRoute path="/compare">
<CompareFrameworks benchmarks={benchmarks} />
</CacheRoute>
</CacheSwitch>
</Suspense>
<QueryParamProvider
ReactRouterRoute={Route}
stringifyOptions={{
transformSearchString: transformSearchStringJsonSafe,
}}
>
<div>
<AppHeader onHistoryChange={fetchBenchmarkData} />
<ScrollToTop />
{isLoading ? <div className="loader">Loading...</div> : undefined}
<div className={`container ${isLoading ? "hidden" : ""}`}>
<Suspense fallback={<div className="loader">Loading...</div>}>
<CacheSwitch>
<CacheRoute exact path="/">
<Home updateDate={updatedAt} />
</CacheRoute>
<CacheRoute exact path="/result">
<BenchmarkResult benchmarks={benchmarks} />
</CacheRoute>
<CacheRoute path="/compare">
<CompareFrameworks benchmarks={benchmarks} />
</CacheRoute>
</CacheSwitch>
</Suspense>
</div>
{/* Bottom Space */}
<div style={{ height: "25vh" }}></div>{" "}
</div>
{/* Bottom Space */}
<div style={{ height: "25vh" }}></div>{" "}
</div>
</QueryParamProvider>
</Router>
);
}
Expand Down
1 change: 1 addition & 0 deletions src/common/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./interfaces";
export * from "./data";
export * from "./formatter";
export * from "./query";
9 changes: 9 additions & 0 deletions src/common/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { decodeDelimitedArray, encodeDelimitedArray } from "use-query-params";

export const CommaArrayParam = {
encode: (array: string[] | null | undefined) =>
encodeDelimitedArray(array, ","),

decode: (arrayStr: string | (string | null)[] | null | undefined) =>
decodeDelimitedArray(arrayStr, ","),
};
9 changes: 6 additions & 3 deletions src/components/FrameworkSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,22 @@ interface Styles<T = any> {
}

export interface SelectOptionFramework extends SelectOption {
color: string;
color?: string;
}

interface Props {
options: SelectOption[];
onChange: (options: SelectOptionFramework[]) => void;
defaultValue?: number[];
value?: SelectOptionFramework[];
disableStyle?: boolean;
}

/** Styles for <Select> */
const styles: Styles<SelectOptionFramework> = {
control: (styles) => ({ ...styles, backgroundColor: "white" }),
option: (styles, { data, isDisabled, isFocused, isSelected }) => {
const color = chroma(data.color);
const color = chroma(data.color!);
return {
...styles,
backgroundColor: isDisabled
Expand All @@ -62,7 +63,7 @@ const styles: Styles<SelectOptionFramework> = {
};
},
multiValue: (styles, { data }) => {
const color = chroma(data.color);
const color = chroma(data.color!);
return {
...styles,
backgroundColor: color.alpha(0.1).css(),
Expand All @@ -86,6 +87,7 @@ function FrameworkSelector({
options,
onChange,
defaultValue = [],
value = [],
disableStyle = false,
}: Props) {
const onOptionsChange = (data: any) => {
Expand All @@ -96,6 +98,7 @@ function FrameworkSelector({
<Select
key={defaultValue.join(",")}
isMulti
value={value}
defaultValue={defaultValue.reduce((filtered, id) => {
const option = options.find((o) => o.value === id);
if (option) filtered.push(option);
Expand Down
75 changes: 58 additions & 17 deletions src/views/BenchmarkResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@ import { useEffect, useState } from "react";
import Select from "react-select";
import DataTable, { IDataTableColumn } from "react-data-table-component";
import { isMobile } from "react-device-detect";
import FrameworkSelector from "../components/FrameworkSelector";
import { useQueryParams } from "use-query-params";
import FrameworkSelector, {
SelectOptionFramework,
} from "../components/FrameworkSelector";
import { Benchmark, MetricTypes } from "../api";
import { COMPARED_METRICS, CONCURRENCIES, SelectOption } from "../common";
import {
CommaArrayParam,
COMPARED_METRICS,
CONCURRENCIES,
SelectOption,
} from "../common";

const defaultMetric = {
label: "Requests / Second",
Expand Down Expand Up @@ -45,16 +53,49 @@ interface Props {

function BenchmarkResult({ benchmarks }: Props) {
const [languages, setLanguages] = useState<SelectOption[]>([]);
const [frameworks, setFrameworks] = useState<SelectOption[]>([]);
const [frameworks, setFrameworks] = useState<SelectOptionFramework[]>([]);
const [tableData, setTableData] = useState<Benchmark[]>([]);
const [metric, setMetric] = useState<SelectOption | null>(defaultMetric);
const [columns, setColumns] = useState<IDataTableColumn<Benchmark>[]>([]);
const [query, setQuery] = useQueryParams({
f: CommaArrayParam, // frameworks
l: CommaArrayParam, // languages
});

const getLanguagesOptions = (): SelectOption[] => {
return [...new Set(benchmarks.map((b) => b.language))].map(
({ label, version }) => ({
value: label,
label: `${label} (${version})`,
})
);
};

const getFrameworkOptions = (): SelectOptionFramework[] => {
return benchmarks.map((b) => ({
value: b.framework.label,
label: `${b.language.label} - ${b.framework.label} (${b.framework.version})`,
}));
};

const scrollToTitle = () => {
document.getElementById("title")!.scrollIntoView();
};

// On metric change
// set languages and frameworks select options value from query params
useEffect(() => {
const languages = query.l || [];
const frameworks = query.f || [];
setLanguages(
getLanguagesOptions().filter((l) => languages.includes(`${l.value}`))
);
setFrameworks(
getFrameworkOptions().filter((f) => frameworks.includes(`${f.value}`))
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [benchmarks]);

// on metric change
useEffect(() => {
// Get metric data by metric key
const { key, title, format, round } = COMPARED_METRICS.find(
Expand All @@ -81,16 +122,22 @@ function BenchmarkResult({ benchmarks }: Props) {
setColumns([...staticColumns, ...dynamicColumns]);
}, [metric]);

// On filter frameworks or languages change
// on filter frameworks or languages change
useEffect(() => {
if (!benchmarks) return;
if (benchmarks.length) {
setQuery({
l: languages.length ? languages.map((l) => `${l.value}`) : undefined,
f: frameworks.length ? frameworks.map((f) => `${f.value}`) : undefined,
});
}

if (!frameworks.length && !languages.length)
return setTableData(benchmarks);

const filteredBenchmark = benchmarks.filter(
(b) =>
languages.map((l) => l.value).includes(b.language.label) ||
frameworks.map((f) => f.value).includes(b.framework.id)
frameworks.map((f) => f.value).includes(b.framework.label)
);

setTableData(filteredBenchmark);
Expand All @@ -104,22 +151,16 @@ function BenchmarkResult({ benchmarks }: Props) {

<Select
isMulti
value={languages}
onChange={(data) => setLanguages(data as SelectOption[])}
options={[...new Set(benchmarks.map((b) => b.language))].map(
({ label, version }) => ({
value: label,
label: `${label} (${version})`,
})
)}
options={getLanguagesOptions()}
placeholder="Filter Languages..."
/>

<div className="pt-md">
<FrameworkSelector
options={benchmarks.map((b) => ({
value: b.id,
label: `${b.language.label} - ${b.framework.label} (${b.framework.version})`,
}))}
value={frameworks}
options={getFrameworkOptions()}
disableStyle
onChange={setFrameworks}
/>
Expand Down

0 comments on commit 5b13478

Please sign in to comment.