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

feat: Add descriptive statistics for number cells in data browser #2529

Merged
merged 7 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
21 changes: 19 additions & 2 deletions src/components/BrowserCell/BrowserCell.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,6 @@ export default class BrowserCell extends Component {
hidden,
width,
current,
onSelect,
onEditChange,
setCopyableValue,
onPointerCmdClick,
Expand All @@ -536,6 +535,8 @@ export default class BrowserCell extends Component {
onEditSelectedRow,
isRequired,
markRequiredFieldRow,
handleCellClick,
selectedCells,
} = this.props;

const classes = [...this.state.classes];
Expand Down Expand Up @@ -573,6 +574,22 @@ export default class BrowserCell extends Component {
);
}

if (selectedCells?.list.has(`${row}-${col}`)) {
if (selectedCells.rowStart === row) {
classes.push(styles.topBorder);
}
if (selectedCells.rowEnd === row) {
classes.push(styles.bottomBorder);
}
if (selectedCells.colStart === col) {
classes.push(styles.leftBorder);
}
if (selectedCells.colEnd === col) {
classes.push(styles.rightBorder);
}
classes.push(styles.selected);
}

return (
<span
ref={this.cellRef}
Expand All @@ -582,8 +599,8 @@ export default class BrowserCell extends Component {
if (e.metaKey === true && type === 'Pointer') {
onPointerCmdClick(value);
} else {
onSelect({ row, col });
setCopyableValue(hidden ? undefined : this.copyableValue);
handleCellClick(e, row, col);
}
}}
onDoubleClick={() => {
Expand Down
66 changes: 65 additions & 1 deletion src/components/BrowserCell/BrowserCell.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,71 @@
}
}

