Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

fix(5715,5729) and add empty state components for integration-related components #5782

Merged
merged 1 commit into from
Jun 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion app/ui-react/packages/ui/src/Dashboard/TopIntegrationsCard.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import * as H from '@syndesis/history';
import { Card } from 'patternfly-react';
import * as React from 'react';
import { IntegrationsEmptyState } from '../Integration';

import './TopIntegrations.css';

export interface ITopIntegrationsProps {
i18nCreateIntegration: string;
i18nCreateIntegrationTip?: string;
i18nEmptyStateInfo: string;
i18nEmptyStateTitle: string;
i18nLast30Days: string;
i18nTitle: string;
linkCreateIntegration: H.LocationDescriptor;
}

export class TopIntegrationsCard extends React.Component<
Expand All @@ -20,7 +27,19 @@ export class TopIntegrationsCard extends React.Component<
{this.props.i18nLast30Days}
</div>
</Card.Heading>
<Card.Body>{this.props.children}</Card.Body>
<Card.Body>
{this.props.children ? (
this.props.children
) : (
<IntegrationsEmptyState
i18nCreateIntegration={this.props.i18nCreateIntegration}
i18nCreateIntegrationTip={this.props.i18nCreateIntegrationTip}
i18nEmptyStateInfo={this.props.i18nEmptyStateInfo}
i18nEmptyStateTitle={this.props.i18nEmptyStateTitle}
linkCreateIntegration={this.props.linkCreateIntegration}
/>
)}
</Card.Body>
</Card>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as H from '@syndesis/history';
import { EmptyState, OverlayTrigger, Tooltip } from 'patternfly-react';
import * as React from 'react';
import { ButtonLink } from '../Layout';

export interface IIntegrationsEmptyStateProps {
i18nCreateIntegration: string;
i18nCreateIntegrationTip?: string;
i18nEmptyStateInfo: string;
i18nEmptyStateTitle: string;
linkCreateIntegration: H.LocationDescriptor;
}

