Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ const DetailsCard: React.FC<DashboardItemProps> = ({
const infrastructure = _.get(resources, 'infrastructure');
const infrastructureLoaded = _.get(infrastructure, 'loaded', false);
const infrastructureData = _.get(infrastructure, 'data') as K8sResourceKind;
const infrastructurePlatform = getInfrastructurePlatform(infrastructureData);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rawagner Please be advised, @jtomasek adds this to console-shared selectors in his PR #2558.

https://github.com/openshift/console/pull/2558/files#diff-25304ce4310324e88754e9516a46ac5c

Once #2558 is merged, we should update our existing code to use this shared selector.

This also applies to code below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I will update the existing code then

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm wondering if there are any duplicate code detectors for TypeScript / JavaScript, which can calculate code similarity (e.g. percentage) between files.


const cephCluster = _.get(resources, 'ceph');
const cephClusterLoaded = _.get(cephCluster, 'loaded', false);
const cephClusterData = _.get(cephCluster, 'data') as K8sResourceKind[];
const cephClusterName = getName(_.get(cephClusterData, 0));

const subscription = _.get(resources, 'subscription');
const subscriptionLoaded = _.get(subscription, 'loaded');
Expand All @@ -76,30 +78,33 @@ const DetailsCard: React.FC<DashboardItemProps> = ({
</DashboardCardHeader>
<DashboardCardBody>
<DetailsBody>
<DetailItem
key="service_name"
title="Service Name"
value="OpenShift Container Storage"
isLoading={false}
/>
<DetailItem key="service_name" title="Service Name" isLoading={false} error={false}>
OpenShift Container Storage
</DetailItem>
<DetailItem
key="cluster_name"
title="Cluster Name"
value={getName(_.get(cephClusterData, 0))}
error={!cephClusterName}
isLoading={!cephClusterLoaded}
/>
>
{cephClusterName}
</DetailItem>
<DetailItem
key="provider"
title="Provider"
value={getInfrastructurePlatform(infrastructureData)}
error={!infrastructurePlatform}
isLoading={!infrastructureLoaded}
/>
>
{infrastructurePlatform}
</DetailItem>
<DetailItem
key="version"
title="Version"
value={ocsVersion}
isLoading={!subscriptionLoaded}
/>
error={!ocsVersion}
>
{ocsVersion}
</DetailItem>
</DetailsBody>
</DashboardCardBody>
</DashboardCard>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import {
DashboardItemProps,
withDashboardResources,
} from '@console/internal/components/dashboards-page/with-dashboard-resources';
import { FirehoseResource } from '@console/internal/components/utils';
import { FirehoseResource, ExternalLink } from '@console/internal/components/utils';
import { InfrastructureModel, SubscriptionModel } from '@console/internal/models/index';
import { referenceForModel, K8sResourceKind } from '@console/internal/module/k8s';
import { getInfrastructurePlatform } from '@console/ceph-storage-plugin/src/selectors';
import { getMetric } from '../../utils';

const NOOBAA_SYSTEM_NAME_QUERY = 'NooBaa_system_info';

Expand Down Expand Up @@ -55,11 +56,15 @@ export const ObjectServiceDetailsCard: React.FC<DashboardItemProps> = ({

const queryResult = prometheusResults.getIn([NOOBAA_SYSTEM_NAME_QUERY, 'result']);

const systemName = _.get(queryResult, 'data.result[0].metric.system_name');
const systemName = getMetric(queryResult, 'system_name');
const systemAddress = getMetric(queryResult, 'system_address');
const systemLink =
systemName && systemAddress ? `${systemAddress}fe/systems/${systemName}` : undefined;

const infrastructure = _.get(resources, 'infrastructure');
const infrastructureLoaded = _.get(infrastructure, 'loaded', false);
const infrastructureData = _.get(infrastructure, 'data') as K8sResourceKind;
const infrastructurePlatform = getInfrastructurePlatform(infrastructureData);

const subscription = _.get(resources, 'subscription');
const subscriptionLoaded = _.get(subscription, 'loaded');
Expand All @@ -72,30 +77,33 @@ export const ObjectServiceDetailsCard: React.FC<DashboardItemProps> = ({
</DashboardCardHeader>
<DashboardCardBody>
<DetailsBody>
<DetailItem
key="service_name"
title="Service Name"
value="OpenShift Container Storage"
isLoading={false}
/>
<DetailItem key="service_name" title="Service Name" error={false} isLoading={false}>
OpenShift Container Storage
</DetailItem>
<DetailItem
key="system_name"
title="System Name"
value={systemName}
isLoading={!queryResult}
/>
error={!systemLink}
>
<ExternalLink href={systemLink} text={systemName} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rawagner If DetailItem has error prop set to a truthy value, does the child content (i.e. ExternalLink above) actually render?

If yes, the systemLink will be either invalid or undefined (see my suggestion above).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, child is not rendered then. DetailItem will render unavailable string

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good, so we can simply use the error={!systemLink} as a guard for the system link 😃

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

</DetailItem>
<DetailItem
key="provider"
title="Provider"
value={getInfrastructurePlatform(infrastructureData)}
error={!infrastructurePlatform}
isLoading={!infrastructureLoaded}
/>
>
{infrastructurePlatform}
</DetailItem>
<DetailItem
key="version"
title="Version"
value={ocsVersion}
isLoading={!subscriptionLoaded}
/>
error={!ocsVersion}
>
{ocsVersion}
</DetailItem>
</DetailsBody>
</DashboardCardBody>
</DashboardCard>
Expand Down
33 changes: 21 additions & 12 deletions frontend/public/components/dashboard/details-card/detail-item.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import * as React from 'react';
import classNames from 'classnames';

import { LoadingInline } from '../../utils';

export const DetailItem: React.FC<DetailItemProps> = React.memo(({ title, value, isLoading }) => (
<React.Fragment>
<dt className="co-details-card__item-title">{title}</dt>
<dd className={classNames('co-details-card__item-value', {'text-secondary': !value})}>
{isLoading ? <LoadingInline /> : value || 'Unavailable'}
</dd>
</React.Fragment>
));
export const DetailItem: React.FC<DetailItemProps> = React.memo(
({ title, isLoading = false, children, error = false }) => {
let status: React.ReactNode;
if (isLoading) {
status = <LoadingInline />;
} else if (error) {
status = <span className="text-secondary">Unavailable</span>;
} else {
status = children;
}
return (
<React.Fragment>
<dt className="co-details-card__item-title">{title}</dt>
<dd className="co-details-card__item-value">{status}</dd>
</React.Fragment>
);
}
);

type DetailItemProps = {
title: string;
value?: string;
isLoading: boolean;
isLoading?: boolean;
error?: boolean;
children: React.ReactNode;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI there is a React helper type to avoid repeating children in your component props:

// node_modules/@types/react/index.d.ts
type PropsWithChildren<P> = P & { children?: ReactNode };

You can use it like so:

type DetailItemProps = React.PropsWithChildren<{
  title: string;
  isLoading: boolean;
  error: boolean;
}>;

and it will add an optional children prop.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React.FC already includes optional children prop as it uses that helper internally, so it is not necessary to deal with children prop at all (except for the cases when we want to explicitly define children prop as specific type or make it required)

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L495

};
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,16 @@ export const DetailsCard_ = connect(mapStateToProps)(({
const clusterVersionLoaded = _.get(resources.cv, 'loaded', false);
const clusterVersionError = _.get(resources.cv, 'loadError');
const clusterVersionData = _.get(resources.cv, 'data') as ClusterVersionKind;
const clusterId = getClusterID(clusterVersionData);
const openShiftVersion = getOpenShiftVersion(clusterVersionData);

const infrastructureLoaded = _.get(resources.infrastructure, 'loaded', false);
const infrastructureError = _.get(resources.infrastructure, 'loadError');
const infrastructureData = _.get(resources.infrastructure, 'data') as K8sResourceKind;

const infrastructurePlatform = getInfrastructurePlatform(infrastructureData);

const kubernetesVersionResponse = urlResults.getIn(['version', 'result']);
const k8sGitVersion = getK8sGitVersion(kubernetesVersionResponse);

return (
<DashboardCard>
Expand All @@ -89,29 +92,37 @@ export const DetailsCard_ = connect(mapStateToProps)(({
<DetailItem
key="clusterid"
title="Cluster ID"
value={getClusterID(clusterVersionData)}
error={!clusterId}
isLoading={!clusterVersionLoaded && !clusterVersionError}
/>
>
{clusterId}
</DetailItem>
<DetailItem
key="provider"
title="Provider"
value={getInfrastructurePlatform(infrastructureData)}
error={!infrastructurePlatform}
isLoading={!infrastructureLoaded && !infrastructureError}
/>
>
{infrastructurePlatform}
</DetailItem>
<DetailItem
key="openshift"
title="OpenShift version"
value={getOpenShiftVersion(clusterVersionData)}
error={!openShiftVersion}
isLoading={!clusterVersionLoaded && !clusterVersionError}
/>
>
{openShiftVersion}
</DetailItem>
</>
) : (
<DetailItem
key="kubernetes"
title="Kubernetes version"
value={getK8sGitVersion(kubernetesVersionResponse)}
error={!k8sGitVersion}
isLoading={!kubernetesVersionResponse}
/>
>
{k8sGitVersion}
</DetailItem>
)}
</DetailsBody>
</DashboardCardBody>
Expand Down