.hasMore{
.leftBorder {
position: relative;

&:after {
position: absolute;
pointer-events: none;
content: '';
border-left: 2px solid #555572;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}

.rightBorder {
position: relative;

&:after {
position: absolute;
pointer-events: none;
content: '';
border-right: 2px solid #555572;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}

.topBorder {
position: relative;

&:after {
position: absolute;
pointer-events: none;
content: '';
border-top: 2px solid #555572;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}

.bottomBorder {
position: relative;

&:after {
position: absolute;
pointer-events: none;
content: '';
border-bottom: 2px solid #555572;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}

.selected {
background-color: #e3effd;
}

.hasMore {
height: auto;
max-height: 25px;
overflow-y: scroll;
Expand Down
2 changes: 2 additions & 0 deletions src/components/BrowserRow/BrowserRow.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ export default class BrowserRow extends Component {
showNote={this.props.showNote}
onRefresh={this.props.onRefresh}
scripts={this.props.scripts}
handleCellClick={this.props.handleCellClick}
selectedCells={this.props.selectedCells}
/>
);
})}
Expand Down
103 changes: 102 additions & 1 deletion src/components/Toolbar/Toolbar.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,110 @@
* the root directory of this source tree.
*/
import PropTypes from 'lib/PropTypes';
import React from 'react';
import React, { useEffect } from 'react';
import Icon from 'components/Icon/Icon.react';
import styles from 'components/Toolbar/Toolbar.scss';
import Popover from 'components/Popover/Popover.react';
import Position from 'lib/Position';
import { useNavigate, useNavigationType, NavigationType } from 'react-router-dom';

const POPOVER_CONTENT_ID = 'toolbarStatsPopover';

const Stats = ({ data }) => {
const [selected, setSelected] = React.useState(null);
const [open, setOpen] = React.useState(false);
const buttonRef = React.useRef();

const statsOptions = [
{
type: 'sum',
label: 'Sum',
getValue: data => data.reduce((sum, value) => sum + value, 0),
},
{
type: 'mean',
label: 'Mean',
getValue: data => data.reduce((sum, value) => sum + value, 0) / data.length,
},
{
type: 'count',
label: 'Count',
getValue: data => data.length,
},
{
type: 'p99',
label: 'P99',
getValue: data => {
const sorted = data.sort((a, b) => a - b);
return sorted[Math.floor(sorted.length * 0.99)];
},
},
];

const toggle = () => {
setOpen(!open);
};

const renderPopover = () => {
const node = buttonRef.current;
const position = Position.inDocument(node);
return (
<Popover
fixed={true}
position={position}
onExternalClick={toggle}
contentId={POPOVER_CONTENT_ID}
>
<div id={POPOVER_CONTENT_ID}>
<div
onClick={toggle}
style={{
cursor: 'pointer',
width: node.clientWidth,
height: node.clientHeight,
}}
></div>
<div className={styles.stats_popover_container}>
{statsOptions.map(item => {
const itemStyle = [styles.stats_popover_item];
if (item.type === selected?.type) {
itemStyle.push(styles.active);
}
return (
<div
key={item.type}
className={itemStyle.join(' ')}
onClick={() => {
setSelected(item);
toggle();
}}
>
<span>{item.label}</span>
</div>
);
})}
</div>
</div>
</Popover>
);
};

useEffect(() => {
setSelected(statsOptions[0]);
}, []);

return (
<>
{selected ? (
<button ref={buttonRef} className={styles.stats} onClick={toggle}>
{`${selected.label}: ${selected.getValue(data)}`}
</button>
) : null}
{open ? renderPopover() : null}
</>
);
};

const Toolbar = props => {
const action = useNavigationType();
const navigate = useNavigate();
Expand All @@ -34,6 +133,7 @@ const Toolbar = props => {
</div>
</div>
</div>
{props.selectedData.length ? <Stats data={props.selectedData} /> : null}
<div className={styles.actions}>{props.children}</div>
</div>
);
Expand All @@ -44,6 +144,7 @@ Toolbar.propTypes = {
subsection: PropTypes.string,
details: PropTypes.string,
relation: PropTypes.object,
selectedData: PropTypes.array,
};

export default Toolbar;
38 changes: 38 additions & 0 deletions src/components/Toolbar/Toolbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,41 @@ body:global(.expanded) {
right: 14px;
top: 4px;
}

.stats {
position: absolute;
right: 20px;
bottom: 10px;
background: $blue;
border-radius: 3px;
padding: 2px 4px;
font-size: 16px;
color: white;
box-shadow: none;
border: none;
}

.stats_popover_container {
display: flex;
flex-direction: column;
background: $blue;
gap: 4px;
padding: 2px 0px;
font-size: 16px;
mtrezza marked this conversation as resolved.
Show resolved Hide resolved
color: white;
}

.stats_popover_item {
cursor: pointer;
padding: 0px 8px;

&:hover {
color: $blue;
background-color: white;
}
}

.active {
color: $blue;
background-color: white;
}
6 changes: 6 additions & 0 deletions src/dashboard/Data/Browser/BrowserTable.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ export default class BrowserTable extends React.Component {
showNote={this.props.showNote}
onRefresh={this.props.onRefresh}
scripts={this.context.scripts}
selectedCells={this.props.selectedCells}
handleCellClick={this.props.handleCellClick}
/>
<Button
value="Clone"
Expand Down Expand Up @@ -236,6 +238,8 @@ export default class BrowserTable extends React.Component {
showNote={this.props.showNote}
onRefresh={this.props.onRefresh}
scripts={this.context.scripts}
selectedCells={this.props.selectedCells}
handleCellClick={this.props.handleCellClick}
/>
<Button
value="Add"
Expand Down Expand Up @@ -312,6 +316,8 @@ export default class BrowserTable extends React.Component {
showNote={this.props.showNote}
onRefresh={this.props.onRefresh}
scripts={this.context.scripts}
selectedCells={this.props.selectedCells}
handleCellClick={this.props.handleCellClick}
/>
);
}
Expand Down
3 changes: 3 additions & 0 deletions src/dashboard/Data/Browser/BrowserToolbar.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ const BrowserToolbar = ({
login,
logout,
toggleMasterKeyUsage,

selectedData,
}) => {
const selectionLength = Object.keys(selection).length;
const isPendingEditCloneRows = editCloneRows && editCloneRows.length > 0;
Expand Down Expand Up @@ -238,6 +240,7 @@ const BrowserToolbar = ({
section={relation ? `Relation <${relation.targetClassName}>` : 'Class'}
subsection={subsection}
details={details.join(' \u2022 ')}
selectedData={selectedData}
>
{onAddRow && (
<a className={classes.join(' ')} onClick={onClick}>
Expand Down
Loading
Loading