Skip to content

Commit

Permalink
[PR #3880/18dfe82d backport][stable-4.7] Expose download counts (#4127)
Browse files Browse the repository at this point in the history
* Expose download counts (#3880)

* Expose download counts

for collections and legacy roles

Issue: AAH-2241

* DownloadCount - show number of downloads, use for legacy roles

* Collections - use DownloadCount, check insights mode

and reorganize the CollectionHeader page controls to look the same but allow for an extra row
and start pulling the collection api in loadCollection
and warn about collection count applying to all versions

(won't do anything without pulp_ansible#1477)

* fix title .. show be on the top even if the line gets larger

* repositoryBasePath for querying collection api

* move collection count to right side of version header

(cherry picked from commit 18dfe82)

* remove actuallyCollection, collection download counts

not supported in 4.7

* remove insights logic

---------

Co-authored-by: Martin Hradil <[email protected]>
  • Loading branch information
patchback[bot] and himdel authored Aug 14, 2023
1 parent 2d8603e commit 62cbfa6
Show file tree
Hide file tree
Showing 18 changed files with 203 additions and 153 deletions.
1 change: 1 addition & 0 deletions CHANGES/2241.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Expose legacy role download count in the UI
6 changes: 6 additions & 0 deletions src/api/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ export class API extends HubAPI {
`pulp/api/v3/content/ansible/collection_versions/`,
);
}

getDetail(distroBasePath, namespace, name) {
return this.http.get(
`v3/plugin/ansible/content/${distroBasePath}/collections/index/${namespace}/${name}/`,
);
}
}

export const CollectionAPI = new API();
2 changes: 2 additions & 0 deletions src/api/response-types/legacy-role.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export class LegacyRoleListType {
commit: string;
name: string;
description: string;
download_count: number;
summary_fields: {
dependencies: string[];
namespace: {
Expand Down Expand Up @@ -77,6 +78,7 @@ export class LegacyRoleDetailType {
commit: string;
name: string;
description: string;
download_count: number;
summary_fields: {
dependencies: string[];
namespace: {
Expand Down
6 changes: 2 additions & 4 deletions src/components/headers/base-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,9 @@ export class BaseHeader extends React.Component<IProps> {
</Title>
</div>
</div>
{pageControls ? (
<div className='header-right'>{pageControls}</div>
) : null}
{pageControls || null}
</div>
{versionControl ? <>{versionControl}</> : null}
{versionControl || null}

{children ? (
<div className='header-bottom'>{children}</div>
Expand Down
134 changes: 68 additions & 66 deletions src/components/headers/collection-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,15 @@ export class CollectionHeader extends React.Component<IProps, IState> {

render() {
const {
activeTab,
breadcrumbs,
className,
collection,
collections,
collectionsCount,
collection,
content,
params,
updateParams,
breadcrumbs,
activeTab,
className,
} = this.props;

const {
Expand Down Expand Up @@ -474,69 +474,71 @@ export class CollectionHeader extends React.Component<IProps, IState> {
}
breadcrumbs={<Breadcrumbs links={breadcrumbs} />}
versionControl={
<div className='install-version-column'>
<span>{t`Version`}</span>
<div className='install-version-dropdown'>
<Select
isOpen={isOpenVersionsSelect}
onToggle={(isOpenVersionsSelect) =>
this.setState({ isOpenVersionsSelect })
}
variant={SelectVariant.single}
onSelect={() =>
this.setState({ isOpenVersionsSelect: false })
}
selections={`v${version}`}
aria-label={t`Select collection version`}
loadingVariant={
collections.length < collectionsCount
? {
text: t`View more`,
onClick: () =>
this.setState({
isOpenVersionsModal: true,
isOpenVersionsSelect: false,
}),
}
: null
}
>
{collections
.map((c) => c.collection_version)
.map((v) => (
<SelectOption
key={v.version}
value={`v${v.version}`}
onClick={() =>
updateParams(
ParamHelper.setParam(
params,
'version',
v.version.toString(),
),
)
}
>
<Trans>
{v.version} updated {isLatestVersion(v)}
</Trans>
</SelectOption>
))}
</Select>
<div className='column-section'>
<div className='install-version-column'>
<span>{t`Version`}</span>
<div className='install-version-dropdown'>
<Select
isOpen={isOpenVersionsSelect}
onToggle={(isOpenVersionsSelect) =>
this.setState({ isOpenVersionsSelect })
}
variant={SelectVariant.single}
onSelect={() =>
this.setState({ isOpenVersionsSelect: false })
}
selections={`v${version}`}
aria-label={t`Select collection version`}
loadingVariant={
collections.length < collectionsCount
? {
text: t`View more`,
onClick: () =>
this.setState({
isOpenVersionsModal: true,
isOpenVersionsSelect: false,
}),
}
: null
}
>
{collections
.map((c) => c.collection_version)
.map((v) => (
<SelectOption
key={v.version}
value={`v${v.version}`}
onClick={() =>
updateParams(
ParamHelper.setParam(
params,
'version',
v.version.toString(),
),
)
}
>
<Trans>
{v.version} updated {isLatestVersion(v)}
</Trans>
</SelectOption>
))}
</Select>
</div>
{latestVersion ? (
<span className='last-updated'>
<Trans>
Last updated <DateComponent date={latestVersion} />
</Trans>
</span>
) : null}
{display_signatures ? (
<SignatureBadge
isCompact
signState={collection.is_signed ? 'signed' : 'unsigned'}
/>
) : null}
</div>
{latestVersion ? (
<span className='last-updated'>
<Trans>
Last updated <DateComponent date={latestVersion} />
</Trans>
</span>
) : null}
{display_signatures ? (
<SignatureBadge
isCompact
signState={collection.is_signed ? 'signed' : 'unsigned'}
/>
) : null}
</div>
}
pageControls={
Expand Down
4 changes: 0 additions & 4 deletions src/components/headers/header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ $breakpoint-md: 1000px;
.column-section {
display: flex;
justify-content: space-between;

.header-right {
align-items: right;
}
}

.install-version-column {
Expand Down
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export { ShaLabel } from './sha-label/sha-label';
export { DataForm } from './shared/data-form';
export { DetailList } from './shared/detail-list';
export { Details } from './shared/details';
export { DownloadCount } from './shared/download-count';
export { LoginLink } from './shared/login-link';
export { UIVersion } from './shared/ui-version';
export {
Expand Down
5 changes: 4 additions & 1 deletion src/components/legacy-role-list/legacy-role-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import * as React from 'react';
import { Link } from 'react-router-dom';
import { LegacyRoleDetailType } from 'src/api';
import { DateComponent, Logo, Tag } from 'src/components';
import { DateComponent, DownloadCount, Logo, Tag } from 'src/components';
import { Paths, formatPath } from 'src/paths';
import { chipGroupProps } from 'src/utilities';
import './legacy-role-item.scss';
Expand Down Expand Up @@ -105,6 +105,9 @@ export class LegacyRoleListItem extends React.Component<LegacyRoleProps> {
</Trans>
</div>
<div className='hub-entry'>{release_name}</div>
<div className='hub-entry'>
<DownloadCount item={role} />
</div>
</DataListCell>,
);

Expand Down
27 changes: 27 additions & 0 deletions src/components/shared/download-count.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Trans, t } from '@lingui/macro';
import { DownloadIcon } from '@patternfly/react-icons';
import React from 'react';
import { Tooltip } from 'src/components';
import { language } from 'src/l10n';

interface IProps {
item?: { download_count?: number };
}

export const DownloadCount = ({ item }: IProps) => {
if (!item?.download_count) {
return null;
}

const downloadCount = new Intl.NumberFormat(language).format(
item.download_count,
);

return (
<Tooltip
content={t`Download count is the sum of all versions' download counts`}
>
<DownloadIcon /> <Trans>{downloadCount} Downloads</Trans>
</Tooltip>
);
};
16 changes: 8 additions & 8 deletions src/containers/collection-detail/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import { AlertType } from 'src/components';
import { Paths, formatPath } from 'src/paths';

export interface IBaseCollectionState {
alerts?: AlertType[];
collection?: CollectionVersionSearch;
collections?: CollectionVersionSearch[];
collectionsCount?: number;
content?: CollectionVersionContentType;
distroBasePath?: string;
params: {
version?: string;
showing?: string;
keywords?: string;
};
collections?: CollectionVersionSearch[];
collectionsCount?: number;
collection?: CollectionVersionSearch;
content?: CollectionVersionContentType;
alerts?: AlertType[];
distroBasePath?: string;
}

// Caches the collection data when matching, prevents redundant fetches between collection detail tabs
Expand All @@ -28,9 +28,9 @@ const cache = {
name: null,
version: null,

collection: null,
collections: [],
collectionsCount: 0,
collection: null,
content: null,
};

Expand Down Expand Up @@ -110,9 +110,9 @@ export function loadCollection({
cache.name = name;
cache.version = version;

cache.collection = collection;
cache.collections = collections;
cache.collectionsCount = collectionsCount;
cache.collection = collection;
cache.content = content;
},
);
Expand Down
21 changes: 13 additions & 8 deletions src/containers/collection-detail/collection-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ class CollectionContent extends React.Component<
const params = ParamHelper.parseParamString(props.location.search);

this.state = {
collection: null,
collections: [],
collectionsCount: 0,
collection: null,
content: null,
params: params,
params,
};
}

Expand All @@ -35,7 +35,7 @@ class CollectionContent extends React.Component<
}

render() {
const { collections, collectionsCount, collection, params, content } =
const { collection, collections, collectionsCount, content, params } =
this.state;

if (collections.length <= 0) {
Expand Down Expand Up @@ -66,17 +66,17 @@ class CollectionContent extends React.Component<
return (
<React.Fragment>
<CollectionHeader
reload={() => this.loadCollections(true)}
activeTab='contents'
breadcrumbs={breadcrumbs}
collection={collection}
collections={collections}
collectionsCount={collectionsCount}
collection={collection}
content={content}
params={params}
reload={() => this.loadCollections(true)}
updateParams={(params) =>
this.updateParams(params, () => this.loadCollections(true))
}
breadcrumbs={breadcrumbs}
activeTab='contents'
/>
<Main>
<section className='body'>
Expand All @@ -98,7 +98,12 @@ class CollectionContent extends React.Component<
matchParams: this.props.routeParams,
navigate: this.props.navigate,
setCollection: (collections, collection, content, collectionsCount) =>
this.setState({ collections, collection, content, collectionsCount }),
this.setState({
collections,
collection,
content,
collectionsCount,
}),
stateParams: this.state.params,
});
}
Expand Down
Loading

0 comments on commit 62cbfa6

Please sign in to comment.