Skip to content
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
150 changes: 77 additions & 73 deletions src/components/GraphPanel/GraphPanel.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ const GraphPanel = ({
onGraphSelect,
onNewGraph,
disableAnimation = false,
hideHeader = false,
hideFooter = false,
}) => {
const chartRef = useRef(null);
const containerRef = useRef(null);
Expand Down Expand Up @@ -561,82 +563,84 @@ const GraphPanel = ({

return (
<div className={styles.container}>
<div className={styles.header}>
<h2 className={styles.title}>{currentGraphTitle}</h2>
<div className={styles.headerButtons}>
{showDropdown && (
<div className={styles.dropdown} ref={dropdownRef}>
<button
className={styles.dropdownTrigger}
onClick={() => setShowGraphDropdown(!showGraphDropdown)}
aria-label="Select graph"
title="Select graph"
>
<Icon name="down-solid" width={14} height={14} fill="#ffffff" />
</button>
{showGraphDropdown && (
<div className={styles.dropdownMenu}>
{availableGraphs.map((graph) => (
{!hideHeader && (
<div className={styles.header}>
<h2 className={styles.title}>{currentGraphTitle}</h2>
<div className={styles.headerButtons}>
{showDropdown && (
<div className={styles.dropdown} ref={dropdownRef}>
<button
className={styles.dropdownTrigger}
onClick={() => setShowGraphDropdown(!showGraphDropdown)}
aria-label="Select graph"
title="Select graph"
>
<Icon name="down-solid" width={14} height={14} fill="#ffffff" />
</button>
{showGraphDropdown && (
<div className={styles.dropdownMenu}>
{availableGraphs.map((graph) => (
<button
key={graph.id}
className={`${styles.dropdownItem} ${graph.id === graphConfig?.id ? styles.dropdownItemActive : ''}`}
onClick={() => handleGraphSelect(graph)}
>
<span className={styles.dropdownItemTitle}>
{graph.title || 'Graph'}
</span>
<span className={styles.dropdownItemType}>
{graph.chartType}
</span>
</button>
))}
<div className={styles.dropdownSeparator} />
<button
key={graph.id}
className={`${styles.dropdownItem} ${graph.id === graphConfig?.id ? styles.dropdownItemActive : ''}`}
onClick={() => handleGraphSelect(graph)}
className={styles.dropdownItem}
onClick={handleNewGraph}
>
<span className={styles.dropdownItemTitle}>
{graph.title || 'Graph'}
</span>
<span className={styles.dropdownItemType}>
{graph.chartType}
</span>
<Icon name="plus" width={12} height={12} />
<span>Create Graph</span>
</button>
))}
<div className={styles.dropdownSeparator} />
<button
className={styles.dropdownItem}
onClick={handleNewGraph}
>
<Icon name="plus" width={12} height={12} />
<span>Create Graph</span>
</button>
</div>
)}
</div>
)}
{hasActiveGraph && onEdit && (
<button
type="button"
onClick={() => onEdit()}
className={styles.editButton}
aria-label="Edit graph configuration"
title="Edit graph"
>
<Icon name="edit-solid" width={14} height={14} fill="#ffffff" />
</button>
)}
{hasActiveGraph && onRefresh && (
<button
type="button"
onClick={() => onRefresh()}
className={styles.refreshButton}
aria-label="Refresh graph data"
title="Refresh graph"
>
<Icon name="refresh-solid" width={14} height={14} fill="#ffffff" />
</button>
)}
{onClose && (
<button
type="button"
onClick={() => onClose()}
className={styles.closeButton}
aria-label="Close graph panel"
title="Close graph"
>
<Icon name="x-solid" width={14} height={14} fill="#ffffff" />
</button>
)}
</div>
)}
</div>
)}
{hasActiveGraph && onEdit && (
<button
type="button"
onClick={() => onEdit()}
className={styles.editButton}
aria-label="Edit graph configuration"
title="Edit graph"
>
<Icon name="edit-solid" width={14} height={14} fill="#ffffff" />
</button>
)}
{hasActiveGraph && onRefresh && (
<button
type="button"
onClick={() => onRefresh()}
className={styles.refreshButton}
aria-label="Refresh graph data"
title="Refresh graph"
>
<Icon name="refresh-solid" width={14} height={14} fill="#ffffff" />
</button>
)}
{onClose && (
<button
type="button"
onClick={() => onClose()}
className={styles.closeButton}
aria-label="Close graph panel"
title="Close graph"
>
<Icon name="x-solid" width={14} height={14} fill="#ffffff" />
</button>
)}
</div>
</div>
</div>
)}

<div className={styles.chartContainer} ref={containerRef}>
{isLoading ? (
Expand All @@ -651,7 +655,7 @@ const GraphPanel = ({
)}
</div>

{graphConfig && (
{graphConfig && !hideFooter && (
<div className={styles.configInfo}>
<small>
Data points: {data?.length || 0}
Expand Down
3 changes: 1 addition & 2 deletions src/components/GraphPanel/GraphPanel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
height: 100%;
display: flex;
flex-direction: column;
background: #fefafb;
border-radius: 4px;
}

Expand Down Expand Up @@ -159,7 +158,7 @@
.chartContainer {
flex: 1;
padding: 16px;
min-height: 300px;
min-height: 100px;
position: relative;
}

Expand Down
26 changes: 14 additions & 12 deletions src/dashboard/Data/Browser/DataBrowser.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -2199,18 +2199,20 @@ export default class DataBrowser extends React.Component {
className={styles.resizablePanel}
style={{ right: aggregationPanelWidth }}
>
<GraphPanel
graphConfig={this.state.graphConfig}
data={this.props.data}
columns={this.props.columns}
isLoading={!this.props.data}
onRefresh={this.handleRefresh}
onEdit={this.showGraphDialog}
onClose={this.toggleGraphPanelVisibility}
availableGraphs={this.state.availableGraphs}
onGraphSelect={this.selectGraph}
onNewGraph={this.showNewGraphDialog}
/>
<div className={styles.graphPanelContainer}>
<GraphPanel
graphConfig={this.state.graphConfig}
data={this.props.data}
columns={this.props.columns}
isLoading={!this.props.data}
onRefresh={this.handleRefresh}
onEdit={this.showGraphDialog}
onClose={this.toggleGraphPanelVisibility}
availableGraphs={this.state.availableGraphs}
onGraphSelect={this.selectGraph}
onNewGraph={this.showNewGraphDialog}
/>
</div>
</ResizableBox>
);
})()}
Expand Down
6 changes: 6 additions & 0 deletions src/dashboard/Data/Browser/Databrowser.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
background-color: #fefafb;
}

.graphPanelContainer{
height: 100%;
overflow: auto;
background-color: #fefafb;
}

.multiPanelWrapper {
display: flex;
flex-direction: row;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Label from 'components/Label/Label.react';
import Dropdown from 'components/Dropdown/Dropdown.react';
import Option from 'components/Dropdown/Option.react';
import TextInput from 'components/TextInput/TextInput.react';
import Toggle from 'components/Toggle/Toggle.react';

const GraphConfigDialog = ({
initialConfig,
Expand All @@ -21,10 +22,13 @@ const GraphConfigDialog = ({
onClose,
onSave,
}) => {
const [title, setTitle] = useState(initialConfig?.title || '');
const [className, setClassName] = useState(initialConfig?.className || '');
const [graphId, setGraphId] = useState(initialConfig?.graphId || '');
const [filterId, setFilterId] = useState(initialConfig?.filterId || '');
const [limit, setLimit] = useState(initialConfig?.limit?.toString() || '1000');
const [showLegend, setShowLegend] = useState(initialConfig?.showLegend ?? true);
const [showAxisLabels, setShowAxisLabels] = useState(initialConfig?.showAxisLabels ?? true);

const classesWithGraphs = useMemo(() => {
return classes
Expand Down Expand Up @@ -68,12 +72,15 @@ const GraphConfigDialog = ({
const selectedFilter = filtersForClass.find(f => f.id === filterId);

onSave({
title: title || selectedGraph?.title || 'Graph',
className,
graphId,
graphConfig: selectedGraph,
filterId: filterId || null,
filterConfig: selectedFilter ? [selectedFilter] : null,
limit: parseInt(limit, 10) || 1000,
showLegend,
showAxisLabels,
});
};

Expand Down Expand Up @@ -102,6 +109,16 @@ const GraphConfigDialog = ({
/>
) : (
<>
<Field
label={<Label text="Title" description="Custom title for the graph element" />}
input={
<TextInput
value={title}
onChange={setTitle}
placeholder={selectedGraph?.title || 'Graph'}
/>
}
/>
<Field
label={<Label text="Class" description="Select the class containing the graph" />}
input={
Expand Down Expand Up @@ -165,6 +182,30 @@ const GraphConfigDialog = ({
}
/>
)}
{className && graphId && (
<>
<Field
label={<Label text="Show Legend" description="Display the graph legend" />}
input={
<Toggle
value={showLegend}
onChange={setShowLegend}
type={Toggle.Types.YES_NO}
/>
}
/>
<Field
label={<Label text="Show Axis Labels" description="Display the Y-axis labels" />}
input={
<Toggle
value={showAxisLabels}
onChange={setShowAxisLabels}
type={Toggle.Types.YES_NO}
/>
}
/>
</>
)}
</>
)}
</Modal>
Expand Down
39 changes: 30 additions & 9 deletions src/dashboard/Data/CustomDashboard/elements/GraphElement.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,38 @@ const GraphElement = ({
);
}

const title = config.title || config.graphConfig?.title || 'Graph';

// Apply overrides from config (title removed, legend and axis labels configurable)
const modifiedGraphConfig = {
...config.graphConfig,
title: undefined,
showLegend: config.showLegend ?? config.graphConfig?.showLegend ?? true,
showAxisLabels: config.showAxisLabels ?? config.graphConfig?.showAxisLabels ?? true,
};

return (
<div className={styles.graphElement}>
<GraphPanel
graphConfig={config.graphConfig}
data={data}
columns={columns}
isLoading={isLoading}
error={error}
onRefresh={onRefresh}
disableAnimation={true}
/>
<div className={styles.graphHeader}>
<span className={styles.graphTitle}>{title}</span>
{onRefresh && (
<button type="button" onClick={onRefresh} className={styles.refreshButton}>
<Icon name="refresh-solid" width={12} height={12} fill="#94a3b8" />
</button>
)}
</div>
<div className={styles.graphContainer}>
<GraphPanel
graphConfig={modifiedGraphConfig}
data={data}
columns={columns}
isLoading={isLoading}
error={error}
disableAnimation={true}
hideHeader={true}
hideFooter={true}
/>
</div>
</div>
);
};
Expand Down
Loading
Loading