Skip to content

Commit

Permalink
Addition of skeleton components for dashboard views including placeme…
Browse files Browse the repository at this point in the history
…nt graphic for charts
  • Loading branch information
sg00dwin committed Dec 5, 2019
1 parent 3158e47 commit 6beabd7
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 39 deletions.
6 changes: 3 additions & 3 deletions frontend/__tests__/components/graphs/area.spec.tsx
Expand Up @@ -4,7 +4,7 @@ import { Chart, ChartArea, ChartAxis } from '@patternfly/react-charts';

import { AreaChart } from '@console/internal/components/graphs/area';
import { GraphEmpty } from '@console/internal/components/graphs/graph-empty';
import { LoadingBox } from '@console/internal/components/utils';

import {
PrometheusGraph,
PrometheusGraphLink,
Expand Down Expand Up @@ -37,8 +37,8 @@ describe('<AreaChart />', () => {
expect(wrapper.find(GraphEmpty).exists()).toBe(true);
});

it('should show a loading state', () => {
it('should show a loading skeleton state', () => {
const wrapper = mount(<AreaChart data={[]} loading={true} />); // Use full mount function so that we can check for a LoadingBox child
expect(wrapper.find(LoadingBox).exists()).toBe(true);
expect(wrapper.find('.skeleton-chart').exists()).toBe(true);
});
});
6 changes: 3 additions & 3 deletions frontend/__tests__/components/graphs/bar.spec.tsx
Expand Up @@ -4,7 +4,7 @@ import { ChartBar } from '@patternfly/react-charts';

import { BarChart } from '@console/internal/components/graphs/bar';
import { GraphEmpty } from '@console/internal/components/graphs/graph-empty';
import { LoadingBox } from '@console/internal/components/utils';

import {
PrometheusGraph,
PrometheusGraphLink,
Expand All @@ -28,8 +28,8 @@ describe('<BarChart />', () => {
expect(wrapper.find(GraphEmpty).exists()).toBe(true);
});

it('should show a loading state', () => {
it('should show a skeleton loading state', () => {
const wrapper = mount(<BarChart data={[]} loading={true} />); // Use full mount function so that we can check for a LoadingBox child
expect(wrapper.find(LoadingBox).exists()).toBe(true);
expect(wrapper.find('.skeleton-chart').exists()).toBe(true);
});
});
3 changes: 1 addition & 2 deletions frontend/__tests__/components/graphs/graph-empty.spec.tsx
Expand Up @@ -3,12 +3,11 @@ import { shallow } from 'enzyme';
import { EmptyState, Title } from '@patternfly/react-core';

import { GraphEmpty } from '@console/internal/components/graphs/graph-empty';
import { LoadingBox } from '@console/internal/components/utils';

describe('<GraphEmpty />', () => {
it('should render a loading state', () => {
const wrapper = shallow(<GraphEmpty loading />);
expect(wrapper.find(LoadingBox).exists()).toBe(true);
expect(wrapper.find('.skeleton-chart').exists()).toBe(true);
});

it('should render an empty state', () => {
Expand Down
Expand Up @@ -66,7 +66,17 @@ export const RecentEventsBodyContent: React.FC<RecentEventsBodyContentProps> = (
return <ErrorLoadingEvents />;
}
if (!(events && events.loaded)) {
return <div className="skeleton-activity" />;
return (
<div className="co-status-card__alerts-body">
<div className="co-status-card__alert-item co-status-card__alert-item--loading">
<div className="skeleton-activity__dashboard" />
<div className="skeleton-activity__dashboard" />
<div className="skeleton-activity__dashboard" />
<div className="skeleton-activity__dashboard" />
<div className="skeleton-activity__dashboard" />
</div>
</div>
);
}

const filteredEvents = filter ? eventsData.filter(filter) : eventsData;
Expand Down Expand Up @@ -119,7 +129,11 @@ export const OngoingActivityBody: React.FC<OngoingActivityBodyProps> = ({
loaded || resourceActivities.length > 0 || prometheusActivities.length > 0;
let body: React.ReactNode;
if (!activitiesLoaded) {
body = <div className="skeleton-activity" />;
body = (
<div className="co-activity-item__ongoing">
<div className="skeleton-activity__dashboard" />
</div>
);
} else {
const allActivities = prometheusActivities.map(({ results, loader }, idx) => (
// eslint-disable-next-line react/no-array-index-key
Expand Down
Expand Up @@ -134,17 +134,34 @@
text-align: left;
}

.skeleton-activity {
.skeleton-activity__dashboard {
animation: $skeleton-animation;
background: $skeleton-color;
height: 30px;
height: $skeleton-bone-height-1line;
margin-bottom: 1em;
opacity: 0;
margin: 1rem var(--pf-c-card--child--PaddingRight) 1rem var(--pf-c-card--child--PaddingLeft);
width: 100%;
&::after {
background-repeat: no-repeat;
content: "";
display: block;
content:"";
display:block;
height: 100%;
width: 100%;
}
&:last-of-type {
margin-bottom: 0;
}
}

.skeleton-activity__dashboard::after {
background-image:
$skeleton-activity-bone,
$skeleton-activity-icon;

background-position:
$skeleton-activity-position,
$skeleton-activity-icon-position;

background-size:
$skeleton-activity-size,
$skeleton-activity-icon-size;
}
@@ -1,14 +1,13 @@
import * as React from 'react';
import * as classNames from 'classnames';
import { LoadingInline } from '@console/internal/components/utils/status-box';

export const DetailItem: React.FC<DetailItemProps> = React.memo(
({ title, isLoading = false, children, error = false, valueClassName }) => {
let status: React.ReactNode;
if (error) {
status = <span className="text-secondary">Not available</span>;
} else if (isLoading) {
status = <LoadingInline />;
status = <div className="skeleton-text" />;
} else {
status = children;
}
Expand Down
Expand Up @@ -23,8 +23,11 @@ const AlertsBody: React.FC<AlertsBodyProps> = ({
);
} else if (isLoading) {
body = (
<div className="co-status-card__alerts-body--loading">
<div className="skeleton-alerts" />
<div className="co-status-card__alerts-body">
<div className="co-status-card__alert-item co-status-card__alert-item--loading">
<div className="skeleton-status-alerts" />
<div className="skeleton-status-alerts" />
</div>
</div>
);
} else if (!children) {
Expand Down
Expand Up @@ -13,11 +13,10 @@
}
}

.co-status-card__alerts-body--loading {
align-items: center;
.co-status-card__alert-item--loading {
display: flex;
flex-direction: column;
height: 100%;
justify-content: center;
width: 100%;
}

Expand Down Expand Up @@ -108,13 +107,13 @@
font-size: 0.7rem;
}

.skeleton-alerts {
.skeleton-health {
animation: $skeleton-animation;
border-radius: 50px;
background: $skeleton-color;
height: 40px;
width: 400px;
height: $skeleton-bone-height-1line;
opacity: 0;
margin-right: 0.5rem;
width: $skeleton-bone-height-1line;
&::after {
background-repeat: no-repeat;
content: "";
Expand All @@ -124,17 +123,37 @@
}
}

.skeleton-health {
.skeleton-status-alerts {
animation: $skeleton-animation;
background: $skeleton-color;
height: 20px;
width: 20px;
height: 50px;
margin-bottom: 1em;
opacity: 0;
width: 100%;
&::after {
background-repeat: no-repeat;
content: "";
display: block;
content:"";
display:block;
height: 100%;
width: 100%;
}
&:last-of-type {
margin-bottom: 0;
}
}

.skeleton-status-alerts::after {
background-image:
$skeleton-status-bone,
$skeleton-status-bone,
$skeleton-status-resource-icon;

background-position:
$skeleton-status-metadata-position,
$skeleton-status-resource-position,
$skeleton-status-resource-icon-position;

background-size:
$skeleton-status-metadata-size,
$skeleton-status-resource-size,
$skeleton-status-resource-icon-size;
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 51 additions & 0 deletions frontend/packages/console-shared/src/styles/skeleton-screen.scss
@@ -1,2 +1,53 @@
$skeleton-animation: loading-skeleton 1s ease-out .15s infinite alternate;
$skeleton-color: #eaedf1;
$skeleton-bone-height-1line: 24px;

// Dashboard Status
$skeleton-status-bone-height: $skeleton-bone-height-1line; // position out of alpha
$skeleton-status-bone: linear-gradient($skeleton-color $skeleton-status-bone-height, transparent 0);
$skeleton-status-position: 0 10px;
$skeleton-status-data-position: $skeleton-status-position;
$skeleton-status-data-size: 200px;
$skeleton-status-metadata-position: 45px 0;
$skeleton-status-metadata-size: 80px 15px;
$skeleton-status-resource-icon: radial-gradient(circle 12px at center, $skeleton-color 100%, transparent 0);
$skeleton-status-resource-icon-position: $skeleton-status-position;
$skeleton-status-resource-icon-size: $skeleton-bone-height-1line $skeleton-bone-height-1line;
$skeleton-status-resource-position: 45px 24px;
$skeleton-status-resource-size: 75%;

// Dashboard Activity
$skeleton-activity-bone: linear-gradient($skeleton-color $skeleton-bone-height-1line, transparent 0);
$skeleton-activity-icon: radial-gradient(circle 12px at center, $skeleton-color 100%, transparent 0);
$skeleton-activity-icon-position: 0 0;
$skeleton-activity-icon-size: $skeleton-status-resource-icon-size;
$skeleton-activity-position: 45px 0;
$skeleton-activity-size: auto;


.skeleton-text {
animation: $skeleton-animation;
background: $skeleton-color;
height: $skeleton-bone-height-1line;
opacity: 0;
&::after {
background-repeat: no-repeat;
content: "";
display: block;
height: 100%;
width: 100%;
}
}

.skeleton-chart {
animation: $skeleton-animation;
background-image: url('../images/skeleton-chart-cpu.png');
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
display: inline-block;
height: 100%;
opacity: 0;
vertical-align: middle;
width: 90%;
}
10 changes: 5 additions & 5 deletions frontend/public/components/graphs/graph-empty.tsx
@@ -1,19 +1,19 @@
import * as React from 'react';
import { EmptyState, EmptyStateVariant, Title } from '@patternfly/react-core';
import { LoadingBox } from '../utils';

export const GraphEmpty: React.FC<GraphEmptyProps> = ({ height = 180, loading = false }) => (
<div
style={{
height,
width: '100%',
display: 'flex',
alignItems: 'center',
display: 'flex',
height,
justifyContent: 'center',
padding: '5px',
width: '100%',
}}
>
{loading ? (
<LoadingBox />
<div className="skeleton-chart" />
) : (
<EmptyState variant={EmptyStateVariant.full}>
<Title className="graph-empty-state__title text-secondary" size="sm">
Expand Down
2 changes: 1 addition & 1 deletion frontend/public/components/utils/_skeleton-screen.scss
@@ -1,6 +1,6 @@
@import '~@console/shared/src/styles/skeleton-screen';

$skeleton-detail-bone-height: 24px;
$skeleton-detail-bone-height: $skeleton-bone-height-1line;
$skeleton-detail-bone: linear-gradient(white $skeleton-detail-bone-height, transparent 0);

$skeleton-detail-position: 15px 35px; // declared out of alpha order to be reused
Expand Down

0 comments on commit 6beabd7

Please sign in to comment.