Skip to content

Commit

Permalink
feat: add popup to error/warning counters
Browse files Browse the repository at this point in the history
  • Loading branch information
erdkse committed Nov 1, 2021
1 parent fe6789f commit d8ebd04
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 11 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import AppContext from '@src/AppContext';
import {NAVIGATOR_HEIGHT_OFFSET} from '@constants/constants';
import {ItemBlueprint} from '@models/navigator';
import {useAppDispatch, useAppSelector} from '@redux/hooks';
import {selectInstance} from '@redux/reducers/navigator';
import {useItemCustomization} from './useItemCustomization';
import * as S from './styled';

Expand All @@ -22,6 +23,7 @@ function NavSectionItem<ItemType, ScopeType>(props: {
const [isHovered, setIsHovered] = useState<boolean>(false);

const itemInstance = useAppSelector(state => state.navigator.itemInstanceMap[itemId]);
const selectedInstanceId = useAppSelector(state => state.navigator.selectedInstanceId);
const {instanceHandler} = blueprint;

const {Prefix, Suffix, QuickAction, ContextMenu} = useItemCustomization(blueprint.customization);
Expand Down Expand Up @@ -53,6 +55,14 @@ function NavSectionItem<ItemType, ScopeType>(props: {
}
}, [instanceHandler, itemInstance, dispatch]);

useEffect(() => {
if (selectedInstanceId && itemId === selectedInstanceId) {
onClick();
selectInstance(null);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedInstanceId]);

return (
<ScrollIntoView ref={scrollContainer}>
<S.ItemContainer
Expand Down
109 changes: 100 additions & 9 deletions src/components/organisms/NavigatorPane/WarningsAndErrorsDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React, {useMemo} from 'react';
import styled from 'styled-components';
import MonoIcon, {MonoIconTypes} from '@components/atoms/MonoIcon';
import {useAppSelector} from '@redux/hooks';
import {useAppSelector, useAppDispatch} from '@redux/hooks';
import {ResourceRefType} from '@models/k8sresource';
import Colors from '@styles/Colors';
import {isInPreviewModeSelector} from '@redux/selectors';
import {PREVIEW_PREFIX} from '@constants/constants';
import {Dropdown, Menu} from 'antd';
import {selectInstance} from '@redux/reducers/navigator';

const Container = styled.span`
width: 100%;
Expand All @@ -14,21 +16,106 @@ const Container = styled.span`
const WarningContainer = styled.span`
margin-left: 10px;
color: ${Colors.yellowWarning};
cursor: pointer;
`;

const ErrorContainer = styled.span`
margin-left: 10px;
color: ${Colors.redError};
cursor: pointer;
`;

const Label = styled.span`
margin-left: 3px;
`;

const StyledMenu = styled(Menu)`
max-height: 400px;
overflow-y: scroll;
padding: 4px 0;
`;

const StyledMenuItem = styled(Menu.Item)`
margin-bottom: 0 !important;
margin-top: 0 !important;
height: 28px !important;
line-height: 28px !important;
padding: 0 4px;
`;

type Warning = {
id: string;
type: string;
name: string;
count: number;
};

type RefDropdownMenuProps = {
warnings: Warning[];
};

const RefDropdownMenu = (props: RefDropdownMenuProps) => {
const dispatch = useAppDispatch();
const {warnings} = props;
return (
<StyledMenu>
{warnings.map(warning => (
<StyledMenuItem key={warning.id} onClick={() => dispatch(selectInstance(warning.id))}>
<Label>{warning.type}:</Label>
<Label>&nbsp;{warning.name}</Label>
<Label>&nbsp;({warning.count})</Label>
</StyledMenuItem>
))}
</StyledMenu>
);
};

function WarningsAndErrorsDisplay() {
const resourceMap = useAppSelector(state => state.main.resourceMap);
const isInPreviewMode = useAppSelector(isInPreviewModeSelector);

const warnings: any[] = useMemo(() => {
return Object.values(resourceMap)
.filter(resource =>
isInPreviewMode ? resource.filePath.startsWith(PREVIEW_PREFIX) : !resource.filePath.startsWith(PREVIEW_PREFIX)
)
.map(resource => {
if (resource.refs) {
const unsatisfiedRefs = resource.refs.filter(ref => ref.type === ResourceRefType.Unsatisfied);
if (unsatisfiedRefs.length > 0) {
return {
id: resource.id,
type: resource.kind,
name: resource.name,
count: unsatisfiedRefs.length,
};
}
return null;
}
return null;
})
.filter(warning => warning);
}, [resourceMap, isInPreviewMode]);

const errors: any[] = useMemo(() => {
return Object.values(resourceMap)
.filter(resource =>
isInPreviewMode ? resource.filePath.startsWith(PREVIEW_PREFIX) : !resource.filePath.startsWith(PREVIEW_PREFIX)
)
.map(resource => {
if (resource.validation && !resource.validation.isValid) {
return {
id: resource.id,
type: resource.kind,
name: resource.name,
count: resource.validation.errors.length,
};
}
return null;
})
.filter(error => error);
}, [resourceMap, isInPreviewMode]);

const warningsCount = useMemo(() => {
return Object.values(resourceMap)
.filter(resource =>
Expand All @@ -52,16 +139,20 @@ function WarningsAndErrorsDisplay() {
return (
<Container>
{warningsCount > 0 && (
<WarningContainer>
<MonoIcon type={MonoIconTypes.Warning} />
<Label>{warningsCount}</Label>
</WarningContainer>
<Dropdown overlay={<RefDropdownMenu warnings={warnings} />} trigger={['click']} placement="bottomCenter">
<WarningContainer>
<MonoIcon type={MonoIconTypes.Warning} />
<Label>{warningsCount}</Label>
</WarningContainer>
</Dropdown>
)}
{errorsCount > 0 && (
<ErrorContainer>
<MonoIcon type={MonoIconTypes.Error} />
<Label>{errorsCount}</Label>
</ErrorContainer>
<Dropdown overlay={<RefDropdownMenu warnings={errors} />} trigger={['click']} placement="bottomCenter">
<ErrorContainer>
<MonoIcon type={MonoIconTypes.Error} />
<Label>{errorsCount}</Label>
</ErrorContainer>
</Dropdown>
)}
</Container>
);
Expand Down
1 change: 1 addition & 0 deletions src/models/navigator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,5 @@ export interface NavigatorInstanceState {

export interface NavigatorState extends NavigatorInstanceState {
collapsedSectionIds: string[];
selectedInstanceId: string | null;
}
1 change: 1 addition & 0 deletions src/redux/initialState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ const initialNavigatorState: NavigatorState = {
sectionInstanceMap: {},
itemInstanceMap: {},
collapsedSectionIds: [],
selectedInstanceId: null,
};

export default {
Expand Down
6 changes: 5 additions & 1 deletion src/redux/reducers/navigator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ export const navigatorSlice = createSlice({
expandSectionIds: (state: Draft<NavigatorState>, action: PayloadAction<string[]>) => {
state.collapsedSectionIds = state.collapsedSectionIds.filter(sectionId => !action.payload.includes(sectionId));
},
selectInstance: (state: Draft<NavigatorState>, action: PayloadAction<string | null>) => {
state.selectedInstanceId = action.payload;
},
},
});

export const {updateNavigatorInstanceState, collapseSectionIds, expandSectionIds} = navigatorSlice.actions;
export const {updateNavigatorInstanceState, collapseSectionIds, expandSectionIds, selectInstance} =
navigatorSlice.actions;
export default navigatorSlice.reducer;

0 comments on commit d8ebd04

Please sign in to comment.