Skip to content

Commit

Permalink
Adjust tile size when legend changes.
Browse files Browse the repository at this point in the history
Restyle 'vertical' layout
  • Loading branch information
bgoldowsky committed Sep 10, 2024
1 parent 91a6e2d commit 6865b74
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 60 deletions.
56 changes: 44 additions & 12 deletions src/plugins/bar-graph/bar-graph-tile.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,80 @@
import React from "react";
import React, { useRef } from "react";
import classNames from "classnames";
import { observer } from "mobx-react";
import { useResizeDetector } from "react-resize-detector";

import { ChartArea } from "./chart-area";
import { LegendArea } from "./legend-area";
import { BasicEditableTileTitle } from "../../components/tiles/basic-editable-tile-title";
import { ITileProps } from "../../components/tiles/tile-component";
import { ChartArea } from "./chart-area";
import { BarGraphModelContext } from "./bar-graph-content-context";
import { isBarGraphModel } from "./bar-graph-content";
import { TileToolbar } from "../../components/toolbar/tile-toolbar";
import { LegendArea } from "./legend-area";

import "./bar-graph.scss";

import "./bar-graph-toolbar";

const legendWidth = 190;
const legendHeight = 190; // FIXME

export const BarGraphComponent: React.FC<ITileProps> = observer((props: ITileProps) => {

const { model, readOnly } = props;
const { model, readOnly, onRequestRowHeight } = props;
const content = isBarGraphModel(model.content) ? model.content : null;

const {height: containerHeight, width: containerWidth, ref} = useResizeDetector();
const requestedHeight = useRef<number|undefined>(undefined);

const onResize = (width: number|undefined, height: number|undefined) => {
let desiredTileHeight;
if (height) {
if (legendBelow) {
const desiredLegendHeight = height;
desiredTileHeight = 300 + desiredLegendHeight;

Check warning on line 31 in src/plugins/bar-graph/bar-graph-tile.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/bar-graph/bar-graph-tile.tsx#L30-L31

Added lines #L30 - L31 were not covered by tests
} else {
const desiredLegendHeight = Math.max(height, 260); // Leave room for at least 5 rows per spec
desiredTileHeight = desiredLegendHeight + 66;

Check warning on line 34 in src/plugins/bar-graph/bar-graph-tile.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/bar-graph/bar-graph-tile.tsx#L33-L34

Added lines #L33 - L34 were not covered by tests
}
if (requestedHeight.current !== desiredTileHeight) {
requestedHeight.current = desiredTileHeight;
onRequestRowHeight(model.id, desiredTileHeight);

Check warning on line 38 in src/plugins/bar-graph/bar-graph-tile.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/bar-graph/bar-graph-tile.tsx#L37-L38

Added lines #L37 - L38 were not covered by tests
}
}
};

// We use two resize detectors to track the size of the container and the size of the legend area
const { height: containerHeight, width: containerWidth, ref: containerRef } = useResizeDetector();

const { height: legendHeight, ref: legendRef } = useResizeDetector({
refreshMode: 'debounce',
refreshRate: 500,
skipOnMount: false,
onResize
});

let svgWidth = 10, svgHeight = 10;
// Legend is on the right if the width is >= 450px, otherwise below
const legendBelow = containerWidth && containerWidth < 450;
if (containerWidth && containerHeight) {
// Legend is on the right if the width is >= 450px
svgWidth = legendBelow ? containerWidth : containerWidth-legendWidth;
svgHeight = legendBelow ? containerHeight-legendHeight : containerHeight;
if (legendBelow) {
const vertPadding = 18;
svgWidth = containerWidth;

Check warning on line 59 in src/plugins/bar-graph/bar-graph-tile.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/bar-graph/bar-graph-tile.tsx#L58-L59

Added lines #L58 - L59 were not covered by tests
svgHeight = containerHeight - vertPadding - (legendHeight || 0);
} else {
svgWidth = containerWidth - legendWidth;
svgHeight = containerHeight;
}
}

return (
<BarGraphModelContext.Provider value={content}>
<BasicEditableTileTitle />
<TileToolbar tileType="bargraph" readOnly={!!readOnly} tileElement={props.tileElt} />
<div
ref={ref}
ref={containerRef}
className={classNames("bar-graph-content", legendBelow ? "vertical" : "horizontal", { "read-only": readOnly })}
data-testid="bar-graph-content"
>
<ChartArea width={svgWidth} height={svgHeight} />
<LegendArea />
<LegendArea legendRef={legendRef} />
</div>
</BarGraphModelContext.Provider>
);
Expand Down
52 changes: 40 additions & 12 deletions src/plugins/bar-graph/bar-graph.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@
align-items: center;
overflow: auto;

&.vertical {
flex-direction: column;
}

svg.bar-graph-svg {
// width: 100%;
// height: 100%;

.visx-bar-group .visx-bar {
stroke: black;
Expand Down Expand Up @@ -104,12 +98,46 @@
}
}

&.vertical div.bar-graph-legend {
width: 100%;
height: 186px;
border-top: 1.5px solid #0592af;
border-left: none;
padding: 8px 0 0 0;
// Overrides for vertical (legend underneath) layout
&.vertical {
flex-direction: column;

div.bar-graph-legend {
width: 100%;
height: auto;
border-top: 1.5px solid #0592af;
border-left: none;
padding: 8px 0 0 0;

.dataset-header {
margin-left: 5px;
align-items: center;

.dataset-label-text, .dataset-name {
display: inline-block;
margin-right: 5px;
}
}

.sort-by {
margin: 0 0 10px 20px;

button.chakra-menu__menu-button {
width: auto;
margin: 5px 0 0 5px;
}
}

.secondary-values {
display: flex;
flex-wrap: wrap;
margin-left: 8px;

.color-button {
margin: 0 7px 0 7px;
}
}
}
}

button.chakra-menu__menu-button {
Expand Down
75 changes: 40 additions & 35 deletions src/plugins/bar-graph/legend-area.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import { LegendSecondaryRow } from './legend-secondary-row';
import RemoveDataIcon from "../../assets/remove-data-icon.svg";
import DropdownCaretIcon from "../../assets/dropdown-caret.svg";

interface IProps {
legendRef: React.RefObject<HTMLDivElement>;
}

export const LegendArea = observer(function LegendArea () {
export const LegendArea = observer(function LegendArea ({legendRef}: IProps) {
const model = useBarGraphModelContext();

function unlinkDataset() {
Expand Down Expand Up @@ -38,44 +41,46 @@ export const LegendArea = observer(function LegendArea () {

return (
<div className="bar-graph-legend">
<div className="dataset-header">
<div className="dataset-icon">
<a onClick={unlinkDataset} aria-label={`Unlink ${model.dataSet.name}`}>
<RemoveDataIcon/>
</a>
<div className="inner-container" ref={legendRef}>
<div className="dataset-header">
<div className="dataset-icon">
<a onClick={unlinkDataset} aria-label={`Unlink ${model.dataSet.name}`}>
<RemoveDataIcon />
</a>
</div>
<div className="dataset-label">
<span className="dataset-label-text">Data from:</span>
<span className="dataset-name">{model.dataSet.name}</span>
</div>
</div>
<div className="dataset-label">
<span className="dataset-label-text">Data from:</span>
<span className="dataset-name">{model.dataSet.name}</span>
</div>
</div>

<div className="sort-by">
<div>
Sort by:
<div className="sort-by">
<span>
Sort by:
</span>
<Menu boundary="scrollParent">
<MenuButton>
<span className="button-content">
<span className="button-text">{currentLabel}</span>
<DropdownCaretIcon />
</span>
</MenuButton>
<Portal>
<MenuList>
<MenuItem onClick={() => setSecondaryAttribute(undefined)}>None</MenuItem>

Check warning on line 70 in src/plugins/bar-graph/legend-area.tsx

View check run for this annotation

Codecov / codecov/patch

src/plugins/bar-graph/legend-area.tsx#L70

Added line #L70 was not covered by tests
{availableAttributes.map((a) => (
<MenuItem key={a.id} onClick={() => setSecondaryAttribute(a.id)}>{a.name}</MenuItem>
))}
</MenuList>
</Portal>
</Menu>
</div>
<Menu boundary="scrollParent">
<MenuButton>
<span className="button-content">
<span className="button-text">{currentLabel}</span>
<DropdownCaretIcon/>
</span>
</MenuButton>
<Portal>
<MenuList>
<MenuItem onClick={() => setSecondaryAttribute(undefined)}>None</MenuItem>
{availableAttributes.map((a) => (
<MenuItem key={a.id} onClick={() => setSecondaryAttribute(a.id)}>{a.name}</MenuItem>
))}
</MenuList>
</Portal>
</Menu>
</div>

<div className="secondary-values">
{currentSecondary
? secondaryKeys.map((key) => <LegendSecondaryRow key={key} attrValue={key} />)
: <LegendSecondaryRow attrValue={currentPrimary.name}/> }
<div className="secondary-values">
{currentSecondary
? secondaryKeys.map((key) => <LegendSecondaryRow key={key} attrValue={key} />)
: <LegendSecondaryRow attrValue={currentPrimary.name} />}
</div>
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/graph/graph-registration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { GraphWrapperComponent } from "./components/graph-wrapper-component";
import { createGraphModel, GraphModel } from "./models/graph-model";
import { updateGraphContentWithNewSharedModelIds, updateGraphObjectWithNewSharedModelIds }
from "./utilities/graph-utils";
import { AppConfigModelType } from "../../models/stores/app-config-model";

import Icon from "./assets/graph-icon.svg";
import HeaderIcon from "./assets/graph-tile-id.svg";
import { AppConfigModelType } from "../../models/stores/app-config-model";

function graphAllowsMultipleDataSets(appConfig: AppConfigModelType) {
return !!appConfig.getSetting("defaultSeriesLegend", "graph");
Expand Down

0 comments on commit 6865b74

Please sign in to comment.