Skip to content

Commit

Permalink
puch recharts
Browse files Browse the repository at this point in the history
  • Loading branch information
thewbuk committed Nov 5, 2024
1 parent 6a6076c commit 36fa1c9
Show file tree
Hide file tree
Showing 3 changed files with 258 additions and 356 deletions.
2 changes: 1 addition & 1 deletion packages/toolkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@instill-ai/toolkit",
"version": "0.110.0-rc.93",
"version": "0.110.0-rc.103",
"description": "Instill AI's frontend toolkit",
"repository": "https://github.com/instill-ai/design-system.git",
"bugs": "https://github.com/instill-ai/design-system/issues",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,178 +1,47 @@
"use client";

import * as React from "react";
import * as echarts from "echarts";
import {
LineChart,
Line,
XAxis,
YAxis,
Tooltip,
ResponsiveContainer,
} from "recharts";
import { Icons, SelectOption, Tooltip as InstillTooltip } from "@instill-ai/design-system";
import { generateModelTriggerChartRecordData } from "../../../lib";
import { ModelTriggersSummary } from "./ModelTriggersSummary";
import {
ModelTriggersStatusSummary,
ModelTriggerTableRecord,
Nullable,
} from "instill-sdk";

import { Icons, SelectOption, Tooltip } from "@instill-ai/design-system";

import { generateModelTriggerChartRecordData } from "../../../lib";
import { ModelTriggersSummary } from "./ModelTriggersSummary";

type ModelsTriggerCountsLineChartProps = {
models: ModelTriggerTableRecord[];
isLoading: boolean;
selectedTimeOption: SelectOption;
modelTriggersSummary: Nullable<ModelTriggersStatusSummary>;
};

/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
function selectGraph(params: any, myChart: echarts.ECharts): void {
myChart.dispatchAction({
type: "legendSelect",
// legend name
name: params.name as string,
});
}

/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
function unselectGraph(params: any, myChart: echarts.ECharts): void {
for (const legend in params.selected) {
if (legend !== params.name) {
myChart.dispatchAction({
type: "legendUnSelect",
// legend name
name: legend,
});
}
}
}

