Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#493 conflict 해결 pr #504

Merged
merged 18 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { selectedDataUpdater } from "../VerticalClusterList.util";

import { CLUSTER_HEIGHT, DETAIL_HEIGHT, GRAPH_WIDTH, NODE_GAP, SVG_MARGIN } from "./ClusterGraph.const";
import type { ClusterGraphElement } from "./ClusterGraph.type";
import { destroyClusterGraph, drawClusterBox, drawCommitAmountCluster, drawTotalLine } from "./Draws";
import { destroyClusterGraph, drawClusterBox, drawCommitAmountCluster, drawSubGraph, drawTotalLine } from "./Draws";
import { getTranslateAfterSelect } from "./ClusterGraph.util";
import styles from "./ClusterGraph.module.scss";

Expand All @@ -28,46 +28,49 @@ const drawClusterGraph = (
.data(data)
.join("g")
.on("click", onClickCluster)
.attr("data-testid", "cluster-graph__container")
.attr("class", cx("cluster-graph__container"))
.attr("transform", (d, i) => getTranslateAfterSelect(d, i, detailElementHeight, true));
group.append("title").text((_, i) => `${i + 1}번째 container`);

group.append("title").text((_, i) => `${i + 1} container`);

group
.transition()
.duration(0)
.attr("transform", (d, i) => getTranslateAfterSelect(d, i, detailElementHeight));

drawTotalLine(svgRef, data, detailElementHeight, SVG_MARGIN, CLUSTER_HEIGHT, NODE_GAP, GRAPH_WIDTH);
drawClusterBox(group, GRAPH_WIDTH, CLUSTER_HEIGHT);
drawCommitAmountCluster(group, GRAPH_WIDTH, CLUSTER_HEIGHT);
drawSubGraph(svgRef, data, detailElementHeight);
drawTotalLine(svgRef, data, detailElementHeight, SVG_MARGIN, CLUSTER_HEIGHT, NODE_GAP, GRAPH_WIDTH);
};

