Display information of project on home tab
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
"Folders": "Folders",
|
||||
"test_cases": "Test Cases",
|
||||
"test_runs": "Test Runs",
|
||||
"progress": "Progress",
|
||||
"test_types": "Test types",
|
||||
"other": "Other",
|
||||
"security": "Security",
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"Folders": "フォルダー",
|
||||
"test_cases": "テストケース",
|
||||
"test_runs": "テスト実行",
|
||||
"progress": "進捗",
|
||||
"test_types": "テスト種別",
|
||||
"other": "その他",
|
||||
"security": "セキュリティ",
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import React from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { ProgressSeriesType } from "@/types/run";
|
||||
const Chart = dynamic(() => import("react-apexcharts"), { ssr: false });
|
||||
|
||||
type Props = {
|
||||
progressSeries: ProgressSeriesType[];
|
||||
progressCategories: string[];
|
||||
};
|
||||
|
||||
export default function TestProgressBarChart({
|
||||
progressSeries,
|
||||
progressCategories,
|
||||
}: Props) {
|
||||
const [chartData, setChartData] = useState({
|
||||
series: [],
|
||||
options: {
|
||||
labels: [],
|
||||
colors: [],
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const updateChartDate = () => {
|
||||
if (progressSeries) {
|
||||
setChartData({
|
||||
series: progressSeries,
|
||||
options: {
|
||||
chart: {
|
||||
toolbar: {
|
||||
show: false,
|
||||
},
|
||||
stacked: true,
|
||||
},
|
||||
legend: {
|
||||
position: "right",
|
||||
},
|
||||
xaxis: {
|
||||
type: "datetime",
|
||||
categories: progressCategories,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
updateChartDate();
|
||||
}, [progressSeries, progressCategories]);
|
||||
|
||||
return (
|
||||
<Chart
|
||||
options={chartData.options}
|
||||
series={chartData.series}
|
||||
type="bar"
|
||||
width={"100%"}
|
||||
height={"100%"}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ProjectType } from "@/types/project";
|
||||
import { testTypes, priorities } from "@/config/selection";
|
||||
import { testTypes, priorities, testRunCaseStatus } from "@/config/selection";
|
||||
|
||||
// aggregate folder, case, run mum
|
||||
function aggregateBasicInfo(project: ProjectType) {
|
||||
@@ -49,4 +49,44 @@ function aggregateTestPriority(project: ProjectType) {
|
||||
return result;
|
||||
}
|
||||
|
||||
export { aggregateBasicInfo, aggregateTestType, aggregateTestPriority };
|
||||
function aggregateProgress(project: ProjectType) {
|
||||
let series = testRunCaseStatus.map((status) => {
|
||||
return { name: status.uid, data: [] };
|
||||
});
|
||||
let categories = [];
|
||||
|
||||
project.Runs.forEach((run) => {
|
||||
run.RunCases.forEach((runCase) => {
|
||||
const createdAtDate = new Date(runCase.createdAt);
|
||||
const dateString = createdAtDate.toISOString().slice(0, 10);
|
||||
|
||||
const alreadyExists = categories.includes(dateString);
|
||||
if (!alreadyExists) {
|
||||
categories.push(dateString);
|
||||
series.forEach((itr) => {
|
||||
itr.data.push(0);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
project.Runs.forEach((run) => {
|
||||
run.RunCases.forEach((runCase) => {
|
||||
const createdAtDate = new Date(runCase.createdAt);
|
||||
const dateString = createdAtDate.toISOString().slice(0, 10);
|
||||
const index = categories.indexOf(dateString);
|
||||
|
||||
const target = series[runCase.status];
|
||||
target.data[index]++;
|
||||
});
|
||||
});
|
||||
|
||||
return { series, categories };
|
||||
}
|
||||
|
||||
export {
|
||||
aggregateBasicInfo,
|
||||
aggregateTestType,
|
||||
aggregateTestPriority,
|
||||
aggregateProgress,
|
||||
};
|
||||
|
||||
@@ -5,14 +5,17 @@ import { title } from "@/components/primitives";
|
||||
import { Card, CardBody, Chip } from "@nextui-org/react";
|
||||
import { Folder, Clipboard, FlaskConical } from "lucide-react";
|
||||
import { CaseTypeCountType, CasePriorityCountType } from "@/types/case";
|
||||
import { ProgressSeriesType } from "@/types/run";
|
||||
import { HomeMessages } from "./page";
|
||||
import {
|
||||
aggregateBasicInfo,
|
||||
aggregateTestPriority,
|
||||
aggregateTestType,
|
||||
aggregateProgress,
|
||||
} from "./aggregate";
|
||||
import TestTypesChart from "./TestTypesDonutChart";
|
||||
import TestPriorityChart from "./TestPriorityDonutChart";
|
||||
import TestProgressBarChart from "./TestProgressColumnChart";
|
||||
import Config from "@/config/config";
|
||||
const apiServer = Config.apiServer;
|
||||
|
||||
@@ -54,6 +57,8 @@ export function Home({ projectId, messages }: Props) {
|
||||
const [typesCounts, setTypesCounts] = useState<CaseTypeCountType[]>();
|
||||
const [priorityCounts, setPriorityCounts] =
|
||||
useState<CasePriorityCountType[]>();
|
||||
const [progressCategories, setProgressCategories] = useState<string[]>();
|
||||
const [progressSeries, setProgressSeries] = useState<ProgressSeriesType[]>();
|
||||
const url = `${apiServer}/home/${projectId}`;
|
||||
|
||||
useEffect(() => {
|
||||
@@ -82,6 +87,10 @@ export function Home({ projectId, messages }: Props) {
|
||||
|
||||
const priorityRet = aggregateTestPriority(project);
|
||||
setPriorityCounts([...priorityRet]);
|
||||
|
||||
const { series, categories } = aggregateProgress(project);
|
||||
setProgressSeries([...series]);
|
||||
setProgressCategories([...categories]);
|
||||
}
|
||||
|
||||
aggregate();
|
||||
@@ -119,7 +128,16 @@ export function Home({ projectId, messages }: Props) {
|
||||
</Card>
|
||||
|
||||
<Divider className="my-6" />
|
||||
<div className="flex">
|
||||
<div style={{ height: "20rem" }}>
|
||||
<h3>{messages.progress}</h3>
|
||||
<TestProgressBarChart
|
||||
progressSeries={progressSeries}
|
||||
progressCategories={progressCategories}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Divider className="my-6" />
|
||||
<div className="flex pb-20">
|
||||
<div style={{ width: "32rem", height: "18rem" }}>
|
||||
<h3>{messages.testTypes}</h3>
|
||||
<TestTypesChart typesCounts={typesCounts} messages={messages} />
|
||||
@@ -132,8 +150,6 @@ export function Home({ projectId, messages }: Props) {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider className="my-6" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ export type HomeMessages = {
|
||||
folders: string;
|
||||
testCases: string;
|
||||
testRuns: string;
|
||||
progress: string;
|
||||
testTypes: string;
|
||||
other: string;
|
||||
security: string;
|
||||
@@ -32,6 +33,7 @@ export default function Page({ params }: { params: { projectId: string } }) {
|
||||
folders: t("Folders"),
|
||||
testCases: t("test_cases"),
|
||||
testRuns: t("test_runs"),
|
||||
progress: t("progress"),
|
||||
testTypes: t("test_types"),
|
||||
other: t("other"),
|
||||
security: t("security"),
|
||||
|
||||
@@ -26,6 +26,11 @@ type RunStatusCountType = {
|
||||
count: number;
|
||||
};
|
||||
|
||||
type ProgressSeriesType = {
|
||||
name: string;
|
||||
data: number[];
|
||||
}
|
||||
|
||||
type RunsMessages = {
|
||||
runList: string,
|
||||
id: string;
|
||||
@@ -78,6 +83,7 @@ export {
|
||||
RunCaseType,
|
||||
RunCaseInfoType,
|
||||
RunStatusCountType,
|
||||
ProgressSeriesType,
|
||||
RunsMessages,
|
||||
RunMessages,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user