Skip to content

Commit

Permalink
Refine home page and sign-in page (microsoft#4084)
Browse files Browse the repository at this point in the history
  • Loading branch information
debuggy authored Jan 3, 2020
1 parent 513d010 commit 864236d
Show file tree
Hide file tree
Showing 11 changed files with 458 additions and 216 deletions.
101 changes: 81 additions & 20 deletions src/webportal/src/app/home/home.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@

import c from 'classnames';
import { isEmpty } from 'lodash';
import { Stack, StackItem } from 'office-ui-fabric-react';
import { Stack, StackItem, Pivot, PivotItem } from 'office-ui-fabric-react';
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import MediaQuery from 'react-responsive';

import Card from '../components/card';
import JobStatus from './home/job-status';
import { VirtualClusterStatistics } from './home/virtual-cluster-statistics';
import GpuChart from './home/gpu-chart';
Expand All @@ -40,12 +41,14 @@ import AbnormalJobList from './home/abnormal-job-list';
import { BREAKPOINT1 } from './home/util';
import { SpinnerLoading } from '../components/loading';
import { clearToken } from '../user/user-logout/user-logout.component.js';
import { TooltipIcon } from '../job-submission/components/controls/tooltip-icon';

import t from '../components/tachyons.scss';

const Home = () => {
const [loading, setLoading] = useState(true);
const [jobs, setJobs] = useState(null);
const [userJobs, setUserJobs] = useState(null);
const [userInfo, setUserInfo] = useState(null);
const [virtualClusters, setVirtualClusters] = useState(null);
const [gpuPerNode, setGpuPerNode] = useState(null);
Expand All @@ -61,6 +64,7 @@ const Home = () => {
}
Promise.all([
isAdmin ? listAllJobs().then(setJobs) : listJobs().then(setJobs),
listJobs().then(setUserJobs),
getUserInfo().then(setUserInfo),
listVirtualClusters().then(setVirtualClusters),
getAvailableGpuPerNode().then(setGpuPerNode),
Expand Down Expand Up @@ -91,7 +95,7 @@ const Home = () => {
>
{/* small */}
<MediaQuery maxWidth={BREAKPOINT1}>
<Stack padding='l2' gap='l2' styles={{ minHeight: '100%' }}>
<Stack padding='l2' gap='l1' styles={{ minHeight: '100%' }}>
<JobStatus style={{ height: 320 }} jobs={jobs} />
<React.Fragment>
<VirtualClusterStatistics
Expand All @@ -106,32 +110,62 @@ const Home = () => {
virtualClusters={virtualClusters}
/>
</React.Fragment>
{isAdmin ? (
<AbnormalJobList jobs={listAbnormalJobs(jobs, lowGpuJobInfo)} />
) : (
<RecentJobList jobs={jobs} />
)}
<Card className={c(t.h100, t.ph5)}>
{isAdmin ? (
<Pivot>
<PivotItem
headerText='Abnormal jobs'
onRenderItemLink={(link, defaultRenderer) => {
return (
<Stack horizontal gap='s1'>
{defaultRenderer(link)}
<TooltipIcon
content={
'A job is treaded as an abnormal job if running more than 5 days or GPU usage is lower than 10%'
}
/>
</Stack>
);
}}
>
<AbnormalJobList
style={{ minHeight: 0 }}
jobs={listAbnormalJobs(jobs, lowGpuJobInfo)}
/>
</PivotItem>
<PivotItem headerText='My recent jobs'>
<RecentJobList style={{ minHeight: 0 }} jobs={userJobs} />
</PivotItem>
</Pivot>
) : (
<Pivot>
<PivotItem headerText='My recent jobs'>
<RecentJobList style={{ minHeight: 0 }} jobs={userJobs} />
</PivotItem>
</Pivot>
)}
</Card>
</Stack>
</MediaQuery>
{/* large */}
<MediaQuery minWidth={BREAKPOINT1 + 1}>
<Stack
padding='l2'
gap='l2'
gap='l1'
styles={{ root: { height: '100%', minHeight: 640 } }}
>
{/* top */}
<StackItem disableShrink>
<Stack gap='l2' horizontal>
<Stack gap='l1' horizontal>
<React.Fragment>
<JobStatus style={{ width: '25%' }} jobs={jobs} />
<JobStatus style={{ width: '33%' }} jobs={jobs} />
<VirtualClusterStatistics
style={{ width: '41%' }}
style={{ width: '33%' }}
userInfo={userInfo}
virtualClusters={virtualClusters}
/>
<GpuChart
style={{ width: '33%' }}
style={{ width: '34%' }}
gpuPerNode={gpuPerNode}
userInfo={userInfo}
virtualClusters={virtualClusters}
Expand All @@ -140,14 +174,41 @@ const Home = () => {
</Stack>
</StackItem>
{/* bottom */}
{isAdmin ? (
<AbnormalJobList
style={{ minHeight: 0 }}
jobs={listAbnormalJobs(jobs, lowGpuJobInfo)}
/>
) : (
<RecentJobList style={{ minHeight: 0 }} jobs={jobs} />
)}
<Card className={c(t.h100, t.ph5)}>
{isAdmin ? (
<Pivot>
<PivotItem
headerText='Abnormal jobs'
onRenderItemLink={(link, defaultRenderer) => {
return (
<Stack horizontal gap='s1'>
{defaultRenderer(link)}
<TooltipIcon
content={
'A job is treaded as an abnormal job if running more than 5 days or GPU usage is lower than 10%'
}
/>
</Stack>
);
}}
>
<AbnormalJobList
style={{ minHeight: 0 }}
jobs={listAbnormalJobs(jobs, lowGpuJobInfo)}
/>
</PivotItem>
<PivotItem headerText='My recent jobs'>
<RecentJobList style={{ minHeight: 0 }} jobs={userJobs} />
</PivotItem>
</Pivot>
) : (
<Pivot>
<PivotItem headerText='My recent jobs'>
<RecentJobList style={{ minHeight: 0 }} jobs={userJobs} />
</PivotItem>
</Pivot>
)}
</Card>
</Stack>
</MediaQuery>
</div>
Expand Down
46 changes: 11 additions & 35 deletions src/webportal/src/app/home/home/abnormal-job-list.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import c from 'classnames';
import {
Link,
Stack,
FontClassNames,
DetailsList,
DetailsListLayoutMode,
Expand All @@ -29,7 +28,6 @@ import {
import PropTypes from 'prop-types';
import React, { useCallback, useState } from 'react';

import Card from '../../components/card';
import {
getJobDuration,
getDurationString,
Expand All @@ -40,15 +38,11 @@ import {
isStoppable,
} from '../../components/util/job';
import { zeroPaddingClass } from './util';
import { Header } from './header';
import userAuth from '../../user/user-auth/user-auth.component';
import { stopJob } from './conn';
import { cloneDeep } from 'lodash';
import StopJobConfirm from '../../job/job-view/fabric/JobList/StopJobConfirm';

// Move it to common folder
import { TooltipIcon } from '../../job-submission/components/controls/tooltip-icon';

import t from '../../components/tachyons.scss';
import StatusBadge from '../../components/status-badge';

Expand Down Expand Up @@ -78,7 +72,7 @@ const AbnormalJobList = ({ jobs, style }) => {
},
{
key: 'gpuCount',
minWidth: 150,
minWidth: 50,
name: 'GPUs',
fieldName: 'totalGpuNumber',
className: FontClassNames.mediumPlus,
Expand Down Expand Up @@ -205,40 +199,22 @@ const AbnormalJobList = ({ jobs, style }) => {
);

return (
<Card className={c(t.h100, t.ph5)} style={style}>
<Stack gap='l1' styles={{ root: [t.h100] }}>
<Stack.Item>
<Header
headerName='Abnormal jobs'
linkName='All jobs'
linkHref='/job-list.html'
showLink
>
<TooltipIcon
content={
'A job is treaded as an abnormal job if running more than 5 days or GPU usage is lower than 10%'
}
/>
</Header>
</Stack.Item>
<Stack.Item styles={{ root: { overflow: 'auto' } }} grow>
<DetailsList
styles={{ root: { minHeight: 200, overflow: 'unset' } }}
columns={jobListColumns}
disableSelectionZone
items={abnormalJobs}
layoutMode={DetailsListLayoutMode.justified}
selectionMode={SelectionMode.none}
/>
</Stack.Item>
</Stack>
<div className={c(t.mv3, t.ph5, t.h100, t.overflowYAuto)}>
<DetailsList
styles={{ root: { minHeight: 200, overflow: 'unset' } }}
columns={jobListColumns}
disableSelectionZone
items={abnormalJobs}
layoutMode={DetailsListLayoutMode.justified}
selectionMode={SelectionMode.none}
/>
<StopJobConfirm
hideDialog={hideDialog}
currentJob={currentJob}
setHideDialog={setHideDialog}
stopJob={stopAbnormalJob}
/>
</Card>
</div>
);
};

Expand Down
4 changes: 4 additions & 0 deletions src/webportal/src/app/home/home/c3.scss
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
stroke-dasharray: 3 3;
}

.c3-ygrid-lines {
stroke-width: 0.2px;
}

/*-- Text on Chart --*/
.c3-text.c3-empty {
fill: #808080;
Expand Down
13 changes: 13 additions & 0 deletions src/webportal/src/app/home/home/gpu-chart.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ const GpuChart = ({ style, gpuPerNode, virtualClusters, userInfo }) => {
return prev;
}, Array.from({ length: maxGpu + 1 }, () => 0));
stack[1][0] = 'dedicated';
const maxValue = Math.max(...stack[0].slice(1), ...stack[1].slice(1)) - 1;
const ylines = [
{ value: maxValue / 4 },
{ value: (maxValue * 2) / 4 },
{ value: (maxValue * 3) / 4 },
{ value: maxValue },
];

// c3 option
const defaultOption = {
Expand All @@ -105,6 +112,7 @@ const GpuChart = ({ style, gpuPerNode, virtualClusters, userInfo }) => {
labels: {
format: x => (x === 0 ? '' : x),
},
empty: { label: { text: 'No available GPU nodes now' } },
},
padding: {
left: 20,
Expand Down Expand Up @@ -134,6 +142,11 @@ const GpuChart = ({ style, gpuPerNode, virtualClusters, userInfo }) => {
inner: true,
},
},
grid: {
y: {
lines: ylines,
},
},
legend: {
show: false,
},
Expand Down
22 changes: 4 additions & 18 deletions src/webportal/src/app/home/home/job-status.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ import { isEmpty } from 'lodash';
import PropTypes from 'prop-types';
import querystring from 'querystring';
import {
Icon,
Stack,
FontClassNames,
ColorClassNames,
DefaultButton,
getTheme,
FontWeights,
getTheme,
} from 'office-ui-fabric-react';
import React from 'react';
import styled from 'styled-components';

import StatusBadge from '../../components/status-badge';
import Card from '../../components/card';
import { getHumanizedJobStateString } from '../../components/util/job';

Expand All @@ -47,22 +47,8 @@ const StatusRow = ({ cellClassName, icon, name, count, link }) => {
return (
<TableRow>
<td className={cellClassName}>
<div className={c(t.flex, t.itemsCenter, t.justifyStart)}>
<div>
<Icon
className={ColorClassNames.neutralSecondary}
iconName={icon}
/>
</div>
<div
className={c(
ColorClassNames.neutralSecondary,
FontClassNames.mediumPlus,
)}
style={{ marginLeft: spacing.m }}
>
{name}
</div>
<div className={c(t.w4)}>
<StatusBadge status={name} />
</div>
</td>
<td className={cellClassName}>
Expand Down
Loading

0 comments on commit 864236d

Please sign in to comment.