Skip to content

Commit

Permalink
refactor: rename EntityListContent to EntityView (#959)
Browse files Browse the repository at this point in the history
* refactor: rename EntityListContent to EntityView

* chore: remove unused filter props model

* chore: remove unused EntityListBlueprint

* refactor: entity filters types

* refactor: define slots for view component and switch

* fix: EntityGrid useMemo

* feat: add isListLoading prop

* feat: add executor/status icon size prop

* feat: is test/test-suite with execution check

* feat: add tests/testSuites metrics provider

* feat: secondary label list item

* feat: view component additional props

* refactor: testsMetrics and testSuitesMetrics

* feat: labels filters key value input

* feat: EntityGridItemDropdown

* refactor: separate styled component for entity view

* feat: view component base props

* feat: reusable EntityDropdown atom

* refactor: dots dropdown open prop

* refactor: navigate link

* refactor: do not use cloneElement

* refactor: remove onAbort + abort all executions

* refactor: add test/test suite button

* refactor: smaller filters width

* refactor: table sorting style

* refactor: filters flex

* refactor: changes

* refactor: metrics for grid/table view

* refactor: improvements

* chore: remove unused
  • Loading branch information
topliceanurazvan authored Dec 15, 2023
1 parent 57c31d9 commit df55203
Show file tree
Hide file tree
Showing 58 changed files with 894 additions and 578 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import styled from 'styled-components';

export const StyledExecutorIcon = styled.div<{$noWidth: boolean}>`
width: ${({$noWidth}) => ($noWidth ? 'unset' : '28px')};
height: ${({$noWidth}) => ($noWidth ? 'unset' : '28px')};
export const StyledExecutorIcon = styled.div<{$size: 'large' | 'small'}>`
width: ${({$size}) => ($size === 'large' ? '28px' : '16px')};
height: ${({$size}) => ($size === 'large' ? '28px' : '16px')};
svg {
width: 100%;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import {ReactComponent as TracetestIcon} from '@assets/tracetestIcon.svg';
import {StyledExecutorIcon} from './ExecutorIcon.styled';

type ExecutorIconProps = {
size?: 'large' | 'small';
type?: string;
noWidth?: boolean;
};

export const executorIcons: Record<string, JSX.Element> = {
Expand All @@ -39,15 +39,15 @@ export const executorIcons: Record<string, JSX.Element> = {
};

const ExecutorIcon: React.FC<ExecutorIconProps> = props => {
const {type, noWidth = false} = props;
const {size = 'large', type} = props;

const icon = type ? executorIcons[type] : <DefaultIcon />;

if (!icon) {
return <DefaultIcon />;
}
return (
<StyledExecutorIcon $noWidth={noWidth} className="dashboard-test-runner">
<StyledExecutorIcon $size={size} className="dashboard-test-runner">
{icon || <DefaultIcon />}
</StyledExecutorIcon>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@ import styled from 'styled-components';

import Colors from '@styles/Colors';

export const StyledLabelListItem = styled.li<{isSkippedMode: boolean}>`
export const StyledLabelListItem = styled.li<{$type: 'primary' | 'secondary'}>`
display: flex;
align-items: center;
padding: 0 5px;
border: 1px solid ${Colors.slate700};
border: ${({$type}) => ($type === 'primary' ? `1px solid ${Colors.slate700}` : 'none')};
border-radius: 4px;
background: transparent;
background-color: ${({$type}) => ($type === 'primary' ? 'transparent' : Colors.slate800)};
font-size: 12px;
font-weight: 400;
text-wrap: nowrap;
max-width: 50vw;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ type LabelListItemProps = {
labelValue?: EntityValue;
isSkippedMode?: boolean;
skippedLabelsNumber?: number;
type?: 'primary' | 'secondary';
};

const LabelListItem: React.FC<LabelListItemProps> = props => {
const {labelKey = '', labelValue = '', isSkippedMode = false, skippedLabelsNumber = 0} = props;
const {labelKey = '', labelValue = '', isSkippedMode = false, skippedLabelsNumber = 0, type = 'primary'} = props;

const value = isSkippedMode ? `+${skippedLabelsNumber} more` : labelValue ? `${labelKey}: ${labelValue}` : labelKey;

return (
<StyledLabelListItem isSkippedMode={isSkippedMode}>
<SplitLabelText value={value} />
<StyledLabelListItem $type={type}>
<SplitLabelText type={type} value={value} />
</StyledLabelListItem>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ type SplitLabelProps = {
value: string;
textClassName?: string;
disabled?: boolean;
type?: 'primary' | 'secondary';
};

const SplitLabelText: React.FC<SplitLabelProps> = props => {
const {value, textClassName = 'regular', disabled = false} = props;
const {value, textClassName = 'regular', disabled = false, type = 'primary'} = props;

if (!labelRegex.test(value)) {
return (
Expand All @@ -32,7 +33,11 @@ const SplitLabelText: React.FC<SplitLabelProps> = props => {
<Text color={disabled ? Colors.slate500 : Colors.slate400} className={textClassName}>
{key}:{' '}
</Text>
<Text color={disabled ? Colors.slate500 : Colors.slate200} className={textClassName} ellipsis>
<Text
color={disabled ? Colors.slate500 : type === 'secondary' ? Colors.slate400 : Colors.slate200}
className={textClassName}
ellipsis
>
{rest.join(':')}
</Text>
</SplitLabelTextContainer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import styled from 'styled-components';

export const StyledStatusIcon = styled.div`
export const StyledStatusIcon = styled.div<{$size: 'small' | 'large'}>`
display: flex;
justify-content: center;
align-items: center;
height: 28px;
width: 28px;
height: ${({$size}) => ($size === 'large' ? '28px' : '20px')};
width: ${({$size}) => ($size === 'large' ? '28px' : '20px')};
border: 1px solid;
border-radius: 4px;
span {
width: 20px;
height: 20px;
width: ${({$size}) => ($size === 'large' ? '20px' : '12px')};
height: ${({$size}) => ($size === 'large' ? '20px' : '12px')};
}
`;
5 changes: 3 additions & 2 deletions packages/web/src/components/atoms/StatusIcon/StatusIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,14 @@ const iconStyles: Record<string, IconStyle> = {

type StatusIconProps = {
status: IconProps['name'];
size?: 'small' | 'large';
};

const StatusIcon: React.FC<StatusIconProps> = props => {
const {status} = props;
const {status, size = 'large'} = props;

return (
<StyledStatusIcon style={iconStyles[status]}>
<StyledStatusIcon $size={size} style={iconStyles[status]}>
<Icon name={status} />
</StyledStatusIcon>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ interface DotsDropdownProps {
trigger?: ('click' | 'hover' | 'contextMenu')[];
overlayClassName?: string;
disabled?: boolean;
open?: boolean;
onOpenChange?: (open: boolean) => void;
}

const DotsDropdown: React.FC<DotsDropdownProps> = ({
Expand All @@ -34,6 +36,8 @@ const DotsDropdown: React.FC<DotsDropdownProps> = ({
trigger = ['click'],
overlayClassName = 'light-dropdown',
disabled,
open,
onOpenChange,
}) => {
return (
<Dropdown
Expand All @@ -44,6 +48,8 @@ const DotsDropdown: React.FC<DotsDropdownProps> = ({
}}
placement={placement}
disabled={disabled}
open={open}
onOpenChange={onOpenChange}
>
<DotsWrapper style={wrapperStyle} onClick={event => event.stopPropagation()}>
<Dots color={Colors.grey450} withPadding={withPadding} disabled={disabled} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function EntityGridBase<T extends {item: any}>(props: EntityGridProps<T>): React
const itemProps = {...componentProps, item} as T;
return <Component {...itemProps} key={itemKey ? getIn(item, itemKey) : `item-${index}`} />;
}),
[data]
[Component, componentProps, data, itemKey]
);

if (loadingInitially) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import React, {FC, forwardRef, memo, useCallback} from 'react';
import {FC, forwardRef, memo, useCallback} from 'react';

import {ExecutorIcon, StatusIcon, Tag} from '@atoms';

import {Text} from '@custom-antd';

import useExecutorIcon from '@hooks/useExecutorIcon';

import {ActionsDropdownProps} from '@models/actionsDropdown';
import type {Execution} from '@models/execution';
import type {ExecutionMetrics} from '@models/metrics';
import type {TestSuiteExecution} from '@models/testSuiteExecution';

import {DotsDropdown, LabelsList, MetricsBarChart} from '@molecules';
import {LabelsList, MetricsBarChart} from '@molecules';

import Colors from '@styles/Colors';

Expand All @@ -31,6 +32,7 @@ import EntityGridItemExecutionTime from './EntityGridItemExecutionTime';
export interface Item {
type?: string;
name: string;
namespace?: string;
labels?: Record<string, string>;
}

Expand All @@ -46,42 +48,41 @@ interface EntityGridItemPureProps {
latestExecution?: TestSuiteExecution | Execution;
metrics?: Metrics;
onClick: (item: Item) => void;
onAbort: (item: Item) => void;
dataTest: string;
outOfSync?: boolean;
isAgentAvailable?: boolean;
entityLabel: string;
DropdownComponent: React.FC<ActionsDropdownProps>;
}

const EntityGridItemTestIcon: FC<{item: Item}> = memo(({item}) => {
const icon = useExecutorIcon(item);
return item.type ? <ExecutorIcon type={icon} /> : null;
});

const isRunningStatus = (status: string) => ['running', 'queued'].includes(status);

const EntityGridItemPure = forwardRef<HTMLDivElement, EntityGridItemPureProps>((props, ref) => {
const {item, latestExecution, onClick, onAbort, dataTest, metrics, outOfSync, isAgentAvailable, entityLabel} = props;
const {
item,
latestExecution,
onClick,
dataTest,
metrics,
outOfSync,
isAgentAvailable,
entityLabel,
DropdownComponent,
} = props;

const status =
(latestExecution as Execution)?.executionResult?.status ||
(latestExecution as TestSuiteExecution)?.status ||
'pending';
const executions = metrics?.executions;
const isRunning = isRunningStatus(status) || executions?.some(execution => isRunningStatus(execution.status));

const click = useCallback(() => {
onClick(item);
}, [onClick, item]);

const abort = useCallback(
(event: React.MouseEvent<HTMLSpanElement>) => {
event.stopPropagation();
onAbort(item);
},
[onAbort, item]
);

return (
<ItemWrapper onClick={click} ref={ref} data-test={dataTest}>
<DetailsWrapper>
Expand All @@ -108,13 +109,7 @@ const EntityGridItemPure = forwardRef<HTMLDivElement, EntityGridItemPureProps>((
</ItemColumn>
<ExecutionTimeItemColumn>
<EntityGridItemExecutionTime time={latestExecution?.startTime} />
{isRunning ? (
<DotsDropdown
placement="bottomRight"
disabled={outOfSync}
items={[{key: 1, label: <span onClick={abort}>Abort all executions</span>}]}
/>
) : null}
<DropdownComponent name={item.name} namespace={item.namespace} outOfSync={outOfSync} type={item.type} />
</ExecutionTimeItemColumn>
</ItemRow>
<RowsWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const AppliedFiltersNotification = styled.div`
background-color: ${Colors.purple};
`;

export const StyledFilterLabel = styled.div<{isFiltersDisabled: boolean}>`
export const StyledFilterLabel = styled.div<{$disabled: boolean}>`
position: relative;
display: flex;
justify-content: space-between;
Expand All @@ -71,14 +71,14 @@ export const StyledFilterLabel = styled.div<{isFiltersDisabled: boolean}>`
border-radius: 4px;
padding: 11px;
background-color: ${props => (props.isFiltersDisabled ? Colors.slate800disabled : Colors.slate800)};
background-color: ${props => (props.$disabled ? Colors.slate800disabled : Colors.slate800)};
color: ${Colors.slate500};
cursor: ${props => (props.isFiltersDisabled ? 'not-allowed' : 'pointer')};
cursor: ${props => (props.$disabled ? 'not-allowed' : 'pointer')};
transition: 0.3s ease;
${props =>
props.isFiltersDisabled
props.$disabled
? ''
: `
&:hover {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ type LabelsListProps = {
howManyLabelsToShow?: number;
shouldSkipLabels?: boolean;
className?: string;
type?: 'primary' | 'secondary';
};

const LabelsList: React.FC<LabelsListProps> = props => {
const {labels, howManyLabelsToShow = 3, shouldSkipLabels = false, className = ''} = props;
const {labels, howManyLabelsToShow = 3, shouldSkipLabels = false, className = '', type = 'primary'} = props;

const labelKeys: EntityKey[] = Object.keys(labels);

Expand All @@ -28,7 +29,7 @@ const LabelsList: React.FC<LabelsListProps> = props => {
}
}

return <LabelListItem key={labelKey} labelKey={labelKey} labelValue={labels[labelKey]} />;
return <LabelListItem key={labelKey} labelKey={labelKey} labelValue={labels[labelKey]} type={type} />;
})
.filter(labelComponent => labelComponent);

Expand All @@ -37,7 +38,7 @@ const LabelsList: React.FC<LabelsListProps> = props => {

const renderedSkippedLabels = skippedLabelsArray
? skippedLabelsArray.map(([labelKey]) => {
return <LabelListItem key={labelKey} labelKey={labelKey} labelValue={labels[labelKey]} />;
return <LabelListItem key={labelKey} labelKey={labelKey} labelValue={labels[labelKey]} type={type} />;
})
: null;

Expand All @@ -56,6 +57,7 @@ const LabelsList: React.FC<LabelsListProps> = props => {
key="skipped-labels-number"
isSkippedMode={shouldSkipLabels}
skippedLabelsNumber={skippedLabelsNumber}
type={type}
/>
</div>
</Popover>
Expand Down
Loading

0 comments on commit df55203

Please sign in to comment.