/*
* SPDX-FileCopyrightText: 2023 The Refinery Authors
*
* SPDX-License-Identifier: EPL-2.0
*/
import CloseIcon from '@mui/icons-material/Close';
import FilterListIcon from '@mui/icons-material/FilterList';
import LabelIcon from '@mui/icons-material/Label';
import LabelOutlinedIcon from '@mui/icons-material/LabelOutlined';
import SentimentVeryDissatisfiedIcon from '@mui/icons-material/SentimentVeryDissatisfied';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
import Button from '@mui/material/Button';
import Checkbox from '@mui/material/Checkbox';
import FormControlLabel from '@mui/material/FormControlLabel';
import IconButton from '@mui/material/IconButton';
import Switch from '@mui/material/Switch';
import Typography from '@mui/material/Typography';
import { styled } from '@mui/material/styles';
import { observer } from 'mobx-react-lite';
import { useId } from 'react';
import type GraphStore from './GraphStore';
import { isVisibilityAllowed } from './GraphStore';
import RelationName from './RelationName';
const VisibilityDialogRoot = styled('div', {
name: 'VisibilityDialog-Root',
shouldForwardProp: (propName) => propName !== 'dialog',
})<{ dialog: boolean }>(({ theme, dialog }) => {
const overlayOpacity = dialog ? 0.16 : 0.09;
return {
maxHeight: '100%',
maxWidth: '100%',
overflow: 'hidden',
display: 'flex',
flexDirection: 'column',
'.VisibilityDialog-title': {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
padding: theme.spacing(1),
paddingLeft: theme.spacing(2),
borderBottom: `1px solid ${theme.palette.divider}`,
'& h2': {
flexGrow: 1,
},
'.MuiIconButton-root': {
flexGrow: 0,
flexShrink: 0,
marginLeft: theme.spacing(2),
},
},
'.MuiFormControlLabel-root': {
marginLeft: 0,
paddingTop: theme.spacing(1),
paddingLeft: theme.spacing(1),
'& + .MuiFormControlLabel-root': {
paddingTop: 0,
},
},
'.VisibilityDialog-scroll': {
display: 'flex',
flexDirection: 'column',
height: 'auto',
overflowX: 'hidden',
overflowY: 'auto',
margin: `0 ${theme.spacing(2)}`,
'& table': {
// We use flexbox instead of `display: table` to get proper text-overflow
// behavior for overly long relation names.
display: 'flex',
flexDirection: 'column',
},
'& thead, & tbody': {
display: 'flex',
flexDirection: 'column',
},
'& thead': {
position: 'sticky',
top: 0,
zIndex: 999,
backgroundColor: theme.palette.background.paper,
...(theme.palette.mode === 'dark'
? {
// In dark mode, MUI Paper gets a lighter overlay.
backgroundImage: `linear-gradient(
rgba(255, 255, 255, ${overlayOpacity}),
rgba(255, 255, 255, ${overlayOpacity})
)`,
}
: {}),
'& tr': {
height: '44px',
},
},
'& tr': {
display: 'flex',
flexDirection: 'row',
maxWidth: '100%',
},
'& tbody tr': {
transition: theme.transitions.create('background', {
duration: theme.transitions.duration.shortest,
}),
'&:hover': {
background: theme.palette.action.hover,
'@media (hover: none)': {
background: 'transparent',
},
},
},
'& th, & td': {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
// Set width in advance, since we can't rely on `display: table-cell`.
width: '44px',
},
'& th:nth-of-type(3), & td:nth-of-type(3)': {
justifyContent: 'start',
paddingLeft: theme.spacing(1),
paddingRight: theme.spacing(2),
// Only let the last column grow or shrink.
flexGrow: 1,
flexShrink: 1,
// Compute the maximum available space in advance to let the text overflow.
maxWidth: 'calc(100% - 88px)',
width: 'min-content',
},
'& td:nth-of-type(3)': {
cursor: 'pointer',
userSelect: 'none',
WebkitTapHighlightColor: 'transparent',
},
'& thead th, .VisibilityDialog-custom tr:last-child td': {
borderBottom: `1px solid ${theme.palette.divider}`,
},
},
// Hack to apply `text-overflow`.
'.VisibilityDialog-nowrap': {
maxWidth: '100%',
overflow: 'hidden',
wordWrap: 'nowrap',
textOverflow: 'ellipsis',
},
'.VisibilityDialog-buttons': {
padding: theme.spacing(1),
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
...(dialog
? {
marginTop: theme.spacing(1),
borderTop: `1px solid ${theme.palette.divider}`,
}
: {}),
},
'.VisibilityDialog-empty': {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
color: theme.palette.text.secondary,
},
'.VisibilityDialog-emptyIcon': {
fontSize: '6rem',
marginBottom: theme.spacing(1),
},
};
});
function VisibilityDialog({
graph,
close,
dialog,
}: {
graph: GraphStore;
close: () => void;
dialog?: boolean;
}): JSX.Element {
const titleId = useId();
const builtinRows: JSX.Element[] = [];
const rows: JSX.Element[] = [];
graph.relationMetadata.forEach((metadata, name) => {
if (!isVisibilityAllowed(metadata, 'must')) {
return;
}
const visibility = graph.getVisibility(name);
const row = (
graph.setVisibility(name, visibility === 'none' ? 'must' : 'none')
}
/>
|
graph.setVisibility(name, visibility === 'all' ? 'must' : 'all')
}
/>
|
graph.cycleVisibility(name)}>
|
);
if (name.startsWith('builtin::')) {
builtinRows.push(row);
} else {
rows.push(row);
}
});
const hasRows = rows.length > 0 || builtinRows.length > 0;
return (
{dialog && (
Customize view
)}
graph.toggleAbbrevaite()}
/>
}
label="Fully qualified names"
/>
graph.toggleScopes()} />
}
label="Object scopes"
/>
{hasRows ? (
|
|
Symbol |
{...rows}
{...builtinRows}
) : (
)}
{!dialog && (
)}
);
}
VisibilityDialog.defaultProps = {
dialog: false,
};
export default observer(VisibilityDialog);