export const ModelsTriggerCountsLineChart = ({
isLoading,
models,
selectedTimeOption,
modelTriggersSummary,
}: ModelsTriggerCountsLineChartProps) => {
const chartRef = React.useRef<HTMLDivElement>(null);
const { xAxis, yAxis } = React.useMemo(
() => generateModelTriggerChartRecordData(models, selectedTimeOption.value),
[models, selectedTimeOption.value],
[models, selectedTimeOption.value]
);

React.useEffect(() => {
if (chartRef.current) {
// Dispose the previous chart instance
echarts.dispose(chartRef.current); // eslint-disable-line
const myChart = echarts.init(chartRef.current, null, {
renderer: "svg",
}); // eslint-disable-line
const option = {
grid: {
left: "50px",
right: "50px",
top: 10,
bottom: 50,
},
graphic: {
type: "image",
style: {
image: "/images/no-chart-placeholder.svg",
x: "45%",
y: "0%",
width: models.length === 0 ? 225 : 0,
height: models.length === 0 ? 225 : 0,
},
},
animation: false,
title: {
show: models.length === 0,
textStyle: {
color: "#1D2433A6",
fontSize: 14,
fontWeight: 500,
fontFamily: "var(--font-ibm-plex-sans)",
fontStyle: "italic",
},
text: isLoading ? "Loading..." : "No models have been triggered yet",
left: `${isLoading ? "49.5%" : "44.5%"}`,
bottom: 100,
},
tooltip: {
trigger: "item",
tiggerOn: "click",
backgroundColor: "white",
borderColor: "transparent",
textStyle: {
color: "var(--semantic-fg-primary)",
},
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
formatter: function (params: any) {
const triggerTime = params.name;
const computeTimeDuration = params.value;
return `
<div class="Content" style="padding: 5px; background: white; border-radius: 4px; flex-direction: column; justify-content: flex-start; align-items: flex-start; display: inline-flex">
<div class="TextAndSupportingText" style="border-radius: 8px; flex-direction: column; justify-content: flex-start; align-items: flex-start; gap: 4px; display: flex">
<div class="Date product-body-text-4-medium" style="color: var(--semantic-fg-disabled); font-size: 12px; line-height: 16px; word-wrap: break-word">${triggerTime}</div>
<div style="display: flex; align-items: center; white-space: nowrap;">
<span class="PipelineId product-body-text-3-regular" style="color: var(--semantic-fg-secondary); font-size: 14px; line-height: 20px;">
All model triggers&nbsp;
</span>
<span class="Number product-body-text-3-semibold" style="color: var(--semantic-fg-primary); font-size: 14px; line-height: 20px;">${computeTimeDuration}</span>
</div>
</div>
</div>
`;
},
},
xAxis: {
type: "category",
data: xAxis,
axisLabel: {
fontSize: "10px",
fontFamily: "var(--font-ibm-plex-sans)",
fontStyle: "normal",
fontWeight: "500",
color: "#6B7280",
},
},
yAxis: {
type: "value",
minInterval: 1,
axisLabel: {
fontSize: "10px",
fontFamily: "var(--font-ibm-plex-sans)",
fontStyle: "normal",
fontWeight: "500",
color: "#6B7280",
},
},
series: [
{
name: "Model Triggers",
type: "line",
smooth: true,
data: yAxis,
symbol: "circle",
symbolSize: 8,
itemStyle: {
borderColor: "white",
borderWidth: 2,
},
},
],
};

myChart.setOption(option, true);

/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
myChart.on("legendselectchanged", function (params: any) {
const selected = Object.values(params.selected);
if (selected.filter((select) => !select).length === selected.length) {
myChart.dispatchAction({
type: "legendAllSelect",
});
} else {
selectGraph(params, myChart);
unselectGraph(params, myChart);
}
});
}
}, [isLoading, xAxis, yAxis, models]);
const chartData = React.useMemo(() => {
return xAxis.map((date, index) => ({
name: date,
value: yAxis[index] || 0,
}));
}, [xAxis, yAxis]);

return (
<div className="inline-flex w-full flex-col items-start justify-start rounded-sm bg-semantic-bg-primary shadow">
Expand All @@ -182,18 +51,18 @@ export const ModelsTriggerCountsLineChart = ({
<div className="text-semantic-fg-primary product-headings-heading-2">
Number of model triggers
</div>
<Tooltip.Provider>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<InstillTooltip.Provider>
<InstillTooltip.Root>
<InstillTooltip.Trigger asChild>
<div className="relative h-4 w-4">
<Icons.AlertCircle className="h-4 w-4 stroke-semantic-fg-primary" />
</div>
</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Content
</InstillTooltip.Trigger>
<InstillTooltip.Portal>
<InstillTooltip.Content
className="rounded-sm"
sideOffset={5}
side={"right"}
side="right"
>
<div className="inline-flex w-80 flex-col items-start justify-start rounded-sm bg-semantic-bg-primary p-3">
<div className="flex flex-col items-start justify-start gap-1 self-stretch">
Expand All @@ -207,40 +76,117 @@ export const ModelsTriggerCountsLineChart = ({
</div>
</div>
</div>
<Tooltip.Arrow
<InstillTooltip.Arrow
className="fill-semantic-bg-primary"
offset={10}
width={9}
height={6}
/>
</Tooltip.Content>
</Tooltip.Portal>
</Tooltip.Root>
</Tooltip.Provider>
</InstillTooltip.Content>
</InstillTooltip.Portal>
</InstillTooltip.Root>
</InstillTooltip.Provider>
</div>
</div>
{/* Status */}

<div className="px-8 pb-8 w-full">
<ModelTriggersSummary>
<ModelTriggersSummary.Card
summary={
modelTriggersSummary ? modelTriggersSummary.completed : null
}
summary={modelTriggersSummary?.completed ?? null}
/>
<ModelTriggersSummary.Card
summary={
modelTriggersSummary ? modelTriggersSummary.errored : null
}
summary={modelTriggersSummary?.errored ?? null}
/>
</ModelTriggersSummary>
</div>
<div
id="main"
ref={chartRef}
style={{ width: "100%", height: "400px", paddingLeft: "0px" }}
className="!p-0"
/>

<div className="w-full h-[400px]">
{isLoading ? (
<div className="w-full h-full flex items-center justify-center text-semantic-fg-disabled italic">
Loading...
</div>
) : models.length === 0 ? (
<div className="w-full h-full flex flex-col items-center justify-center">
<img
src="/images/no-chart-placeholder.svg"
alt="No data"
className="w-56 h-56"
/>
<p className="text-semantic-fg-disabled italic mt-4">
No models have been triggered yet
</p>
</div>
) : (
<ResponsiveContainer width="100%" height="100%">
<LineChart
data={chartData}
margin={{ top: 10, right: 20, left: 0, bottom: 10 }}
>
<XAxis
dataKey="name"
tick={{
fontSize: 10,
fontFamily: "var(--font-ibm-plex-sans)",
fill: "#6B7280",
}}
axisLine={{ stroke: "#E5E7EB" }}
tickLine={false}
/>
<YAxis
tick={{
fontSize: 10,
fontFamily: "var(--font-ibm-plex-sans)",
fill: "#6B7280",
}}
axisLine={{ stroke: "#E5E7EB" }}
tickLine={false}
allowDecimals={false}
interval="preserveStart"
/>
<Tooltip
trigger="click"
contentStyle={{
backgroundColor: "white",
border: "none",
borderRadius: "4px",
padding: "5px",
}}
formatter={(value: number, name: string) => {
return [
<div key={name} style={{ padding: "5px" }}>
<div style={{ color: "var(--semantic-fg-disabled)", fontSize: "12px", lineHeight: "16px" }}>
{name}
</div>
<div style={{ display: "flex", alignItems: "center" }}>
<span style={{ color: "var(--semantic-fg-secondary)", fontSize: "14px", lineHeight: "20px" }}>
All model triggers&nbsp;
</span>
<span style={{ color: "var(--semantic-fg-primary)", fontSize: "14px", lineHeight: "20px", fontWeight: 600 }}>
{value}
</span>
</div>
</div>
];
}}
/>
<Line
type="linear"
dataKey="value"
stroke="#3B82F6"
strokeWidth={2}
dot={{
r: 4,
strokeWidth: 2,
fill: "white",
stroke: "#3B82F6",
}}
activeDot={{ r: 6 }}
/>
</LineChart>
</ResponsiveContainer>
)}
</div>
</div>
</div>
);
};
};
Loading

0 comments on commit 36fa1c9

Please sign in to comment.