export class IntegrationsEmptyState extends React.Component<
IIntegrationsEmptyStateProps
> {
public getCreateIntegrationTooltip() {
return (
<Tooltip id="createTip">
{this.props.i18nCreateIntegrationTip
? this.props.i18nCreateIntegrationTip
: this.props.i18nCreateIntegration}
</Tooltip>
);
}

public render() {
return (
<EmptyState>
<EmptyState.Icon />
<EmptyState.Title>{this.props.i18nEmptyStateTitle}</EmptyState.Title>
<EmptyState.Info>{this.props.i18nEmptyStateInfo}</EmptyState.Info>
<EmptyState.Action>
<OverlayTrigger
overlay={this.getCreateIntegrationTooltip()}
placement="top"
>
<ButtonLink
data-testid={'integrations-empty-state-create-button'}
href={this.props.linkCreateIntegration}
as={'primary'}
>
{this.props.i18nCreateIntegration}
</ButtonLink>
</OverlayTrigger>
</EmptyState.Action>
</EmptyState>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ListViewToolbar,
SimplePageHeader,
} from '../Shared';
import { IntegrationsEmptyState } from './IntegrationsEmptyState';

export interface IIntegrationsListViewProps extends IListViewToolbarProps {
linkToManageCiCd: H.LocationDescriptor;
Expand All @@ -16,6 +17,9 @@ export interface IIntegrationsListViewProps extends IListViewToolbarProps {
i18nManageCiCd: string;
i18nImport: string;
i18nLinkCreateConnection: string;
i18nLinkCreateIntegrationTip?: string;
i18nEmptyStateInfo: string;
i18nEmptyStateTitle: string;
}

export class IntegrationsListView extends React.Component<
Expand Down Expand Up @@ -52,7 +56,17 @@ export class IntegrationsListView extends React.Component<
</ButtonLink>
</div>
</ListViewToolbar>
{this.props.children}
{this.props.children ? (
this.props.children
) : (
<IntegrationsEmptyState
i18nCreateIntegration={this.props.i18nLinkCreateConnection}
i18nCreateIntegrationTip={this.props.i18nLinkCreateIntegrationTip}
i18nEmptyStateInfo={this.props.i18nEmptyStateInfo}
i18nEmptyStateTitle={this.props.i18nEmptyStateTitle}
linkCreateIntegration={this.props.linkToIntegrationCreation}
/>
)}
</PageSection>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
padding-bottom: 10px;
}

.integration-detail-metrics__duration-difference {
font-size: smaller;
}

.integration-detail-metrics__last-processed {
font-size: smaller;
}

.integration-detail-metrics__uptime-header {
display: flex;
justify-content: space-between;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import './IntegrationDetailMetrics.css';

export interface IIntegrationDetailMetricsProps {
i18nLastProcessed: string;
i18nNoDataAvailable: string;
i18nSince: string;
i18nTotalErrors: string;
i18nTotalMessages: string;
Expand All @@ -34,7 +35,7 @@ export class IntegrationDetailMetrics extends React.Component<
public render() {
const okMessagesCount = this.props.messages! - this.props.errors!;
const startAsDate = new Date(this.props.start!);
const startAsHuman = startAsDate.toLocaleString();
const startAsHuman = this.props.i18nSince + startAsDate.toLocaleString();

return (
<PageSection className="integration-detail-metrics">
Expand All @@ -52,7 +53,7 @@ export class IntegrationDetailMetrics extends React.Component<
<AggregateStatusNotifications>
<AggregateStatusNotification>
<Icon type="pf" name="error-circle-o" />
{this.props.errors}
{this.props.errors ? this.props.errors : 0}
</AggregateStatusNotification>
</AggregateStatusNotifications>
</CardBody>
Expand All @@ -68,8 +69,10 @@ export class IntegrationDetailMetrics extends React.Component<
<CardTitle>{this.props.i18nLastProcessed}</CardTitle>
<CardBody>
<AggregateStatusNotifications>
<AggregateStatusNotification>
{this.props.lastProcessed}
<AggregateStatusNotification className="integration-detail-metrics__last-processed">
{this.props.lastProcessed
? this.props.lastProcessed
: this.props.i18nNoDataAvailable}
</AggregateStatusNotification>
</AggregateStatusNotifications>
</CardBody>
Expand All @@ -84,19 +87,23 @@ export class IntegrationDetailMetrics extends React.Component<
>
<CardTitle>
<AggregateStatusCount>
{this.props.messages}&nbsp;
{this.props.messages ? this.props.messages : 0}&nbsp;
</AggregateStatusCount>
{this.props.i18nTotalMessages}
</CardTitle>
<CardBody>
<AggregateStatusNotifications>
<AggregateStatusNotification>
<Icon type="pf" name="ok" />
{okMessagesCount}&nbsp;
{this.props.errors !== undefined &&
this.props.messages !== undefined
? okMessagesCount
: 0}
&nbsp;
</AggregateStatusNotification>
<AggregateStatusNotification>
<Icon type="pf" name="error-circle-o" />
{this.props.errors}
{this.props.errors ? this.props.errors : 0}
</AggregateStatusNotification>
</AggregateStatusNotifications>
</CardBody>
Expand All @@ -111,15 +118,19 @@ export class IntegrationDetailMetrics extends React.Component<
>
<Card.Title className="integration-detail-metrics__uptime-header">
<div>{this.props.i18nUptime}</div>
<div className="integration-detail-metrics__uptime-uptime">
{this.props.i18nSince}
{startAsHuman}
</div>
{this.props.start !== undefined &&
this.props.durationDifference !== undefined && (
<div className="integration-detail-metrics__uptime-uptime">
{startAsHuman}
</div>
)}
</Card.Title>
<Card.Body>
<AggregateStatusNotifications>
<AggregateStatusNotification>
{this.props.durationDifference}
<AggregateStatusNotification className="integration-detail-metrics__duration-difference">
{this.props.durationDifference !== undefined
? this.props.durationDifference
: this.props.i18nNoDataAvailable}
</AggregateStatusNotification>
</AggregateStatusNotifications>
</Card.Body>
Expand Down
1 change: 1 addition & 0 deletions app/ui-react/packages/ui/src/Integration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export * from './IntegrationFlowStepGeneric';
export * from './IntegrationFlowStepWithOverview';
export * from './IntegrationIcon';
export * from './IntegrationSaveForm';
export * from './IntegrationsEmptyState';
export * from './IntegrationStatus';
export * from './IntegrationStatusDetail';
export * from './IntegrationStepsHorizontalItem';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,18 +223,20 @@ storiesOf('Integration/Detail', module)
<TabBarItem label={'Activity'} to={'#activity'} />
<TabBarItem label={'Metrics'} to={'#metrics'} />
</TabBar>
<IntegrationDetailMetrics
i18nLastProcessed={'Last Processed'}
i18nNoDataAvailable={'No data available'}
i18nSince={'Since '}
i18nTotalErrors={'Total Errors'}
i18nTotalMessages={'Total Messages'}
i18nUptime={'Uptime'}
errors={2}
lastProcessed={'2 May 2019 08:19:42 GMT'}
messages={26126}
start={2323342333}
durationDifference={'3:15:59'}
/>
</Container>
<IntegrationDetailMetrics
i18nLastProcessed={'Last Processed'}
i18nSince={'Since '}
i18nTotalErrors={'Total Errors'}
i18nTotalMessages={'Total Messages'}
i18nUptime={'Uptime'}
errors={2}
lastProcessed={'2 May 2019 08:19:42 GMT'}
messages={26126}
start={2323342333}
/>
</>
</Router>
));
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { action } from '@storybook/addon-actions';
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { IntegrationsEmptyState } from '../../src';

const stories = storiesOf('Integration/IntegrationsEmptyState', module);

const createTip = 'Click to begin creating a new integration';
const info =
'There are currently no integrations. Click the button below to create one.';
const link = '/integrations/create/new-integration/start/abcdefg';
const title = 'Create Integration';

const storyNotes =
'- Verify title is "' +
title +
'"\n' +
'- Verify info is "' +
info +
'"\n' +
'- Verify button text is "' +
title +
'"\n' +
'- Verify button toolipt is "' +
createTip +
'"\n' +
'- Verify clicking button prints "' +
link +
'" in the **Actions** tab';

stories.add(
'render',
() => (
<Router>
<IntegrationsEmptyState
i18nCreateIntegration={title}
i18nCreateIntegrationTip={createTip}
i18nEmptyStateInfo={info}
i18nEmptyStateTitle={title}
linkCreateIntegration={action('blah')}
/>
</Router>
),
{ notes: storyNotes }
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import {
IIntegrationDetailMetricsProps,
IntegrationDetailMetrics,
} from '../../../src';

const stories = storiesOf(
'Integration/Metrics/IntegrationDetailMetrics',
module
);

const durationDifference = '3:15:59';
const errors = 2;
const i18nLastProcessed = 'Last Processed';
const i18nNoDataAvailable = 'No data available';
const i18nSince = 'Since ';
const i18nTotalErrors = 'Total Errors';
const i18nTotalMessages = 'Total Messages';
const i18nUptime = 'Uptime';
const lastProcessed = '2 May 2019 08:19:42 GMT';
const messages = 26126;
const start = 2323342333;

const propsOnlyRequired = {
i18nLastProcessed,
i18nNoDataAvailable,
i18nSince,
i18nTotalErrors,
i18nTotalMessages,
i18nUptime,
} as IIntegrationDetailMetricsProps;

const propsAll = {
...propsOnlyRequired,
durationDifference,
errors,
lastProcessed,
messages,
start,
} as IIntegrationDetailMetricsProps;

stories

.add('empty state', () => <IntegrationDetailMetrics {...propsOnlyRequired} />)

.add('all props', () => <IntegrationDetailMetrics {...propsAll} />);
5 changes: 4 additions & 1 deletion app/ui-react/packages/utils/src/dateHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ export function toDurationString(
timeDuration: number,
unit: 'ms' | 'ns'
): string {
if (!timeDuration) {
if (timeDuration === undefined) {
return 'NaN';
}
if (timeDuration === 0) {
return '0 ms';
}
if (unit === 'ns') {
timeDuration = timeDuration / 1000000;
}
Expand Down
Loading