export const useHandleClusterGraph = ({
data,
clusterSizes,
selectedIndex,
setSelectedData,
}: {
clusterSizes: number[];
selectedIndex: number[];
data: ClusterNode[];
setSelectedData: Dispatch<React.SetStateAction<ClusterNode[]>>;
}) => {
const svgRef = useRef<SVGSVGElement>(null);
const prevSelected = useRef<number[]>([-1]);

const clusterGraphElements = data.map((cluster, i) => ({
const clusterGraphElements = data.map((cluster) => ({
cluster,
clusterSize: clusterSizes[i],
clusterSize: cluster.commitNodeList.length,
selected: {
prev: prevSelected.current,
current: selectedIndex,
},
}));

const handleClickCluster = useCallback(
(_: PointerEvent, d: ClusterGraphElement) =>
setSelectedData(selectedDataUpdater(d.cluster, d.cluster.commitNodeList[0].clusterId)),
(_: PointerEvent, d: ClusterGraphElement) => {
const targetIndex = d.cluster.commitNodeList[0].clusterId;
setSelectedData(selectedDataUpdater(d.cluster, targetIndex));
},
[setSelectedData]
);
useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@
stroke: var(--primary-color);
stroke-width: 1;
}

.circle-group {
fill: var(--primary-color);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,13 @@ const ClusterGraph = () => {

const svgRef = useHandleClusterGraph({
data,
clusterSizes,
selectedIndex,
setSelectedData,
});

console.log(styles);

return (
<svg
className={cx("cluster-graph")}
className={cx("cluster-graph__container", "cluster-graph__total-line", "circle-group")}
ref={svgRef}
width={SVG_WIDTH}
height={graphHeight}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,20 @@ export function getGraphHeight(clusterSizes: number[]) {
return clusterSizes.length * CLUSTER_HEIGHT + clusterSizes.length * NODE_GAP + NODE_GAP;
}

export function getStartYEndY(d: ClusterGraphElement, a: number, detailElementHeight: number) {
const selected = d.selected.current;
const selectedLength = selected.filter((selectedIdx) => selectedIdx < a).length;
const selectedLongerHeight = selectedLength * detailElementHeight;
const startY = SVG_MARGIN.top + 20 + (a + 1) * (CLUSTER_HEIGHT + NODE_GAP) + selectedLongerHeight;
const endY = startY + detailElementHeight - 50;
return { startY, endY };
}

export function getTranslateAfterSelect(
d: ClusterGraphElement,
i: number,
detailElementHeight: number,
isPrev = false
isPrev = false // TODO - this param can be removed
) {
const selected = isPrev ? d.selected.prev : d.selected.current;
const selectedLength = selected.filter((selectedIdx) => selectedIdx < i).length;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import * as d3 from "d3";
import type { RefObject } from "react";

import type { ClusterGraphElement } from "../ClusterGraph.type";
import { getStartYEndY } from "../ClusterGraph.util";
import { GRAPH_WIDTH } from "../ClusterGraph.const";

// create tootip (HTML)
const tooltip = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("Tooltip");

const calculateCirclePositions = (numOfCircles: number, startY: number, endY: number, gap: number) => {
const positionStrategies = new Map<number, (start: number, end: number) => number[]>([
[1, (start, end) => [(start + end) / 2]],
[2, (start, end) => [(3 * start + end) / 4, (start + 3 * end) / 4]],
]);

const strategy = positionStrategies.get(numOfCircles);

return strategy ? strategy(startY, endY) : Array.from({ length: numOfCircles }, (_, i) => startY + i * gap);
};

export const drawSubGraph = (
svgRef: RefObject<SVGSVGElement>,
data: ClusterGraphElement[],
detailElementHeight: number
) => {
const allCirclePositions = data.reduce(
(acc, clusterData, index) => {
if (clusterData.selected.current.includes(index)) {
const { startY, endY } = getStartYEndY(clusterData, index, detailElementHeight);
const numOfCircles = clusterData.cluster.commitNodeList.length;
const gap = (endY - startY) / (numOfCircles - 1);
const circlePositions = calculateCirclePositions(numOfCircles, startY, endY, gap);

const enrichedPositions = circlePositions.map((y, circleIndex) => ({ y, clusterData, circleIndex }));
return acc.concat(enrichedPositions);
}
return acc;
},
[] as Array<{ y: number; clusterData: ClusterGraphElement; circleIndex: number }>
);

const circleRadius = 5;

d3.select(svgRef.current)
.selectAll(".circle-group")
.data(allCirclePositions)
.join("circle")
.attr("class", "circle-group")
.attr("cx", GRAPH_WIDTH / 2 + 2)
.attr("cy", (d) => d.y)
.attr("r", circleRadius)
.on("mouseover", (_, { clusterData, circleIndex }) => {
const { commitNodeList } = clusterData.cluster;
const targetIndex = commitNodeList.length - 1 - circleIndex;
const info = commitNodeList[targetIndex].commit.message;
tooltip.text(info);
return tooltip.style("visibility", "visible");
})
.on("mousemove", (event) => {
return tooltip.style("top", `${event.pageY - 10}px`).style("left", `${event.pageX + 10}px`);
})
.on("mouseout", () => {
return tooltip.style("visibility", "hidden");
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ export const drawTotalLine = (
.attr("x2", svgMargin.left + graphWidth / 2)
.attr("y2", (d) => d.end + d.selected.prev.length * detailElementHeight)
.transition()
.attr("y2", (d) => d.end + d.selected.current.length * detailElementHeight);
.attr("y2", (d) => d.end + d.selected.current.length * detailElementHeight)
.attr("pointer-events", "none");
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./drawClusterBox";
export * from "./drawCommitAmountCluster";
export * from "./drawTotalLine";
export * from "./destroyClusterGraph";
export * from "./drawSubGraph";
33 changes: 33 additions & 0 deletions packages/view/tests/home.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,44 @@
import { test, expect } from "@playwright/test";

test.describe("home", () => {
const CLICK_INDEX = 0;
test.beforeEach(async ({ page }) => {
await page.goto("/");
});

test("has title", async ({ page }) => {
await expect(page).toHaveTitle(/Githru/);
});

test("when click cluster", async ({ page }) => {
await page.waitForSelector("[data-testid=cluster-graph__container]", { state: "attached" });

const childContainers = await page.$$("[data-testid=cluster-graph__container]");

if (childContainers.length > CLICK_INDEX) {
await childContainers[CLICK_INDEX].scrollIntoViewIfNeeded();
await childContainers[CLICK_INDEX].click();
} else {
throw new Error("No child containers found");
}

// waiting for changing
await page.waitForTimeout(1000);

const newChildContainers = await page.$$("[data-testid=cluster-graph__container]");

const targetIndexForCheck = CLICK_INDEX + 1;
const transformPositionForCheck = 10 + targetIndexForCheck * 50 + 220;
if (newChildContainers.length > targetIndexForCheck) {
const transformValue = await newChildContainers[targetIndexForCheck].getAttribute("transform");

if (transformValue !== null) {
expect(transformValue).toBe(`translate(2, ${transformPositionForCheck})`);
} else {
throw new Error("Transform attribute not found");
}
} else {
throw new Error("Not enough child containers found");
}
});
});
4 changes: 3 additions & 1 deletion packages/view/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
} /* Specify a set of entries that re-map imports to additional lookup locations. */,
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
"types": [
"@playwright/test"
] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
"resolveJsonModule": true /* Enable importing .json files. */,
Expand Down
Loading