Skip to content

Commit

Permalink
labels - sparkline unit and other changes, minor layout changes
Browse files Browse the repository at this point in the history
  • Loading branch information
manishiwa committed Jul 21, 2024
1 parent 850bd85 commit e31a12e
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 62 deletions.
20 changes: 12 additions & 8 deletions app/(labels)/labels/CanvasSparkline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ type CanvasSparklineProps = {
const GradientColors = {
negative: ["#FE5468", "#FFDF27"],
positive: ["#10808C", "#1DF7EF"],
neutral: ["#CBCBCB99", "#EEEEEE99"],
};

const GradientStops = {
negative: [3.33 * 25, 0, 200, 50],
positive: [3.33 * 23, 0, 100, 20],
neutral: [0, 0, 100, 0],
};

const CANVAS_WIDTH = 110;
Expand Down Expand Up @@ -56,7 +58,7 @@ export default function CanvasSparkline({ chainKey }: CanvasSparklineProps) {
const canvasRef = useRef<HTMLCanvasElement>(null);
const hoverCanvasRef = useRef<HTMLCanvasElement>(null);

const isNegative = change < 0;
const percentChangeType = !change ? "neutral" : (change * 100).toFixed(1) === "0.0" ? "neutral" : change < 0 ? "negative" : "positive";

const dataValuesWithNulls = adjustedData.map(([, y]) => y);
const dataValues = dataValuesWithNulls.filter((y) => y !== null) as number[];
Expand Down Expand Up @@ -85,10 +87,10 @@ export default function CanvasSparkline({ chainKey }: CanvasSparklineProps) {
const drawSparkline = useCallback(
(ctx: CanvasRenderingContext2D) => {
const [x1, y1, x2, y2] =
GradientStops[isNegative ? "negative" : "positive"];
GradientStops[percentChangeType];
const gradient = ctx.createLinearGradient(x1, y1, x2, y2);
const [color1, color2] =
GradientColors[isNegative ? "negative" : "positive"];
GradientColors[percentChangeType];

gradient.addColorStop(0, color1);
gradient.addColorStop(1, color2);
Expand Down Expand Up @@ -141,7 +143,7 @@ export default function CanvasSparkline({ chainKey }: CanvasSparklineProps) {

ctx.restore();
},
[adjustedData, dataMax, isNegative, maxUnix],
[adjustedData, dataMax, percentChangeType, maxUnix],
);

useEffect(() => {
Expand Down Expand Up @@ -197,7 +199,7 @@ export default function CanvasSparkline({ chainKey }: CanvasSparklineProps) {
// Draw hover circle
ctx.beginPath();
ctx.fillStyle = pointX > (DRAW_WIDTH / 30) * 23
? (isNegative ? GradientColors.negative[0] + "66" : GradientColors.positive[1] + "66")
? (GradientColors[percentChangeType][0] + "66")
: "#CDD8D366";
ctx.arc(pointX, pointY, 3, 0, 2 * Math.PI);
ctx.fill();
Expand All @@ -219,7 +221,7 @@ export default function CanvasSparkline({ chainKey }: CanvasSparklineProps) {
canvas.removeEventListener("mousemove", handleMouseMove);
canvas.removeEventListener("mouseleave", handleMouseLeave);
};
}, [hoverCanvasRef, adjustedData, dataMax, dataMin, isNegative, setHoverDataPoint]);
}, [hoverCanvasRef, adjustedData, dataMax, dataMin, percentChangeType, setHoverDataPoint]);

return (
<>
Expand All @@ -235,8 +237,9 @@ type CanvasSparklineContextType = {
data: [number, number][];
minUnix: number;
maxUnix: number;
change: number;
change: number | null;
value: number;
valueType: string;
hoverDataPoint: [number, number | null] | null;
setHoverDataPoint: (value: [number, number | null] | null) => void;
};
Expand All @@ -251,13 +254,14 @@ export const CanvasSparklineProvider = ({
maxUnix,
change,
value,
valueType,
children,
}: CanvasSparklineContextType & { children: React.ReactNode }) => {
const [hoverDataPoint, setHoverDataPoint] = useState<[number, number | null] | null>(null);

return (
<CanvasSparklineContext.Provider
value={{ minUnix, maxUnix, data, change, value, hoverDataPoint, setHoverDataPoint }}
value={{ minUnix, maxUnix, data, change, value, valueType, hoverDataPoint, setHoverDataPoint }}
>
{children}
</CanvasSparklineContext.Provider>
Expand Down
2 changes: 1 addition & 1 deletion app/(labels)/labels/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Search from "./Search";

export default function Header() {
return (
<div className="fixed z-10 flex flex-col w-full z-50 items-center">
<div className="fixed flex flex-col w-full z-50 items-center">
<div className="absolute h-[170px] w-full overflow-clip">
<div
className="background-container !h-screen"
Expand Down
29 changes: 16 additions & 13 deletions app/(labels)/labels/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import "../../background.css";
import "../../globals.css";
import { LabelsParquetURLS } from "@/lib/urls";
import { DuckDBProvider } from "../SparklineParquetContext";
import { MasterProvider } from "@/contexts/Master";

const jsonLd: Graph = {
"@context": "https://schema.org",
Expand Down Expand Up @@ -191,19 +192,21 @@ export default function RootLayout({
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<Providers forcedTheme="dark">
<main className="relative flex-1 w-full mx-auto z-10 min-h-screen select-none">
{/* <LabelsProviders> */}
<DuckDBProvider
parquetFiles={[
LabelsParquetURLS.full,
LabelsParquetURLS.projects,
LabelsParquetURLS.sparkline,
]}
>
{children}
</DuckDBProvider>
{/* </LabelsProviders> */}
</main>
<MasterProvider>
<main className="relative flex-1 w-full mx-auto min-h-screen select-none">
{/* <LabelsProviders> */}
<DuckDBProvider
parquetFiles={[
LabelsParquetURLS.full,
LabelsParquetURLS.projects,
LabelsParquetURLS.sparkline,
]}
>
{children}
</DuckDBProvider>
{/* </LabelsProviders> */}
</main>
</MasterProvider>
{/* <div className="flex h-fit w-full justify-center">
<div className="flex w-full min-h-screen overflow-y-visible">
<div className="flex flex-col flex-1 overflow-y-clip z-10 overflow-x-clip relative min-h-full bg-white dark:bg-inherit">
Expand Down
129 changes: 89 additions & 40 deletions app/(labels)/labels/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
TooltipTrigger,
} from "@/components/layout/Tooltip";
import { uniqBy } from "lodash";
import { useMaster } from "@/contexts/Master";

const devMiddleware = (useSWRNext) => {
return (key, fetcher, config) => {
Expand Down Expand Up @@ -88,6 +89,8 @@ export default function LabelsPage() {
const showGwei = true;
const showCents = true;

const { formatMetric } = useMaster();

//True is default descending false ascending
// const { theme } = useTheme();
const [showUsd, setShowUsd] = useLocalStorage("showUsd", true);
Expand Down Expand Up @@ -231,6 +234,17 @@ export default function LabelsPage() {
setCurrentMetric(metricKeys[newIndex]);
}, [currentMetric]);

useEffect(() => {
if (!currentMetric) return;

if (metricKeys.includes(sort.metric) && sort.metric !== currentMetric) {
setSort(prev => ({
...prev,
metric: currentMetric,
}));
}
}, [currentMetric, sort, setSort]);

// const [metricIndex, setMetricIndex] = useState(0);
// const [metricChangeIndex, setMetricChangeIndex] = useState(0);

Expand Down Expand Up @@ -596,9 +610,12 @@ export default function LabelsPage() {
Please view on a larger device or make your browser window wider.
</div>
</LabelsContainer> */}
<div className="bg-black h-10 w-32 text-white fixed top-0 left-0 z-50">
{/* <div className="bg-black h-10 w-32 text-white fixed top-0 left-0 z-50">
{SparklineTimestampRange}
</div>
</div> */}
{/* <div className="bg-black h-10 w-32 text-white fixed top-0 left-0 z-50">
{JSON.stringify(sort)} - {currentMetric}
</div> */}

<LabelsTableContainer
className="block"
Expand Down Expand Up @@ -788,49 +805,52 @@ export default function LabelsPage() {
/>
</div>
<div className="relative flex items-center justify-end -mr-[12px]">
<div
className=" flex items-center cursor-pointer"
onClick={() => {
setSort({
metric: currentMetric,
sortOrder:
sort.metric === currentMetric
? sort.sortOrder === "asc"
? "desc"
: "asc"
: "desc",
});
}}
>
{metricKeysLabels[currentMetric]} (7 days)
<Icon
icon={
sort.metric === currentMetric &&
sort.sortOrder === "asc"
? "feather:arrow-up"
: "feather:arrow-down"
}
className="w-[12px] h-[12px]"
style={{
opacity: sort.metric === currentMetric ? 1 : 0.2,
<div className=" flex items-center">
<div
className=" flex items-center cursor-pointer"
onClick={() => {
setSort({
metric: currentMetric,
sortOrder:
sort.metric === currentMetric
? sort.sortOrder === "asc"
? "desc"
: "asc"
: "desc",
});
}}
/>
>
{metricKeysLabels[currentMetric]} (7 days)

<Icon
icon={
sort.metric === currentMetric &&
sort.sortOrder === "asc"
? "feather:arrow-up"
: "feather:arrow-down"
}
className="w-[12px] h-[12px]"
style={{
opacity: sort.metric === currentMetric ? 1 : 0.2,
}}
/>
</div>
<div
className="absolute left-[0px] cursor-pointer bg-white/30 opacity-60 rounded-full px-0.5 py-[2px]"
className="absolute left-[15px] cursor-pointer text-[#CDD8D3] bg-[#5A6462] rounded-full pl-[1px] pr-[2px] py-[1px]"
onClick={handlePreviousMetric}
>
<Icon
icon="feather:chevron-left"
className="w-[12px] h-[12px]"
className="w-[13px] h-[13px]"
/>
</div>
<div
className="absolute -right-[20px] cursor-pointer bg-white/30 opacity-60 rounded-full px-0.5 py-[2px]"
className="absolute -right-[20px] cursor-pointer text-[#CDD8D3] bg-[#5A6462] rounded-full pr-[1px] pl-[2px] py-[1px]"
onClick={handleNextMetric}
>
<Icon
icon="feather:chevron-right"
className="w-[12px] h-[12px]"
className="w-[13px] h-[13px]"
/>
</div>
</div>
Expand Down Expand Up @@ -948,7 +968,7 @@ export default function LabelsPage() {
ownerProjectToProjectData[
filteredLabelsData[item.index].owner_project
][5]) && (
<TooltipContent className="relativeflex flex-col items-start justify-center gap-y-[5px] rounded-[10px] p-2.5 bg-[#151a19] border border-[#5A6462] z-50 max-w-[300px]">
<TooltipContent className="relativeflex flex-col items-start justify-center gap-y-[5px] rounded-[10px] p-2.5 bg-[#151a19] border border-[#5A6462] z-[19] max-w-[300px]">
{/* arrow pointing to the left */}
<div className="absolute top-[calc(50%-4px)] -left-1 w-2 h-2 bg-[#151a19] border-[#5A6462] border border-r-0 border-t-0 transform rotate-45"></div>
{ownerProjectToProjectData[
Expand Down Expand Up @@ -1233,6 +1253,9 @@ export default function LabelsPage() {
value={
filteredLabelsData[item.index][currentMetric]
}
valueType={
currentMetric
}
>
<LabelsSparkline
chainKey={
Expand Down Expand Up @@ -1278,7 +1301,7 @@ const GridTableHeader = ({
}: GridTableProps) => {
return (
<div
className={`select-none gap-x-[10px] pl-[10px] pr-[20px] pt-[30px] text-[11px] items-center font-semibold grid ${gridDefinitionColumns}`}
className={`select-none gap-x-[10px] pl-[10px] pr-[32px] pt-[30px] text-[11px] items-center font-semibold grid ${gridDefinitionColumns}`}
>
{children}
</div>
Expand All @@ -1294,7 +1317,7 @@ const GridTableRow = ({
}: GridTableProps) => {
return (
<div
className={`select-text gap-x-[10px] rounded-full border border-forest-900/20 dark:border-forest-500/20 pl-[10px] pr-[20px] py-[5px] text-xs items-center grid ${gridDefinitionColumns}`}
className={`select-text gap-x-[10px] pl-[10px] pr-[32px] py-[5px] text-xs items-center rounded-full border border-forest-900/20 dark:border-forest-500/20 grid ${gridDefinitionColumns}`}
style={style}
>
{children}
Expand All @@ -1303,7 +1326,9 @@ const GridTableRow = ({
};

const LabelsSparkline = ({ chainKey }: { chainKey: string }) => {
const { data, change, value, hoverDataPoint, setHoverDataPoint } = useCanvasSparkline();
const { data, change, value, valueType, hoverDataPoint, setHoverDataPoint } = useCanvasSparkline();
const { formatMetric } = useMaster();

return (
<>
<CanvasSparkline chainKey={chainKey} />
Expand All @@ -1315,7 +1340,7 @@ const LabelsSparkline = ({ chainKey }: { chainKey: string }) => {
}}
>
<div className="min-w-[55px] text-right" >
{hoverDataPoint[1] && hoverDataPoint[1].toLocaleString("en-GB")}
{hoverDataPoint[1] && formatMetric(hoverDataPoint[1], valueType)}
</div>
<div className={`text-[9px] text-right leading-[1] text-forest-400`}>{new Date(hoverDataPoint[0]).toLocaleDateString("en-GB",
{
Expand All @@ -1333,17 +1358,41 @@ const LabelsSparkline = ({ chainKey }: { chainKey: string }) => {
}}
>
<div className="min-w-[55px] text-right">
{value.toLocaleString("en-GB")}
{formatMetric(value, valueType)}
</div>
<div
{(change === null || parseFloat((change * 100).toFixed(1)) === 0) && (
<div
className={`text-[9px] text-right leading-[1] text-[#CDD8D399] font-normal`}
>
{change === null && "—"}
{change !== null && "0.0%"}
</div>
)}
{(change !== null && parseFloat((change * 100).toFixed(1)) > 0) && (
<div
className={`text-[9px] text-right leading-[1] text-[#1DF7EF] font-normal`}
>
{change > 0 && "+"}
{Math.abs(change) > 100 ? formatNumber(change * 100, true, false) : (change * 100).toFixed(1)}%
</div>
)}
{(change !== null && parseFloat((change * 100).toFixed(1)) < 0) && (
<div
className={`text-[9px] text-right leading-[1] text-[#FE5468] font-semibold`}
>
{change > 0 && "+"}
{Math.abs(change) > 100 ? formatNumber(change * 100, true, false) : (change * 100).toFixed(1)}%
</div>
)}
{/* <div
className={`text-[9px] text-right leading-[1] ${change > 0
? "text-[#1DF7EF] font-normal"
: "text-[#FE5468] font-semibold "
}`}
>
{change > 0 && "+"}
{formatNumber(change * 100, true, false)}%
</div>
</div> */}
</div>
)}
</>
Expand Down
Loading

0 comments on commit e31a12e

Please sign in to comment.