Skip to content

Commit

Permalink
Merge pull request #296 from visdesignlab/degree-column
Browse files Browse the repository at this point in the history
Degree column
  • Loading branch information
JakeWags authored Feb 20, 2024
2 parents ede2a66 + ee22b46 commit ad191bf
Show file tree
Hide file tree
Showing 17 changed files with 251 additions and 135 deletions.
2 changes: 2 additions & 0 deletions packages/upset/src/components/AttributeBars.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export const AttributeBars: FC<Props> = ({ attributes, row }) => {
dimensions.bookmarkStar.gap +
dimensions.bookmarkStar.width +
dimensions.bookmarkStar.gap +
dimensions.degreeColumn.width +
dimensions.degreeColumn.gap +
dimensions.size.width +
dimensions.gap +
dimensions.attribute.width +
Expand Down
27 changes: 27 additions & 0 deletions packages/upset/src/components/Degree.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { FC } from 'react';
import { useRecoilValue } from 'recoil';
import { dimensionsSelector } from '../atoms/dimensionsAtom';
import translate from '../utils/transform';

type Props = {
degree: number;
}

export const Degree: FC<Props> = ({ degree }) => {
const dimensions = useRecoilValue(dimensionsSelector);
return (
<g
transform={translate(
dimensions.matrixColumn.width +
dimensions.bookmarkStar.gap +
dimensions.bookmarkStar.width +
dimensions.bookmarkStar.gap,
dimensions.body.rowHeight / 2 + 5,
)}
>
<text>
{degree}
</text>
</g>
);
};
2 changes: 2 additions & 0 deletions packages/upset/src/components/DeviationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export const DeviationBar: FC<Props> = ({ deviation }) => {
dimensions.bookmarkStar.gap +
dimensions.bookmarkStar.width +
dimensions.bookmarkStar.gap +
dimensions.degreeColumn.width +
dimensions.degreeColumn.gap +
dimensions.size.width +
dimensions.gap +
dimensions.attribute.width / 2,
Expand Down
33 changes: 22 additions & 11 deletions packages/upset/src/components/Header/AttributeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import { HeaderSortArrow } from '../custom/HeaderSortArrow';
/** @jsxImportSource @emotion/react */
type Props = {
label: string;
sort?: boolean;
sortable?: boolean;
};

export const AttributeButton: FC<Props> = ({ label, sort = false }) => {
export const AttributeButton: FC<Props> = ({ label, sortable = false }) => {
const dimensions = useRecoilValue(dimensionsSelector);
const { actions } = useContext(
ProvenanceContext,
Expand All @@ -24,17 +24,27 @@ export const AttributeButton: FC<Props> = ({ label, sort = false }) => {
const sortByOrder = useRecoilValue(sortByOrderSelector);
const setContextMenu = useSetRecoilState(contextMenuAtom);

const handleContextMenuClose = () => {
setContextMenu(null);
};

const sortByHeader = (order: SortByOrder) => {
actions.sortBy(label as SortBy, order);
};

const handleOnClick = () => {
if (sortable) {
if (sortBy !== label) {
sortByHeader('Ascending');
} else {
sortByHeader(sortByOrder === 'Ascending' ? 'Descending' : 'Ascending');
}
}
};

const handleContextMenuClose = () => {
setContextMenu(null);
};

const getMenuItems = () => {
const items = [];
if (sort) {
if (sortable) {
items.push(
{
label: `Sort by ${label} - Ascending`,
Expand Down Expand Up @@ -82,14 +92,15 @@ export const AttributeButton: FC<Props> = ({ label, sort = false }) => {
'&:hover': {
opacity: 0.7,
},
cursor: (sort ? 'context-menu' : 'default'),
cursor: 'context-menu',
}}
onContextMenu={(e) => {
e.preventDefault();
e.stopPropagation();
openContextMenu(e);
}}
transform={translate(0, 6)}
onClick={handleOnClick}
>
<rect
height={dimensions.attribute.buttonHeight}
Expand All @@ -107,14 +118,14 @@ export const AttributeButton: FC<Props> = ({ label, sort = false }) => {
>
<text
id={`header-text-${label}`}
pointerEvents={sort ? 'default' : 'none'}
pointerEvents={sortable ? 'default' : 'none'}
dominantBaseline="middle"
textAnchor="middle"
>
{label}
</text>
{(sort && sortBy === label) &&
<HeaderSortArrow translateX={(dimensions.attribute.width / 2) - 16} translateY={-8} />
{(sortable && sortBy === label) &&
<HeaderSortArrow />
}
</g>
</g>
Expand Down
16 changes: 9 additions & 7 deletions packages/upset/src/components/Header/AttributeHeaders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ export const AttributeHeaders = () => {
<g
transform={translate(
dimensions.matrixColumn.width +
dimensions.gap +
dimensions.size.width +
dimensions.bookmarkStar.gap +
dimensions.bookmarkStar.width +
dimensions.bookmarkStar.gap +
dimensions.attribute.width +
dimensions.attribute.vGap,
dimensions.gap +
dimensions.size.width +
dimensions.bookmarkStar.gap +
dimensions.bookmarkStar.width +
dimensions.bookmarkStar.gap +
dimensions.degreeColumn.width +
dimensions.degreeColumn.gap +
dimensions.attribute.width +
dimensions.attribute.vGap,
dimensions.header.totalHeight - dimensions.attribute.height,
)}
>
Expand Down
128 changes: 128 additions & 0 deletions packages/upset/src/components/Header/DegreeHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { css } from '@emotion/react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useContext } from 'react';
import { Tooltip } from '@mui/material';
import { sortByOrderSelector, sortBySelector } from '../../atoms/config/sortByAtom';
import translate from '../../utils/transform';
import { HeaderSortArrow } from '../custom/HeaderSortArrow';
import { dimensionsSelector } from '../../atoms/dimensionsAtom';
import { contextMenuAtom } from '../../atoms/contextMenuAtom';
import { ProvenanceContext } from '../Root';

export const DegreeHeader = () => {
const { actions } = useContext(ProvenanceContext);
const sortBy = useRecoilValue(sortBySelector);
const sortByOrder = useRecoilValue(sortByOrderSelector);
const dimensions = useRecoilValue(dimensionsSelector);

const setContextMenu = useSetRecoilState(contextMenuAtom);

const sortByDegree = (order: string) => {
actions.sortBy('Degree', order);
};

const handleOnClick = () => {
if (sortBy !== 'Degree') {
sortByDegree('Ascending');
} else {
sortByDegree(sortByOrder === 'Ascending' ? 'Descending' : 'Ascending');
}
};

const handleContextMenuClose = () => {
setContextMenu(null);
};

const getMenuItems = () => [
{
label: 'Sort by Degree - Ascending',
onClick: () => {
sortByDegree('Ascending');
handleContextMenuClose();
},
disabled: sortBy === 'Degree' && sortByOrder === 'Ascending',
},
{
label: 'Sort by Degree - Descending',
onClick: () => {
sortByDegree('Descending');
handleContextMenuClose();
},
disabled: sortBy === 'Degree' && sortByOrder === 'Descending',
},
];

const openContextMenu = (e: MouseEvent) => {
setContextMenu(
{
mouseX: e.clientX,
mouseY: e.clientY,
id: 'header-menu-degree',
items: getMenuItems(),
},
);
};

return (
<g
transform={translate(
dimensions.matrixColumn.width +
dimensions.bookmarkStar.gap +
dimensions.bookmarkStar.width +
dimensions.bookmarkStar.gap,
dimensions.header.totalHeight - dimensions.attribute.buttonHeight - dimensions.attribute.scaleHeight + 1,
)}

>
<Tooltip title="Degree" arrow placement="top">
<g
className="degree-button"
css={css`
cursor: context-menu;
&:hover {
opacity: 0.7;
transition: opacity 0s;
}
`}
onContextMenu={(e) => {
e.preventDefault();
e.stopPropagation();
openContextMenu(e);
}}
onClick={handleOnClick}
>
<rect
fill="#ccc"
stroke="#000"
opacity="0.5"
strokeWidth="0.3px"
height={dimensions.size.buttonHeight}
width={dimensions.degreeColumn.width}
/>
<g
transform={translate(
dimensions.degreeColumn.width / 2,
dimensions.size.buttonHeight / 2,
)}
>
<text
id="header-text"
transform={
translate(0, 2)
}
css={css`
pointer-event: none;
`}
dominantBaseline="middle"
textAnchor="middle"
>
#
</text>
{ sortBy === 'Degree' &&
<HeaderSortArrow translateX={(dimensions.degreeColumn.width / 2) - 16} />}
</g>
</g>
</Tooltip>
</g>
);
};
4 changes: 3 additions & 1 deletion packages/upset/src/components/Header/DeviationHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ export const DeviationHeader = () => {
dimensions.bookmarkStar.gap +
dimensions.bookmarkStar.width +
dimensions.bookmarkStar.gap +
dimensions.degreeColumn.width +
dimensions.degreeColumn.gap +
dimensions.size.width +
dimensions.gap,
dimensions.header.totalHeight - dimensions.attribute.height,
)}
>
<AttributeButton label="Deviation" sort />
<AttributeButton label="Deviation" sortable />
<g
transform={translate(
0,
Expand Down
2 changes: 2 additions & 0 deletions packages/upset/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AttributeHeaders } from './AttributeHeaders';
import { DegreeHeader } from './DegreeHeader';
import { SizeHeader } from './SizeHeader';
import { DeviationHeader } from './DeviationHeader';
import { MatrixHeader } from './MatrixHeader';
Expand All @@ -8,6 +9,7 @@ export const Header = () => (
<>
<CollapseAllButton />
<MatrixHeader />
<DegreeHeader />
<SizeHeader />
<DeviationHeader />
<AttributeHeaders />
Expand Down
26 changes: 17 additions & 9 deletions packages/upset/src/components/Header/SizeHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,22 @@ export const SizeHeader: FC = () => {

const setContextMenu = useSetRecoilState(contextMenuAtom);

const handleContextMenuClose = () => {
setContextMenu(null);
};

const sortBySize = (order: string) => {
actions.sortBy('Size', order);
};

const handleOnClick = () => {
if (sortBy !== 'Size') {
sortBySize('Ascending');
} else {
sortBySize(sortByOrder === 'Ascending' ? 'Descending' : 'Ascending');
}
};

const handleContextMenuClose = () => {
setContextMenu(null);
};

const getMenuItems = () => [
{
label: 'Sort by Size - Ascending',
Expand Down Expand Up @@ -148,7 +156,9 @@ export const SizeHeader: FC = () => {
dimensions.matrixColumn.width +
dimensions.bookmarkStar.gap +
dimensions.bookmarkStar.width +
dimensions.bookmarkStar.gap,
dimensions.bookmarkStar.gap +
dimensions.degreeColumn.width +
dimensions.degreeColumn.gap,
dimensions.header.totalHeight - dimensions.size.height,
)}
>
Expand Down Expand Up @@ -232,6 +242,7 @@ export const SizeHeader: FC = () => {
e.stopPropagation();
openContextMenu(e);
}}
onClick={handleOnClick}
>
<rect
fill="#ccc"
Expand All @@ -240,9 +251,6 @@ export const SizeHeader: FC = () => {
strokeWidth="0.3px"
height={dimensions.size.buttonHeight}
width={dimensions.attribute.width}
onClick={() => {
if (sortBy !== 'Size') actions.sortBy('Size');
}}
/>
<g
transform={translate(
Expand All @@ -261,7 +269,7 @@ export const SizeHeader: FC = () => {
Size
</text>
{ sortBy === 'Size' &&
<HeaderSortArrow translateX={(dimensions.attribute.width / 2) - 16} translateY={-8} />
<HeaderSortArrow />
}
</g>
</g>
Expand Down
1 change: 1 addition & 0 deletions packages/upset/src/components/Matrix.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export const Matrix: FC<Props> = ({
fillOpacity="0.0"
/>
<MemberShipCircle
key={`circle ${set}`}
membershipStatus={membershipStatus}
cx={idx * dimensions.set.width}
cy={dimensions.body.rowHeight / 2}
Expand Down
2 changes: 1 addition & 1 deletion packages/upset/src/components/MatrixRows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export const MatrixRows: FC<Props> = ({ rows }) => {
<g onClick={(e) => e.stopPropagation()}>
{rowTransitions(({ transform }, item) => (
shouldRender(item.row) &&
<a.g transform={transform}>{rowRenderer(item.row)}</a.g>
<a.g key={item.id} transform={transform}>{rowRenderer(item.row)}</a.g>
))}
</g>
);
Expand Down
Loading

0 comments on commit ad191bf

Please sign in to comment.