Skip to content
This repository was archived by the owner on Jan 19, 2025. It is now read-only.

feat(gui): separate column for statistics #689

Merged
merged 9 commits into from
Jun 21, 2022
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
31 changes: 24 additions & 7 deletions api-editor/gui/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {
selectShowUsageImportDialog,
selectUI,
selectShowAddFilterDialog,
selectShowStatistics,
} from '../features/ui/uiSlice';
import { initializeUsages, persistUsages, selectUsages } from '../features/usages/usageSlice';
import { initializePythonPackage, selectRawPythonPackage } from '../features/packageData/apiSlice';
Expand All @@ -69,6 +70,7 @@ import { AbstractPythonFilter } from '../features/filter/model/AbstractPythonFil
import { UsageCountStore } from '../features/usages/model/UsageCountStore';
import { PythonDeclaration } from '../features/packageData/model/PythonDeclaration';
import { SaveFilterDialog } from '../features/filter/SaveFilterDialog';
import { StatisticsView } from '../features/packageData/selectionView/StatisticsView';

export const App: React.FC = function () {
useIndexedDB();
Expand All @@ -93,25 +95,26 @@ export const App: React.FC = function () {
const showUsagesImportDialog = useAppSelector(selectShowUsageImportDialog);
const batchMode = useAppSelector(selectBatchMode);
const showAddFilterDialog = useAppSelector(selectShowAddFilterDialog);
const showStatistics = useAppSelector(selectShowStatistics);

return (
<>
<Grid
autoColumns="0fr 1fr 0fr"
autoRows="0fr 1fr"
templateAreas='"menu menu" "leftPane rightPane" "footer footer"'
autoRows="0fr 1fr 0fr"
templateAreas='"menu menu menu" "leftPane middlePane rightPane" "footer footer footer"'
w="100vw"
h="100vh"
>
<GridItem gridArea="menu" colSpan={2}>
<GridItem gridArea="menu" colSpan={3}>
<MenuBar displayInferErrors={displayInferErrors} />
</GridItem>
<GridItem
gridArea="leftPane"
overflow="auto"
minW="20vw"
w="40vw"
maxW="80vw"
w="30vw"
maxW="50vw"
borderRight={1}
layerStyle="subtleBorder"
resize="horizontal"
Expand Down Expand Up @@ -155,7 +158,7 @@ export const App: React.FC = function () {
)}
{currentUserAction.type === 'todo' && <TodoForm target={userActionTarget || rawPythonPackage} />}
</GridItem>
<GridItem gridArea="rightPane" overflow="auto">
<GridItem gridArea="middlePane" overflow="auto">
<Box flexGrow={1} overflowY="auto" width="100%">
{batchMode === BatchMode.None && <SelectionView />}

Expand Down Expand Up @@ -196,7 +199,21 @@ export const App: React.FC = function () {
)}
</Box>
</GridItem>
<GridItem gridArea="footer" colSpan={2}>
{showStatistics && (
<GridItem
gridArea="rightPane"
overflow="auto"
w="20vw"
borderLeft={1}
layerStyle="subtleBorder"
resize="horizontal"
>
<Box padding={4}>
<StatisticsView />
</Box>
</GridItem>
)}
<GridItem gridArea="footer" colSpan={3}>
{currentUserAction.type === 'none' && <ActionBar declaration={declaration} />}
</GridItem>

Expand Down
36 changes: 21 additions & 15 deletions api-editor/gui/src/common/MenuBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@ import {
BatchMode,
HeatMapMode,
selectHeatMapMode,
selectShowStatistics,
selectSortingMode,
setBatchMode,
setHeatMapMode,
setSortingMode,
SortingMode,
toggleAnnotationImportDialog,
toggleAPIImportDialog,
toggleStatisticsView,
toggleUsageImportDialog,
} from '../features/ui/uiSlice';
import { DeleteAllAnnotations } from './DeleteAllAnnotations';
import { GenerateAdapters } from './GenerateAdapters';
import { useNavigate } from 'react-router-dom';
import { FilterControls } from '../features/filter/FilterControls';

interface MenuBarProps {
Expand All @@ -44,11 +45,11 @@ interface MenuBarProps {
export const MenuBar: React.FC<MenuBarProps> = function ({ displayInferErrors }) {
const { colorMode, toggleColorMode } = useColorMode();
const dispatch = useAppDispatch();
const navigate = useNavigate();

const annotationStore = useAppSelector(selectAnnotationStore);
const sortingMode = useAppSelector(selectSortingMode);
const heatMapMode = useAppSelector(selectHeatMapMode);
const showStatistics = useAppSelector(selectShowStatistics);

const exportAnnotations = () => {
const a = document.createElement('a');
Expand All @@ -60,13 +61,12 @@ export const MenuBar: React.FC<MenuBarProps> = function ({ displayInferErrors })
a.click();
};

const setStatisticsViewPath = () => {
navigate(`/statistics-view`);
};

const colorModeArray: string[] = [];
const visualSettings: string[] = [];
if (colorMode === 'dark') {
colorModeArray.push('darkMode');
visualSettings.push('darkMode');
}
if (showStatistics) {
visualSettings.push('statistics');
}

return (
Expand Down Expand Up @@ -133,19 +133,25 @@ export const MenuBar: React.FC<MenuBarProps> = function ({ displayInferErrors })
</Menu>
</Box>

<Button onClick={setStatisticsViewPath}>Statistics View</Button>

<Box>
<Menu closeOnSelect={false}>
<MenuButton as={Button} rightIcon={<Icon as={FaChevronDown} />}>
Settings
</MenuButton>
<MenuList>
<MenuOptionGroup type="checkbox" value={colorModeArray}>
<MenuItemOption value={'darkMode'} onClick={toggleColorMode}>
Dark Mode
</MenuItemOption>
</MenuOptionGroup>
<MenuGroup title="Visual">
<MenuOptionGroup type="checkbox" value={visualSettings}>
<MenuItemOption value={'darkMode'} onClick={toggleColorMode}>
Dark Mode
</MenuItemOption>
<MenuItemOption
value={'statistics'}
onClick={() => dispatch(toggleStatisticsView())}
>
Show Statistics
</MenuItemOption>
</MenuOptionGroup>
</MenuGroup>
<MenuDivider />
<MenuGroup title="Module/Class/Function Sorting">
<MenuOptionGroup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,10 @@ import { ModuleView } from './ModuleView';
import { ParameterView } from './ParameterView';
import { useAppSelector } from '../../../app/hooks';
import { selectRawPythonPackage } from '../apiSlice';
import { StatisticsView } from './StatisticsView';

export const SelectionView: React.FC = function () {
const rawPythonPackage = useAppSelector(selectRawPythonPackage);
const declaration = rawPythonPackage.getDeclarationById(useLocation().pathname.split('/').splice(1).join('/'));
const location = useLocation().pathname;

if (location === '/statistics-view') {
return (
<Box overflowY="auto" h="100%" w="100%" padding={4}>
<StatisticsView />
</Box>
);
}

if (!declaration) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import { Bar, Line } from 'react-chartjs-2';
import { PythonPackage } from '../model/PythonPackage';
import { UsageCountStore } from '../../usages/model/UsageCountStore';
import { Box, Flex, Button, Heading, VStack, Wrap, WrapItem } from '@chakra-ui/react';
import { Box, Button, Flex, Heading, SimpleGrid, VStack } from '@chakra-ui/react';
import { selectAnnotationStore } from '../../annotations/annotationSlice';
import { useAppDispatch, useAppSelector } from '../../../app/hooks';
import { selectFilterString, setFilterString } from '../../ui/uiSlice';
Expand Down Expand Up @@ -64,21 +64,24 @@ export const StatisticsView: React.FC = function () {
rawPythonPackage,
thresholds,
usages.getNumberOfUsedPublicClasses,
'Classes per Threshold',
'Classes',
'Minimum usefulness',
);
const functionLineChart = createLineChart(
usages,
rawPythonPackage,
thresholds,
usages.getNumberOfUsedPublicFunctions,
'Functions per Threshold',
'Functions',
'Minimum usefulness',
);
const parameterLineChart = createLineChart(
usages,
rawPythonPackage,
thresholds,
usages.getNumberOfUsefulPublicParameters,
'Parameters per Threshold',
'Parameters',
'Minimum usefulness',
);

const filterAction = (annotation: string) => {
Expand All @@ -100,9 +103,34 @@ export const StatisticsView: React.FC = function () {
};

return (
<VStack spacing="4">
<Heading as="h2" size="md">
Statistics
<VStack spacing={4}>
<Heading as="h3" size="md">
Annotations
</Heading>
<SimpleGrid columns={2} spacing={2}>
<Button onClick={() => filterAction('attribute')} children={'Attributes: ' + attributesSize}></Button>
<Button onClick={() => filterAction('boundary')} children={'Boundaries: ' + boundariesSize}></Button>
<Button
onClick={() => filterAction('calledAfter')}
children={'CalledAfter: ' + calledAftersSize}
></Button>
<Button onClick={() => filterAction('constant')} children={'Constants: ' + constantsSize}></Button>
<Button
onClick={() => filterAction('description')}
children={'Descriptions: ' + descriptionSize}
></Button>
<Button onClick={() => filterAction('enum')} children={'Enums: ' + enumsSize}></Button>
<Button onClick={() => filterAction('group')} children={'Groups: ' + groupsSize}></Button>
<Button onClick={() => filterAction('move')} children={'Move: ' + movesSize}></Button>
<Button onClick={() => filterAction('optional')} children={'Optionals: ' + optionalsSize}></Button>
<Button onClick={() => filterAction('pure')} children={'Pures: ' + puresSize}></Button>
<Button onClick={() => filterAction('remove')} children={'Removes: ' + removesSize}></Button>
<Button onClick={() => filterAction('rename')} children={'Renaming: ' + renamingsSize}></Button>
<Button onClick={() => filterAction('required')} children={'Requireds: ' + requiredsSize}></Button>
<Button onClick={() => filterAction('todo')} children={'Todos: ' + todoSize}></Button>
</SimpleGrid>
<Heading as="h3" size="md">
API Size
</Heading>
<Box width="100%">
<Flex wrap="wrap">
Expand All @@ -117,6 +145,9 @@ export const StatisticsView: React.FC = function () {
</Box>
</Flex>
</Box>
<Heading as="h3" size="md">
API Size per Minimum Usefulness Threshold
</Heading>
<Box width="100%">
<Flex wrap="wrap">
<Box minWidth="350px" flex="1 1 33%">
Expand All @@ -130,65 +161,6 @@ export const StatisticsView: React.FC = function () {
</Box>
</Flex>
</Box>
<Heading as="h3" size="md">
Annotations
</Heading>
<Wrap mx="auto" padding="10px 10px 10px 10px">
<WrapItem>
<Button
onClick={() => filterAction('attribute')}
children={'Attributes: ' + attributesSize}
></Button>
</WrapItem>
<WrapItem>
<Button
onClick={() => filterAction('boundary')}
children={'Boundaries: ' + boundariesSize}
></Button>
</WrapItem>
<WrapItem>
<Button
onClick={() => filterAction('calledAfter')}
children={'CalledAfter: ' + calledAftersSize}
></Button>
</WrapItem>
<WrapItem>
<Button onClick={() => filterAction('constant')} children={'Constants: ' + constantsSize}></Button>
</WrapItem>
<WrapItem>
<Button
onClick={() => filterAction('description')}
children={'Descriptions: ' + descriptionSize}
></Button>
</WrapItem>
<WrapItem>
<Button onClick={() => filterAction('enum')} children={'Enums: ' + enumsSize}></Button>
</WrapItem>
<WrapItem>
<Button onClick={() => filterAction('group')} children={'Groups: ' + groupsSize}></Button>
</WrapItem>
<WrapItem>
<Button onClick={() => filterAction('move')} children={'Move: ' + movesSize}></Button>
</WrapItem>
<WrapItem>
<Button onClick={() => filterAction('optional')} children={'Optionals: ' + optionalsSize}></Button>
</WrapItem>
<WrapItem>
<Button onClick={() => filterAction('pure')} children={'Pures: ' + puresSize}></Button>
</WrapItem>
<WrapItem>
<Button onClick={() => filterAction('remove')} children={'Removes: ' + removesSize}></Button>
</WrapItem>
<WrapItem>
<Button onClick={() => filterAction('rename')} children={'Renaming: ' + renamingsSize}></Button>
</WrapItem>
<WrapItem>
<Button onClick={() => filterAction('required')} children={'Requireds: ' + requiredsSize}></Button>
</WrapItem>
<WrapItem>
<Button onClick={() => filterAction('todo')} children={'Todos: ' + todoSize}></Button>
</WrapItem>
</Wrap>
</VStack>
);
};
Expand Down Expand Up @@ -272,6 +244,7 @@ let createLineChart = function (
labels: number[],
getValue: Function,
title: string,
xAxisLabel: string,
): ReactElement {
const options = {
responsive: true,
Expand All @@ -284,6 +257,14 @@ let createLineChart = function (
text: title,
},
},
scales: {
x: {
title: {
display: true,
text: xAxisLabel,
},
},
},
};

const dataValues = new Map();
Expand Down
7 changes: 7 additions & 0 deletions api-editor/gui/src/features/ui/uiSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface UIState {
filterList: Filter[];
sortingMode: SortingMode;
batchMode: BatchMode;
showStatistics: boolean;
}

type UserAction =
Expand Down Expand Up @@ -147,6 +148,7 @@ export const initialState: UIState = {
heatMapMode: HeatMapMode.None,
sortingMode: SortingMode.Alphabetical,
batchMode: BatchMode.None,
showStatistics: true,
};

// Thunks --------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -330,6 +332,9 @@ const uiSlice = createSlice({
setBatchMode(state, action: PayloadAction<BatchMode>) {
state.batchMode = action.payload;
},
toggleStatisticsView(state) {
state.showStatistics = !state.showStatistics;
},
},
extraReducers(builder) {
builder.addCase(initializeUI.fulfilled, (state, action) => action.payload);
Expand Down Expand Up @@ -371,6 +376,7 @@ export const {
removeFilter,
setSortingMode,
setBatchMode,
toggleStatisticsView,
} = actions;
export const uiReducer = reducer;

Expand Down Expand Up @@ -406,3 +412,4 @@ export const selectFilter = createSelector(
);
export const selectSortingMode = (state: RootState): SortingMode => selectUI(state).sortingMode;
export const selectBatchMode = (state: RootState): BatchMode => selectUI(state).batchMode;
export const selectShowStatistics = (state: RootState): boolean => selectUI(state).showStatistics;