Skip to content

Commit

Permalink
Feat/result visualization (#330)
Browse files Browse the repository at this point in the history
* chore: Refactor object ResultArea component wiht new design.

* chore: Add simple dialog.

* chore: create initial plot with dummy data.

* chore: Update generated api files.

* chore: chore: Plot channel height data.

* chore: Add min and max to data for plot.

* chore: Add toggle between different plots.
  • Loading branch information
mheggelund authored Oct 10, 2024
1 parent 65ee09b commit 7108d3b
Show file tree
Hide file tree
Showing 17 changed files with 508 additions and 56 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@types/react": "^18.3.5",
"@types/react-dom": "18.3.0",
"axios": "^1.7.4",
"echarts": "^5.5.1",
"env-cmd": "^10.1.0",
"lodash": "^4.17.21",
"msal-react-tester": "^0.3.1",
Expand Down
1 change: 1 addition & 0 deletions src/api/generated/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export type { OutcropDto } from './models/OutcropDto';
export type { ParameterList } from './models/ParameterList';
export type { PatchAnalogueModelCommandResponse } from './models/PatchAnalogueModelCommandResponse';
export type { PatchAnalogueModelDto } from './models/PatchAnalogueModelDto';
export type { PercentilesDto } from './models/PercentilesDto';
export type { PrepareChunkedUploadCommandResponse } from './models/PrepareChunkedUploadCommandResponse';
export type { PrepareChunkedUploadDto } from './models/PrepareChunkedUploadDto';
export type { ProblemDetails } from './models/ProblemDetails';
Expand Down
3 changes: 3 additions & 0 deletions src/api/generated/models/GetVariogramResultsDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export type GetVariogramResultsDto = {
rvertical: number;
sigma: number;
quality: number;
qualityX: number;
qualityY: number;
qualityZ: number;
family: string;
archelFilter?: string | null;
indicator?: string | null;
Expand Down
7 changes: 7 additions & 0 deletions src/api/generated/models/ObjectEstimationResultDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@
/* tslint:disable */
/* eslint-disable */

import type { PercentilesDto } from './PercentilesDto';

export type ObjectEstimationResultDto = {
mean: number;
sd: number;
count: number;
coefficentOfVariation: number;
meanEstimateStandardError: number;
min: number;
max: number;
percentiles: PercentilesDto;
};

7 changes: 7 additions & 0 deletions src/api/generated/models/ObjectHeightDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@
/* tslint:disable */
/* eslint-disable */

import type { PercentilesDto } from './PercentilesDto';

export type ObjectHeightDto = {
mean: number;
sd: number;
count: number;
coefficentOfVariation: number;
meanEstimateStandardError: number;
min: number;
max: number;
percentiles: PercentilesDto;
modeSd: number;
modeMean: number;
};
Expand Down
17 changes: 17 additions & 0 deletions src/api/generated/models/PercentilesDto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* generated using openapi-typescript-codegen -- do no edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */

export type PercentilesDto = {
p10: number;
p20: number;
p30: number;
p40: number;
p50: number;
p60: number;
p70: number;
p80: number;
p90: number;
};

Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,8 @@ import { spacings } from '../../../../../tokens/spacings';
import { theme } from '../../../../../tokens/theme';

export const Wrapper = styled.div`
display: flex;
flex-direction: column;
border: solid 0.5px ${theme.light.ui.background.medium};
`;

export const InnerWrapper = styled.div`
display: flex;
flex-direction: row;
column-gap: ${spacings.LARGE};
border: solid 0.5px ${theme.light.ui.background.medium};
`;
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,15 @@ export const ChannelResult = ({

return (
<Styled.Wrapper>
<Styled.InnerWrapper>
<ResultArea
computeMethod={computeMethod}
modelArea={modelArea}
data={data}
></ResultArea>
<ChannelResultTable
data={data}
computeMethod={computeMethod}
></ChannelResultTable>
</Styled.InnerWrapper>
<ResultArea
computeMethod={computeMethod}
modelArea={modelArea}
data={data}
></ResultArea>
<ChannelResultTable
data={data}
computeMethod={computeMethod}
></ChannelResultTable>
</Styled.Wrapper>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Component 'Borrowed' from https://dev.to/manufac/using-apache-echarts-with-react-and-typescript-353k
* Echarts wrapper to make Echarts more usable with React lifecycle.
*
* This component only ensures that the chart is initialized with provided options, resizes the chart on container resize
* and cleans up the chart when the component is removed from DOM. It also interacts with echarts
* built in chart loading functionally such that this does not need to be done elsewhere.
*
* **Note: This base is configured such that the chart's width and height will be set to take the entire width and height
* of its parent element. This behaviour can be overridden using the {@see style} prop.**
*/

import {
ECharts,
EChartsOption,
getInstanceByDom,
init,
SetOptionOpts,
} from 'echarts';
import { CSSProperties, useEffect, useRef } from 'react';

export interface ReactEChartsProps {
option: EChartsOption;
style?: CSSProperties;
settings?: SetOptionOpts;
loading?: boolean;
theme?: 'light' | 'dark';
}

export function ReactECharts({
option,
style,
settings,
loading,
theme,
}: ReactEChartsProps): JSX.Element {
const chartRef = useRef<HTMLDivElement>(null);

useEffect(() => {
// Initialize chart
let chart: ECharts | undefined;

if (chartRef.current !== null) {
chart = init(chartRef.current, theme);
}

// Add chart resize listener
// ResizeObserver is leading to a bit janky UX
function resizeChart() {
chart?.resize();
}
window.addEventListener('resize', resizeChart);

// Return cleanup function
return () => {
chart?.dispose();
window.removeEventListener('resize', resizeChart);
};
}, [theme]);

useEffect(() => {
// Update chart
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
chart?.setOption(option, settings);
}
}, [option, settings, theme]); // Whenever theme changes we need to add option and setting due to it being deleted in cleanup function

useEffect(() => {
// Update chart
if (chartRef.current !== null) {
const chart = getInstanceByDom(chartRef.current);
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
loading === true ? chart?.showLoading() : chart?.hideLoading();
}
}, [loading, theme]);

return (
<div ref={chartRef} style={{ width: '100%', height: '350px', ...style }} />
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { PercentilesDto } from '../../../../../../api/generated';
import { ReactECharts, ReactEChartsProps } from '../Echarts/ReactECharts';

export interface ExtendedPrecetile extends PercentilesDto {
min: number;
max: number;
}
export const GraphPlot = ({
data,
mode,
}: {
data: ExtendedPrecetile | undefined;
mode: string;
}) => {
if (data === undefined) return <>Loading ... </>;

const option: ReactEChartsProps['option'] = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
grid: {
left: '10%',
right: '10%',
top: '10%',
bottom: '20%',
},
xAxis: {
type: 'value',
name: mode + ' (m)',
nameLocation: 'middle',
nameGap: 30,
},
yAxis: {
type: 'category',
data: Object.keys(data),
name: 'Precentile',
nameLocation: 'middle',
nameGap: 40,
},
series: [
{
type: 'line',
data: Object.values(data),
},
],
};

return (
<div>
<ReactECharts
option={option}
style={{ width: '100%', height: '350px' }}
/>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,52 @@ import { spacings } from '../../../../../../tokens/spacings';

export const Wrapper = styled.div`
display: flex;
flex-direction: row;
align-items: center;
padding-left: ${spacings.LARGE};
min-width: 320px;
flex-direction: column;
align-items: flex-start;
padding: ${spacings.MEDIUM_SMALL} 0 ${spacings.MEDIUM_SMALL} ${spacings.LARGE};
row-gap: ${spacings.MEDIUM_SMALL};
`;

export const Info = styled.div`
export const ResultHeader = styled.div`
display: flex;
flex-direction: column;
row-gap: ${spacings.MEDIUM};
width: 150px;
flex-direction: row;
justify-content: space-between;
width: 100%;
`;

export const Coordinates = styled.div`
export const MetadataWrapperDiv = styled.div`
display: flex;
flex-direction: column;
row-gap: ${spacings.MEDIUM};
flex-direction: row;
align-items: center;
`;

export const MetadataDiv = styled.div`
align-items: start;
padding-right: ${spacings.MEDIUM};
> label {
margin: 0;
}
`;

export const CoordinateRow = styled.div`
export const CoordinateDiv = styled.div`
display: flex;
flex-direction: row;
column-gap: ${spacings.MEDIUM};
`;

export const RowElement = styled.div`
white-space: nowrap;
> label {
margin: 0;
}
`;

export const Divider = styled.div`
width: 100%;
`;

export const VerticalDivider = styled.div`
width: 0px;
height: 100%;
margin: 0 ${spacings.MEDIUM};
border: 0.5px solid #e0e0e0;
`;
Loading

0 comments on commit 7108d3b

Please sign in to comment.