Skip to content

Commit

Permalink
feat: show downstream packages (#107)
Browse files Browse the repository at this point in the history
This change adds the Downstream tab to the Package Revision page to show the downstream packages for the current package. The tab is hidden when a deployment package is viewed.
  • Loading branch information
ChristopherFry committed Aug 12, 2022
1 parent 139a7c9 commit 6e100c4
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ import {
getPackageRevisionResources,
getPackageRevisionResourcesResource,
} from '../../utils/packageRevisionResources';
import {
getPackageSummaries,
PackageSummary,
} from '../../utils/packageSummary';
import {
findRepository,
getPackageDescriptor,
Expand All @@ -76,6 +80,7 @@ import { toLowerCase } from '../../utils/string';
import { ConfirmationDialog } from '../Controls';
import { PackageLink, RepositoriesLink, RepositoryLink } from '../Links';
import { AdvancedPackageRevisionOptions } from './components/AdvancedPackageRevisionOptions';
import { DownstreamTabContent } from './components/DownstreamTabContent';
import {
PackageRevisionOptions,
RevisionOption,
Expand All @@ -96,6 +101,15 @@ type PackageRevisionPageProps = {
mode: PackageRevisionPageMode;
};

type TabProps = {
label: string;
content: JSX.Element;
};

type ConditionalTabProps = TabProps & {
showTab?: boolean;
};

const useStyles = makeStyles({
packageRevisionOptions: {
display: 'inherit',
Expand Down Expand Up @@ -129,6 +143,10 @@ export const PackageRevisionPage = ({ mode }: PackageRevisionPageProps) => {
const [packageRevision, setPackageRevision] = useState<PackageRevision>();
const [upstreamPackageRevision, setUpstreamPackageRevision] =
useState<PackageRevision>();
const [downstreamPackageSummaries, setDownstreamPackageSummaries] = useState<
PackageSummary[]
>([]);

const [revisionSummaries, setRevisionSummaries] = useState<RevisionSummary[]>(
[],
);
Expand Down Expand Up @@ -245,6 +263,18 @@ export const PackageRevisionPage = ({ mode }: PackageRevisionPageProps) => {
}
}

const downstreamPackages = getPackageSummaries(
thisPackageRevisions,
getRepositorySummaries(allRepositories.current),
allRepositories.current,
).filter(
summary =>
summary.upstreamPackageName === thisPackageRevision.spec.packageName &&
summary.upstreamRepositoryName === thisPackageRevision.spec.repository,
);

setDownstreamPackageSummaries(downstreamPackages);

setIsUpgradeAvailable(upgradeAvailable);
};

Expand Down Expand Up @@ -656,6 +686,10 @@ export const PackageRevisionPage = ({ mode }: PackageRevisionPageProps) => {

const alertMessages = isUpgradeAvailable ? [getUpgradeAlertText()] : [];

const getDisplayTabs = (tabs: ConditionalTabProps[]): TabProps[] => {
return tabs.filter(tab => tab.showTab !== false);
};

return (
<div>
<Breadcrumbs>
Expand Down Expand Up @@ -705,7 +739,7 @@ export const PackageRevisionPage = ({ mode }: PackageRevisionPageProps) => {
/>

<Tabs
tabs={[
tabs={getDisplayTabs([
{
label: 'Resources',
content: (
Expand All @@ -729,6 +763,17 @@ export const PackageRevisionPage = ({ mode }: PackageRevisionPageProps) => {
/>
),
},
{
label: 'Downstream',
content: (
<DownstreamTabContent
packageDescriptor={packageDescriptor}
downstreamPackages={downstreamPackageSummaries}
/>
),
showTab:
!isDeploymentPackage || downstreamPackageSummaries.length > 0,
},
{
label: 'Advanced',
content: (
Expand All @@ -739,7 +784,7 @@ export const PackageRevisionPage = ({ mode }: PackageRevisionPageProps) => {
/>
),
},
]}
])}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { makeStyles } from '@material-ui/core';
import { groupBy, uniq } from 'lodash';
import React, { Fragment } from 'react';
import { PackageSummary } from '../../../utils/packageSummary';
import {
ContentSummary,
PackageContentSummaryOrder,
} from '../../../utils/repository';
import { PackagesTable } from '../../PackagesTable';

type ResourcesTabContentProps = {
packageDescriptor: string;
downstreamPackages: PackageSummary[];
};

const useStyles = makeStyles({
packagesTable: {
marginBottom: '24px',
},
});

export const DownstreamTabContent = ({
packageDescriptor,
downstreamPackages,
}: ResourcesTabContentProps) => {
const classes = useStyles();

const getDesciptorPriority = (descriptor: string): number =>
PackageContentSummaryOrder.indexOf(descriptor as ContentSummary);
const compareDescriptors = (
descriptor1: string,
descriptor2: string,
): number =>
getDesciptorPriority(descriptor1) > getDesciptorPriority(descriptor2)
? 1
: -1;

const requiredDescriptorToShow =
PackageContentSummaryOrder[getDesciptorPriority(packageDescriptor) - 1];
const packagesByDescriptor = groupBy(
downstreamPackages,
packageSummary => packageSummary.packageDescriptor,
);

const packageDescriptorsToDisplay = uniq([
requiredDescriptorToShow,
...Object.keys(packagesByDescriptor),
]).sort(compareDescriptors);

return (
<Fragment>
{packageDescriptorsToDisplay.map(descriptor => (
<div key={descriptor} className={classes.packagesTable}>
<PackagesTable
title={`${descriptor}s`}
packages={packagesByDescriptor[descriptor] ?? []}
showRepositoryColumn
/>
</div>
))}
</Fragment>
);
};
42 changes: 33 additions & 9 deletions plugins/cad/src/components/PackagesTable/PackagesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ import { getSyncStatus, SyncStatus } from '../../utils/configSync';
import { formatCreationTimestamp } from '../../utils/formatDate';
import { PackageSummary } from '../../utils/packageSummary';
import { IconButton, PackageIcon } from '../Controls';
import { PackageLink } from '../Links';
import { PackageLink, RepositoryLink } from '../Links';
import { SyncStatusVisual } from './components/SyncStatusVisual';
import ArrowUpwardIcon from '@material-ui/icons/ArrowUpward';
import { Repository } from '../../types/Repository';

type PackagesTableProps = {
title: string;
packages: PackageSummary[];
showRepositoryColumn?: boolean;
showSyncStatusColumn?: boolean;
};

Expand All @@ -56,11 +58,16 @@ type PackageRow = {
created: string;
upstreamPackageDisplayName?: string;
upstreamPackageRevision?: PackageRevision;
repository: Repository;
navigate: () => void;
unpublished?: UnpublishedPackageRevision;
isUpgradeAvailable?: boolean;
};

type ConditionalTableColumn<T extends object = {}> = TableColumn<T> & {
showColumn?: boolean;
};

type NavigateToPackageRevision = (revision: PackageRevision) => void;

const renderStatusColumn = (row: PackageRow): JSX.Element => {
Expand All @@ -86,6 +93,10 @@ const renderStatusColumn = (row: PackageRow): JSX.Element => {
);
};

const renderRepositoryColumn = (row: PackageRow): JSX.Element => {
return <RepositoryLink repository={row.repository} stopPropagation />;
};

const renderBlueprintColumn = (row: PackageRow): JSX.Element => {
if (row.upstreamPackageRevision) {
return (
Expand All @@ -104,27 +115,35 @@ const renderSyncColumn = (row: PackageRow): JSX.Element => (
);

const getTableColumns = (
includeRepositoryColumn: boolean,
includeSyncStatusColumn: boolean,
): TableColumn<PackageRow>[] => {
const columns: TableColumn<PackageRow>[] = [
const columnDefinitions: ConditionalTableColumn<PackageRow>[] = [
{
title: 'Status',
width: '80px',
render: renderStatusColumn,
},
{
title: 'Repository',
render: renderRepositoryColumn,
showColumn: includeRepositoryColumn,
},
{ title: 'Name', field: 'packageName' },
{ title: 'Revision', field: 'revision' },
{ title: 'Lifecycle', field: 'lifecycle' },
{ title: 'Blueprint', render: renderBlueprintColumn },
{
title: 'Sync Status',
render: renderSyncColumn,
showColumn: includeSyncStatusColumn,
},
{ title: 'Created', field: 'created' },
];

if (includeSyncStatusColumn) {
columns.splice(columns.length - 1, 0, {
title: 'Sync Status',
render: renderSyncColumn,
});
}
const columns = columnDefinitions.filter(
column => column.showColumn !== false,
);

return columns;
};
Expand Down Expand Up @@ -187,6 +206,7 @@ const mapToPackageSummaryRow = (
? `${packageSummary.upstreamPackageName} ${packageSummary.upstreamPackageRevision}`
: undefined,
isUpgradeAvailable: packageSummary.isUpgradeAvailable,
repository: packageSummary.repository,
upstreamPackageRevision: packageSummary.upstreamRevision,
unpublished: mapToUnpublishedRevision(
packageSummary,
Expand All @@ -207,6 +227,7 @@ const mapPackageSummariesToRows = (
export const PackagesTable = ({
title,
packages,
showRepositoryColumn,
showSyncStatusColumn,
}: PackagesTableProps) => {
const navigate = useNavigate();
Expand All @@ -222,7 +243,10 @@ export const PackagesTable = ({
navigate(packageRef({ repositoryName, packageName }));
};

const columns = getTableColumns(!!showSyncStatusColumn);
const columns = getTableColumns(
!!showRepositoryColumn,
!!showSyncStatusColumn,
);

const data = mapPackageSummariesToRows(packages, navigateToPackageRevision);

Expand Down
8 changes: 7 additions & 1 deletion plugins/cad/src/utils/packageSummary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
isNotAPublishedRevision,
sortByPackageNameAndRevisionComparison,
} from './packageRevision';
import { findRepository } from './repository';
import { findRepository, getPackageDescriptor } from './repository';

export type PackageSummary = {
repository: Repository;
Expand All @@ -38,9 +38,11 @@ export type PackageSummary = {
unpublishedRevision?: PackageRevision;
upstreamRevision?: PackageRevision;
upstreamPackageName?: string;
upstreamRepositoryName?: string;
upstreamPackageRevision?: string;
upstreamLatestPublishedRevision?: PackageRevision;
isUpgradeAvailable?: boolean;
packageDescriptor: string;
sync?: RootSync;
};

Expand Down Expand Up @@ -77,11 +79,14 @@ export const getPackageSummariesForRepository = (
? latestRevision
: undefined;

const packageDescriptor = getPackageDescriptor(repository);

const thisPackageSummary: PackageSummary = {
repository,
latestRevision,
latestPublishedRevision,
unpublishedRevision,
packageDescriptor,
};

const useRevision = latestPublishedRevision ?? latestRevision;
Expand All @@ -97,6 +102,7 @@ export const getPackageSummariesForRepository = (

if (upstreamRepository) {
const upstreamRepositoryName = upstreamRepository.metadata.name;
thisPackageSummary.upstreamRepositoryName = upstreamRepositoryName;

thisPackageSummary.upstreamRevision = findPackageRevision(
allPackageRevisions,
Expand Down
6 changes: 6 additions & 0 deletions plugins/cad/src/utils/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ export enum ContentSummary {
FUNCTION = 'Function',
}

export const PackageContentSummaryOrder = [
ContentSummary.DEPLOYMENT,
ContentSummary.BLUEPRINT,
ContentSummary.CATALOG_BLUEPRINT,
];

export const isFunctionRepository = (repository: Repository): boolean => {
return repository.spec.content === RepositoryContent.FUNCTION;
};
Expand Down

0 comments on commit 6e100c4

Please sign in to comment.