Ux fixes (#2913)
* Fixed links to ChaosHub, added textButton component Signed-off-by: Vansh Bhatia <vansh@chaosnative.com> * Added workflow status Icons to homePage Signed-off-by: Vansh Bhatia <vansh@chaosnative.com> * moved from links to TextButton in homePage Signed-off-by: Vansh Bhatia <vansh@chaosnative.com> * removed unused redux Tab state, added pagination bugFix Signed-off-by: Vansh Bhatia <vansh@chaosnative.com> * Review changes Signed-off-by: Vansh Bhatia <vansh@chaosnative.com> * Loader UX issue fixed Signed-off-by: Vansh Bhatia <vansh@chaosnative.com>
This commit is contained in:
parent
91ae3a3134
commit
08204190ff
|
@ -1,6 +1,6 @@
|
|||
import { useQuery } from '@apollo/client';
|
||||
import { Avatar, IconButton, Popover, Typography } from '@material-ui/core';
|
||||
import { ButtonFilled, ButtonOutlined } from 'litmus-ui';
|
||||
import { ButtonFilled, TextButton } from 'litmus-ui';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
@ -121,8 +121,9 @@ const ProfileDropdown: React.FC = () => {
|
|||
</ButtonFilled>
|
||||
</div>
|
||||
|
||||
<ButtonOutlined
|
||||
<TextButton
|
||||
title="Edit your profile"
|
||||
variant="highlight"
|
||||
disabled={projectRole !== 'Owner'}
|
||||
onClick={() => {
|
||||
tabs.changeSettingsTabs(0);
|
||||
|
@ -133,7 +134,7 @@ const ProfileDropdown: React.FC = () => {
|
|||
}}
|
||||
>
|
||||
{t('header.profileDropdown.editProfile')}
|
||||
</ButtonOutlined>
|
||||
</TextButton>
|
||||
</div>
|
||||
</div>
|
||||
</Popover>
|
||||
|
|
|
@ -22,7 +22,7 @@ const Loader: React.FC<LoaderProps> = ({ size, message }) => {
|
|||
const classes = useStyles();
|
||||
const defaultSize = 40;
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<Center>
|
||||
<CircularProgress
|
||||
className={classes.spinner}
|
||||
|
@ -30,7 +30,7 @@ const Loader: React.FC<LoaderProps> = ({ size, message }) => {
|
|||
/>
|
||||
</Center>
|
||||
<Typography>{message}</Typography>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -40,16 +40,13 @@ const useStyles = makeStyles((theme) => ({
|
|||
marginRight: theme.spacing(1.5),
|
||||
},
|
||||
|
||||
'& a': {
|
||||
textDecoration: 'none',
|
||||
marginLeft: theme.spacing(1.875),
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
'& p': {
|
||||
fontWeight: 500,
|
||||
fontSize: '1rem',
|
||||
},
|
||||
|
||||
'& button:last-child': {
|
||||
marginLeft: theme.spacing(2.5),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
|
|
@ -8,12 +8,6 @@ const useStyles = makeStyles((theme) => ({
|
|||
containerHeading: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
|
||||
'& a': {
|
||||
textDecoration: 'none',
|
||||
color: theme.palette.primary.main,
|
||||
marginRight: theme.spacing(4.5),
|
||||
},
|
||||
},
|
||||
heading: {
|
||||
flexGrow: 1,
|
||||
|
|
|
@ -15,6 +15,7 @@ import * as AnalyticsActions from '../../redux/actions/analytics';
|
|||
import { history } from '../../redux/configureStore';
|
||||
import { getToken, getUserId, getUserRole } from '../../utils/auth';
|
||||
import { getProjectID, getProjectRole } from '../../utils/getSearchParams';
|
||||
import Center from '../layouts/Center';
|
||||
|
||||
const ErrorPage = lazy(() => import('../../pages/ErrorPage'));
|
||||
const Workflows = lazy(() => import('../../pages/Workflows'));
|
||||
|
@ -257,7 +258,9 @@ function App() {
|
|||
<Suspense
|
||||
fallback={
|
||||
<div style={{ height: '100vh' }}>
|
||||
<Center>
|
||||
<Loader />
|
||||
</Center>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
|
|
|
@ -3,7 +3,6 @@ export interface TabState {
|
|||
settings: number;
|
||||
node: number;
|
||||
analytics: number;
|
||||
overviewDashboard: number;
|
||||
}
|
||||
|
||||
export enum TabActions {
|
||||
|
@ -11,7 +10,6 @@ export enum TabActions {
|
|||
CHANGE_SETTINGS_TAB = 'CHANGE_SETTINGS_TAB',
|
||||
CHANGE_WORKFLOW_DETAILS_TAB = 'CHANGE_WORKFLOW_DETAILS_TAB',
|
||||
CHANGE_ANALYTICS_DASHBOARD_TAB = 'CHANGE_ANALYTICS_DASHBOARD_TAB',
|
||||
CHANGE_OVERVIEW_DASHBOARD_TAB = 'CHANGE_OVERVIEW_DASHBOARD_TAB',
|
||||
}
|
||||
|
||||
interface TabActionType<T, P> {
|
||||
|
@ -23,5 +21,4 @@ export type TabAction =
|
|||
| TabActionType<typeof TabActions.CHANGE_WORKFLOWS_TAB, number>
|
||||
| TabActionType<typeof TabActions.CHANGE_SETTINGS_TAB, number>
|
||||
| TabActionType<typeof TabActions.CHANGE_WORKFLOW_DETAILS_TAB, number>
|
||||
| TabActionType<typeof TabActions.CHANGE_ANALYTICS_DASHBOARD_TAB, number>
|
||||
| TabActionType<typeof TabActions.CHANGE_OVERVIEW_DASHBOARD_TAB, number>;
|
||||
| TabActionType<typeof TabActions.CHANGE_ANALYTICS_DASHBOARD_TAB, number>;
|
||||
|
|
|
@ -27,10 +27,3 @@ export function changeAnalyticsDashboardTabs(tabNumber: number): TabAction {
|
|||
payload: tabNumber,
|
||||
};
|
||||
}
|
||||
|
||||
export function changeOverviewDashboardTabs(tabNumber: number): TabAction {
|
||||
return {
|
||||
type: TabActions.CHANGE_OVERVIEW_DASHBOARD_TAB,
|
||||
payload: tabNumber,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ const initialState: TabState = {
|
|||
settings: 0,
|
||||
node: 0,
|
||||
analytics: 0,
|
||||
overviewDashboard: 0,
|
||||
};
|
||||
|
||||
export const tabNumber = createReducer<TabState>(initialState, {
|
||||
|
@ -38,15 +37,6 @@ export const tabNumber = createReducer<TabState>(initialState, {
|
|||
analytics: action.payload,
|
||||
};
|
||||
},
|
||||
[TabActions.CHANGE_OVERVIEW_DASHBOARD_TAB](
|
||||
state: TabState,
|
||||
action: TabAction
|
||||
) {
|
||||
return {
|
||||
...state,
|
||||
overviewDashboard: action.payload,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default tabNumber;
|
||||
|
|
|
@ -8,6 +8,13 @@ import {
|
|||
getProjectID,
|
||||
getProjectRole,
|
||||
} from '../../../../utils/getSearchParams';
|
||||
import {
|
||||
FAILED,
|
||||
NOTAVAILABLE,
|
||||
PENDING,
|
||||
RUNNING,
|
||||
SUCCEEDED,
|
||||
} from '../../../WorkflowDetails/workflowConstants';
|
||||
import useStyles from './styles';
|
||||
|
||||
interface WorkflowDashboardCardProps {
|
||||
|
@ -24,15 +31,15 @@ const WorkflowDashboardCard: React.FC<WorkflowDashboardCardProps> = ({
|
|||
|
||||
function getStatusVariant(phase: string) {
|
||||
switch (phase) {
|
||||
case 'Running':
|
||||
case RUNNING:
|
||||
return 'status-running.svg';
|
||||
case 'Succeeded':
|
||||
case SUCCEEDED:
|
||||
return 'status-success.svg';
|
||||
case 'Failed':
|
||||
case FAILED:
|
||||
return 'status-failed.svg';
|
||||
case 'Pending':
|
||||
case PENDING:
|
||||
return 'status-pending.svg';
|
||||
case 'NotAvailabe':
|
||||
case NOTAVAILABLE:
|
||||
return 'status-NotAvailable.svg';
|
||||
default:
|
||||
return '';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useQuery } from '@apollo/client';
|
||||
import { Link, Typography } from '@material-ui/core';
|
||||
import { ButtonFilled, ButtonOutlined } from 'litmus-ui';
|
||||
import { ButtonFilled, ButtonOutlined, TextButton } from 'litmus-ui';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Loader from '../../../components/Loader';
|
||||
|
@ -28,8 +28,6 @@ import {
|
|||
Workflow,
|
||||
WorkflowDataVars,
|
||||
} from '../../../models/graphql/workflowData';
|
||||
import useActions from '../../../redux/actions';
|
||||
import * as TabActions from '../../../redux/actions/tabs';
|
||||
import { history } from '../../../redux/configureStore';
|
||||
import { getProjectID, getProjectRole } from '../../../utils/getSearchParams';
|
||||
import { ApplicationDashboardCard } from './ApplicationDashboardCard';
|
||||
|
@ -42,8 +40,6 @@ const Overview: React.FC = () => {
|
|||
const projectRole = getProjectRole();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const tabs = useActions(TabActions);
|
||||
|
||||
let dataSource = false;
|
||||
let workflowDashboardCount = 0;
|
||||
let applicationDashboardCount = 0;
|
||||
|
@ -155,13 +151,11 @@ const Overview: React.FC = () => {
|
|||
</ButtonFilled>
|
||||
}
|
||||
link={
|
||||
<Link
|
||||
underline="none"
|
||||
color="primary"
|
||||
<TextButton
|
||||
variant="highlight"
|
||||
onClick={() => {
|
||||
tabs.changeWorkflowsTabs(2);
|
||||
history.push({
|
||||
pathname: '/workflows',
|
||||
pathname: '/myhub/Chaos%20Hub',
|
||||
search: `?projectID=${projectID}&projectRole=${projectRole}`,
|
||||
});
|
||||
}}
|
||||
|
@ -169,7 +163,7 @@ const Overview: React.FC = () => {
|
|||
<Typography>
|
||||
{t('homeViews.agentConfiguredHome.noWorkflow.explore')}
|
||||
</Typography>
|
||||
</Link>
|
||||
</TextButton>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
@ -227,12 +221,18 @@ const Overview: React.FC = () => {
|
|||
link={
|
||||
<Link
|
||||
underline="none"
|
||||
color="primary"
|
||||
href="https://prometheus.io/docs/introduction/overview/"
|
||||
href="https://github.com/litmuschaos/litmus/tree/master/monitoring#model-1-optional-prometheus-scrape-config-model"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Typography>Read prometheus doc</Typography>
|
||||
<TextButton variant="highlight" className={classes.docsButton}>
|
||||
<Typography>Sample Prometheus configuration</Typography>
|
||||
<img
|
||||
src="./icons/externalLink.svg"
|
||||
alt="external link"
|
||||
title="Read documentation"
|
||||
/>
|
||||
</TextButton>
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -4,6 +4,12 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
linkPointer: {
|
||||
cursor: 'pointer',
|
||||
},
|
||||
docsButton: {
|
||||
'& img': {
|
||||
padding: 0,
|
||||
margin: theme.spacing(0, 0, 0, 1),
|
||||
},
|
||||
},
|
||||
infoContainerButton: {
|
||||
'& img': {
|
||||
margin: theme.spacing(0, 1, -0.5, 0),
|
||||
|
|
|
@ -366,7 +366,7 @@ const BrowseSchedule: React.FC = () => {
|
|||
<TablePagination
|
||||
rowsPerPageOptions={[10, 25, 50]}
|
||||
component="div"
|
||||
count={filteredWorkflows?.length ?? 0}
|
||||
count={data?.ListWorkflow.totalNoOfWorkflows ?? 0}
|
||||
rowsPerPage={paginationData.limit}
|
||||
page={paginationData.page}
|
||||
onChangePage={(_, page) =>
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from '../../../../utils/getSearchParams';
|
||||
import {
|
||||
FAILED,
|
||||
NOTAVAILABLE,
|
||||
PENDING,
|
||||
RUNNING,
|
||||
SUCCEEDED,
|
||||
|
@ -31,18 +32,20 @@ const WorkflowRunCard: React.FC<WorkflowRunCardProps> = ({ data }) => {
|
|||
|
||||
const nodeSelection = useActions(NodeSelectionActions);
|
||||
|
||||
function getPhaseVariant(variant: string | undefined): string {
|
||||
switch (variant) {
|
||||
function getStatusVariant(phase: string | undefined): string {
|
||||
switch (phase) {
|
||||
case SUCCEEDED:
|
||||
return classes.succeeded;
|
||||
return 'status-success.svg';
|
||||
case RUNNING:
|
||||
return classes.running;
|
||||
return 'status-running.svg';
|
||||
case FAILED:
|
||||
return classes.failed;
|
||||
return 'status-failed.svg';
|
||||
case PENDING:
|
||||
return classes.pending;
|
||||
return 'status-pending.svg';
|
||||
case NOTAVAILABLE:
|
||||
return 'status-NotAvailable.svg';
|
||||
default:
|
||||
return classes.pending;
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,9 +80,11 @@ const WorkflowRunCard: React.FC<WorkflowRunCardProps> = ({ data }) => {
|
|||
<div className={classes.workflowDataContainer}>
|
||||
<div>
|
||||
<div className={classes.statusDiv}>
|
||||
<svg viewBox="0 0 10 10">
|
||||
<circle className={getPhaseVariant(data.phase)} />
|
||||
</svg>
|
||||
<img
|
||||
src={`./icons/${getStatusVariant(data.phase)}`}
|
||||
alt={data.phase}
|
||||
title={data.phase}
|
||||
/>
|
||||
<div>
|
||||
<Typography
|
||||
className={`${classes.testName} ${classes.noWrapProvider}`}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { makeStyles } from '@material-ui/core';
|
|||
const useStyles = makeStyles((theme) => ({
|
||||
animatedContainer: {
|
||||
marginTop: theme.spacing(3.125),
|
||||
padding: theme.spacing(2.5, 0),
|
||||
padding: theme.spacing(2.5),
|
||||
willChange: `transform`,
|
||||
transition: `transform 250ms`,
|
||||
cursor: 'pointer',
|
||||
|
@ -19,19 +19,14 @@ const useStyles = makeStyles((theme) => ({
|
|||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
width: '75%',
|
||||
|
||||
'& svg': {
|
||||
width: '3.75rem',
|
||||
},
|
||||
|
||||
'& circle': {
|
||||
r: '1',
|
||||
cx: '5',
|
||||
cy: '5',
|
||||
},
|
||||
},
|
||||
statusDiv: {
|
||||
display: 'flex',
|
||||
|
||||
'& img': {
|
||||
width: '2.5rem',
|
||||
marginRight: theme.spacing(2),
|
||||
},
|
||||
},
|
||||
|
||||
testName: {
|
||||
|
@ -50,36 +45,9 @@ const useStyles = makeStyles((theme) => ({
|
|||
lastRunTime: {
|
||||
width: '4.8125rem',
|
||||
},
|
||||
listContainer: {
|
||||
'& img': {
|
||||
width: '1rem',
|
||||
marginLeft: theme.spacing(2.25),
|
||||
},
|
||||
'& span': {
|
||||
marginRight: theme.spacing(1.25),
|
||||
},
|
||||
},
|
||||
listItem: {
|
||||
'&:hover': {
|
||||
background: theme.palette.cards.highlight,
|
||||
},
|
||||
},
|
||||
noWrapProvider: {
|
||||
whiteSpace: 'nowrap',
|
||||
},
|
||||
// Phase states indicating the present run status
|
||||
succeeded: {
|
||||
fill: theme.palette.success.main,
|
||||
},
|
||||
running: {
|
||||
fill: theme.palette.primary.main,
|
||||
},
|
||||
failed: {
|
||||
fill: theme.palette.error.main,
|
||||
},
|
||||
pending: {
|
||||
fill: theme.palette.primary.main,
|
||||
},
|
||||
// Resiliency Score indicators
|
||||
lowScore: {
|
||||
color: theme.palette.error.main,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { useQuery } from '@apollo/client';
|
||||
import { Link, Typography } from '@material-ui/core';
|
||||
import { Typography } from '@material-ui/core';
|
||||
import ArrowUpwardIcon from '@material-ui/icons/ArrowUpward';
|
||||
import { ButtonFilled, ButtonOutlined, Modal } from 'litmus-ui';
|
||||
import { ButtonFilled, ButtonOutlined, Modal, TextButton } from 'litmus-ui';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AgentDeployModal } from '../../../components/AgentDeployModal';
|
||||
|
@ -86,9 +86,9 @@ const AgentConfiguredHome: React.FC<AgentConfiguredHomeProps> = ({
|
|||
'homeViews.agentConfiguredHome.recentWorkflowRuns.heading'
|
||||
)}
|
||||
link={
|
||||
<Link
|
||||
underline="none"
|
||||
color="primary"
|
||||
<TextButton
|
||||
className={classes.textButton}
|
||||
variant="highlight"
|
||||
onClick={() => {
|
||||
tabs.changeWorkflowsTabs(0);
|
||||
history.push({
|
||||
|
@ -97,10 +97,10 @@ const AgentConfiguredHome: React.FC<AgentConfiguredHomeProps> = ({
|
|||
});
|
||||
}}
|
||||
>
|
||||
<Typography className={classes.linkPointer}>
|
||||
<Typography>
|
||||
{t('homeViews.agentConfiguredHome.recentWorkflowRuns.viewAll')}
|
||||
</Typography>
|
||||
</Link>
|
||||
</TextButton>
|
||||
}
|
||||
buttonLink="/create-workflow"
|
||||
buttonImgSrc="./icons/calendarBlank.svg"
|
||||
|
@ -138,13 +138,11 @@ const AgentConfiguredHome: React.FC<AgentConfiguredHomeProps> = ({
|
|||
</ButtonFilled>
|
||||
}
|
||||
link={
|
||||
<Link
|
||||
underline="none"
|
||||
color="primary"
|
||||
<TextButton
|
||||
variant="highlight"
|
||||
onClick={() => {
|
||||
tabs.changeWorkflowsTabs(2);
|
||||
history.push({
|
||||
pathname: '/workflows',
|
||||
pathname: '/myhub/Chaos%20Hub',
|
||||
search: `?projectID=${projectID}&projectRole=${projectRole}`,
|
||||
});
|
||||
}}
|
||||
|
@ -152,7 +150,7 @@ const AgentConfiguredHome: React.FC<AgentConfiguredHomeProps> = ({
|
|||
<Typography>
|
||||
{t('homeViews.agentConfiguredHome.noWorkflow.explore')}
|
||||
</Typography>
|
||||
</Link>
|
||||
</TextButton>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { makeStyles } from '@material-ui/core';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
linkPointer: {
|
||||
cursor: 'pointer',
|
||||
textButton: {
|
||||
marginRight: theme.spacing(4.5),
|
||||
},
|
||||
infoContainerButton: {
|
||||
'& svg': {
|
||||
|
|
|
@ -2,6 +2,7 @@ export const FAILED: string = 'Failed';
|
|||
export const RUNNING: string = 'Running';
|
||||
export const PENDING: string = 'Pending';
|
||||
export const SUCCEEDED: string = 'Succeeded';
|
||||
export const NOTAVAILABLE: string = 'NotAvailable';
|
||||
export const OMITTED: string = 'Omitted';
|
||||
export const SKIPPED: string = 'Skipped';
|
||||
export const ERROR: string = 'Error';
|
||||
|
|
Loading…
Reference in New Issue