From d29280099e845e809071e51a03249f52093d9474 Mon Sep 17 00:00:00 2001 From: Martin Hradil Date: Wed, 21 Jun 2023 01:59:38 +0000 Subject: [PATCH] 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) --- src/api/collection.ts | 6 +++ src/api/response-types/collection.ts | 2 + src/components/headers/collection-header.tsx | 48 ++++++++++------- src/components/shared/download-count.tsx | 15 ++++-- src/containers/collection-detail/base.ts | 44 ++++++++++++---- .../collection-detail/collection-content.tsx | 40 +++++++++++---- .../collection-dependencies.tsx | 39 +++++++++----- .../collection-detail/collection-detail.tsx | 32 ++++++++---- .../collection-distributions.tsx | 30 +++++++---- .../collection-detail/collection-docs.tsx | 51 +++++++++++-------- .../collection-import-log.tsx | 41 ++++++++++----- 11 files changed, 239 insertions(+), 109 deletions(-) diff --git a/src/api/collection.ts b/src/api/collection.ts index cccb5e65af..34fe33caa5 100644 --- a/src/api/collection.ts +++ b/src/api/collection.ts @@ -232,6 +232,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(); diff --git a/src/api/response-types/collection.ts b/src/api/response-types/collection.ts index df70785052..3dbe5096d7 100644 --- a/src/api/response-types/collection.ts +++ b/src/api/response-types/collection.ts @@ -222,6 +222,8 @@ export class CollectionDetailType { company: string; related_fields: { my_permissions?: string[] }; }; + + download_count: number; } export class CollectionUsedByDependencies extends CollectionDetailType { diff --git a/src/components/headers/collection-header.tsx b/src/components/headers/collection-header.tsx index 9a80dad77d..7415575449 100644 --- a/src/components/headers/collection-header.tsx +++ b/src/components/headers/collection-header.tsx @@ -21,6 +21,7 @@ import { Navigate } from 'react-router-dom'; import { CertificateUploadAPI, CollectionAPI, + CollectionDetailType, CollectionVersionAPI, CollectionVersionContentType, CollectionVersionSearch, @@ -37,6 +38,7 @@ import { Breadcrumbs, CopyCollectionToRepositoryModal, DeleteCollectionModal, + DownloadCount, ImportModal, LinkTabs, Logo, @@ -68,6 +70,7 @@ interface IProps { collections: CollectionVersionSearch[]; collectionsCount: number; collection: CollectionVersionSearch; + actuallyCollection: CollectionDetailType; content: CollectionVersionContentType; params: { version?: string; @@ -164,15 +167,16 @@ export class CollectionHeader extends React.Component { render() { const { + activeTab, + actuallyCollection, + breadcrumbs, + className, + collection, collections, collectionsCount, - collection, content, params, updateParams, - breadcrumbs, - activeTab, - className, } = this.props; const { @@ -545,20 +549,28 @@ export class CollectionHeader extends React.Component { } pageControls={ - - {DEPLOYMENT_MODE === Constants.INSIGHTS_DEPLOYMENT_MODE ? ( - - - {t`Create issue`} - {' '} - - - ) : null} - {dropdownItems.length > 0 ? ( - - - - ) : null} + + + {DEPLOYMENT_MODE === Constants.INSIGHTS_DEPLOYMENT_MODE ? ( + + + {t`Create issue`} + {' '} + + + ) : null} + {dropdownItems.length > 0 ? ( + + + + ) : null} + + + + } > diff --git a/src/components/shared/download-count.tsx b/src/components/shared/download-count.tsx index f33d44d1f0..1b1f537415 100644 --- a/src/components/shared/download-count.tsx +++ b/src/components/shared/download-count.tsx @@ -1,13 +1,18 @@ -import { Trans } from '@lingui/macro'; +import { Trans, t } from '@lingui/macro'; import { DownloadIcon } from '@patternfly/react-icons'; import React from 'react'; +import { Tooltip } from 'src/components'; +import { Constants } from 'src/constants'; import { language } from 'src/l10n'; interface IProps { item?: { download_count?: number }; } -export const DownloadCount = ({ item }) => { +export const DownloadCount = ({ item }: IProps) => { + if (DEPLOYMENT_MODE === Constants.INSIGHTS_DEPLOYMENT_MODE) { + return null; + } if (!item?.download_count) { return null; } @@ -17,8 +22,10 @@ export const DownloadCount = ({ item }) => { ); return ( - <> + {downloadCount} Downloads - + ); }; diff --git a/src/containers/collection-detail/base.ts b/src/containers/collection-detail/base.ts index 412d1d5b35..a5a8dd243f 100644 --- a/src/containers/collection-detail/base.ts +++ b/src/containers/collection-detail/base.ts @@ -1,5 +1,6 @@ import { CollectionAPI, + CollectionDetailType, CollectionVersionAPI, CollectionVersionContentType, CollectionVersionSearch, @@ -8,17 +9,18 @@ import { AlertType } from 'src/components'; import { Paths, formatPath } from 'src/paths'; export interface IBaseCollectionState { + actuallyCollection?: CollectionDetailType; + 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 @@ -28,9 +30,10 @@ const cache = { name: null, version: null, + actuallyCollection: null, + collection: null, collections: [], collectionsCount: 0, - collection: null, content: null, }; @@ -57,6 +60,7 @@ export function loadCollection({ cache.collection, cache.content, cache.collectionsCount, + cache.actuallyCollection, ); return; } @@ -94,7 +98,19 @@ export function loadCollection({ .then(({ data }) => data) .catch(() => ({ data: [], meta: { count: 0 } })); - return Promise.all([versions, currentVersion, content]).then( + // FIXME: repo -> base_path + const actuallyCollection = CollectionAPI.getDetail( + repo, + namespace, + name, + ).then(({ data }) => data); + + return Promise.all([ + versions, + currentVersion, + content, + actuallyCollection, + ]).then( ([ { data: collections, @@ -102,17 +118,25 @@ export function loadCollection({ }, collection, content, + actuallyCollection, ]) => { - setCollection(collections, collection, content, collectionsCount); + setCollection( + collections, + collection, + content, + collectionsCount, + actuallyCollection, + ); cache.repository = repo; cache.namespace = namespace; cache.name = name; cache.version = version; + cache.actuallyCollection = actuallyCollection; + cache.collection = collection; cache.collections = collections; cache.collectionsCount = collectionsCount; - cache.collection = collection; cache.content = content; }, ); diff --git a/src/containers/collection-detail/collection-content.tsx b/src/containers/collection-detail/collection-content.tsx index b29c39c46d..c9e24de97a 100644 --- a/src/containers/collection-detail/collection-content.tsx +++ b/src/containers/collection-detail/collection-content.tsx @@ -23,11 +23,12 @@ class CollectionContent extends React.Component< const params = ParamHelper.parseParamString(props.location.search); this.state = { + actuallyCollection: null, + collection: null, collections: [], collectionsCount: 0, - collection: null, content: null, - params: params, + params, }; } @@ -36,8 +37,14 @@ class CollectionContent extends React.Component< } render() { - const { collections, collectionsCount, collection, params, content } = - this.state; + const { + actuallyCollection, + collection, + collections, + collectionsCount, + content, + params, + } = this.state; if (collections.length <= 0) { return ; @@ -67,17 +74,18 @@ class CollectionContent extends React.Component< return ( this.loadCollections(true)} + activeTab='contents' + actuallyCollection={actuallyCollection} + 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' />
@@ -98,8 +106,20 @@ class CollectionContent extends React.Component< forceReload, matchParams: this.props.routeParams, navigate: this.props.navigate, - setCollection: (collections, collection, content, collectionsCount) => - this.setState({ collections, collection, content, collectionsCount }), + setCollection: ( + collections, + collection, + content, + collectionsCount, + actuallyCollection, + ) => + this.setState({ + collections, + collection, + content, + collectionsCount, + actuallyCollection, + }), stateParams: this.state.params, }); } diff --git a/src/containers/collection-detail/collection-dependencies.tsx b/src/containers/collection-detail/collection-dependencies.tsx index 83f0cdcff6..0c851d003e 100644 --- a/src/containers/collection-detail/collection-dependencies.tsx +++ b/src/containers/collection-detail/collection-dependencies.tsx @@ -52,16 +52,17 @@ class CollectionDependencies extends React.Component { params['sort'] = !params['sort'] ? '-collection' : 'collection'; this.state = { + actuallyCollection: null, + alerts: [], + collection: null, collections: [], collectionsCount: 0, - collection: null, content: null, dependencies_repos: [], - params: params, + params, usedByDependencies: [], usedByDependenciesCount: 0, usedByDependenciesLoading: true, - alerts: [], }; } @@ -71,15 +72,16 @@ class CollectionDependencies extends React.Component { render() { const { + actuallyCollection, + alerts, + collection, collections, collectionsCount, - collection, content, params, usedByDependencies, usedByDependenciesCount, usedByDependenciesLoading, - alerts, } = this.state; if (collections.length <= 0) { @@ -117,20 +119,21 @@ class CollectionDependencies extends React.Component { this.closeAlert(i)} /> this.loadData(true)} + activeTab='dependencies' + actuallyCollection={actuallyCollection} + breadcrumbs={breadcrumbs} + collection={collection} collections={collections} collectionsCount={collectionsCount} - collection={collection} content={content} params={headerParams} + reload={() => this.loadData(true)} + repo={repository.name} updateParams={(p) => { this.updateParams(this.combineParams(this.state.params, p), () => this.loadData(true), ); }} - breadcrumbs={breadcrumbs} - activeTab='dependencies' - repo={repository.name} />
@@ -291,9 +294,21 @@ class CollectionDependencies extends React.Component { forceReload, matchParams: this.props.routeParams, navigate: this.props.navigate, - setCollection: (collections, collection, content, collectionsCount) => + setCollection: ( + collections, + collection, + content, + collectionsCount, + actuallyCollection, + ) => this.setState( - { collections, collection, content, collectionsCount }, + { + collections, + collection, + content, + collectionsCount, + actuallyCollection, + }, callback, ), stateParams: this.state.params.version diff --git a/src/containers/collection-detail/collection-detail.tsx b/src/containers/collection-detail/collection-detail.tsx index f787834ecf..31f68522f7 100644 --- a/src/containers/collection-detail/collection-detail.tsx +++ b/src/containers/collection-detail/collection-detail.tsx @@ -25,13 +25,14 @@ class CollectionDetail extends React.Component< const params = ParamHelper.parseParamString(props.location.search); this.state = { + actuallyCollection: null, + alerts: [], + collection: null, collections: [], collectionsCount: 0, - collection: null, content: null, distroBasePath: null, - params: params, - alerts: [], + params, }; } @@ -47,12 +48,13 @@ class CollectionDetail extends React.Component< render() { const { + actuallyCollection, + alerts, + collection, collections, collectionsCount, - collection, content, params, - alerts, } = this.state; if (collections.length <= 0) { @@ -78,18 +80,19 @@ class CollectionDetail extends React.Component< this.closeAlert(i)} /> this.loadCollections(true)} + activeTab='install' + actuallyCollection={actuallyCollection} + breadcrumbs={breadcrumbs} + collection={collection} collections={collections} collectionsCount={collectionsCount} - collection={collection} content={content} params={params} + reload={() => this.loadCollections(true)} + repo={this.props.routeParams.repo} updateParams={(p) => this.updateParams(p, () => this.loadCollections(true)) } - breadcrumbs={breadcrumbs} - activeTab='install' - repo={this.props.routeParams.repo} />
@@ -122,12 +125,19 @@ class CollectionDetail extends React.Component< forceReload, matchParams: this.props.routeParams, navigate: this.props.navigate, - setCollection: (collections, collection, content, collectionsCount) => + setCollection: ( + collections, + collection, + content, + collectionsCount, + actuallyCollection, + ) => this.setState({ collections, collection, content, collectionsCount, + actuallyCollection, }), stateParams: this.state.params, }); diff --git a/src/containers/collection-detail/collection-distributions.tsx b/src/containers/collection-detail/collection-distributions.tsx index bd7e1d19cb..8e8520c94a 100644 --- a/src/containers/collection-detail/collection-distributions.tsx +++ b/src/containers/collection-detail/collection-distributions.tsx @@ -29,16 +29,15 @@ import { loadCollection } from './base'; const CollectionDistributions = (props: RouteProps) => { const routeParams = ParamHelper.parseParamString(props.location.search); + const [actuallyCollection, setActuallyCollection] = useState(null); + const [collection, setCollection] = useState(null); const [collections, setCollections] = useState([]); const [collectionsCount, setCollectionsCount] = useState(0); - const [collection, setCollection] = useState(null); const [content, setContent] = useState(null); - const [inputText, setInputText] = useState(''); - - const [distributions, setDistributions] = useState(null); const [count, setCount] = useState(0); + const [distributions, setDistributions] = useState(null); + const [inputText, setInputText] = useState(''); const [loading, setLoading] = useState(true); - const [params, setParams] = useState( Object.keys(routeParams).length ? routeParams @@ -46,15 +45,23 @@ const CollectionDistributions = (props: RouteProps) => { sort: '-pulp_created', }, ); + const loadCollections = (forceReload) => { loadCollection({ forceReload, matchParams: props.routeParams, navigate: props.navigate, - setCollection: (collections, collection, content, collectionsCount) => { + setCollection: ( + collections, + collection, + content, + collectionsCount, + actuallyCollection, + ) => { + setActuallyCollection(actuallyCollection); + setCollection(collection); setCollections(collections); setCollectionsCount(collectionsCount); - setCollection(collection); setContent(content); loadDistributions(collection.repository.pulp_href); @@ -201,19 +208,20 @@ const CollectionDistributions = (props: RouteProps) => { return ( loadCollections(true)} + activeTab='distributions' + actuallyCollection={actuallyCollection} + breadcrumbs={breadcrumbs} + collection={collection} collections={collections} collectionsCount={collectionsCount} - collection={collection} content={content} params={params} + reload={() => loadCollections(true)} updateParams={(params) => { updateParamsMixin( ParamHelper.setParam(params, 'version', params.version), ); }} - breadcrumbs={breadcrumbs} - activeTab='distributions' />
diff --git a/src/containers/collection-detail/collection-docs.tsx b/src/containers/collection-detail/collection-docs.tsx index 6fb36e6dc0..549e0bc113 100644 --- a/src/containers/collection-detail/collection-docs.tsx +++ b/src/containers/collection-detail/collection-docs.tsx @@ -33,11 +33,12 @@ class CollectionDocs extends React.Component { const params = ParamHelper.parseParamString(props.location.search); this.state = { + actuallyCollection: null, + collection: null, collections: [], collectionsCount: 0, - collection: null, content: null, - params: params, + params, }; this.docsRef = React.createRef(); this.searchBarRef = React.createRef(); @@ -48,8 +49,14 @@ class CollectionDocs extends React.Component { } render() { - const { params, collection, collections, collectionsCount, content } = - this.state; + const { + actuallyCollection, + collection, + collections, + collectionsCount, + content, + params, + } = this.state; const urlFields = this.props.routeParams; if (!collection || !content) { @@ -117,30 +124,22 @@ class CollectionDocs extends React.Component { { name: t`Documentation` }, ]; - // scroll to top of page - - // if ( - // this.docsRef.current && - // this.searchBarRef.current !== window.document.activeElement - // ) { - // this.docsRef.current.scrollIntoView(); - // } - return ( this.loadCollection(true)} + activeTab='documentation' + actuallyCollection={actuallyCollection} + breadcrumbs={breadcrumbs} + className='header' + collection={collection} collections={collections} collectionsCount={collectionsCount} - collection={collection} content={content} params={params} + reload={() => this.loadCollection(true)} updateParams={(p) => this.updateParams(p, () => this.loadCollection(true)) } - breadcrumbs={breadcrumbs} - activeTab='documentation' - className='header' />
@@ -305,8 +304,20 @@ class CollectionDocs extends React.Component { forceReload, matchParams: this.props.routeParams, navigate: this.props.navigate, - setCollection: (collections, collection, content, collectionsCount) => - this.setState({ collections, collection, content, collectionsCount }), + setCollection: ( + collections, + collection, + content, + collectionsCount, + actuallyCollection, + ) => + this.setState({ + collections, + collection, + content, + collectionsCount, + actuallyCollection, + }), stateParams: this.state.params, }); } diff --git a/src/containers/collection-detail/collection-import-log.tsx b/src/containers/collection-detail/collection-import-log.tsx index 0a9abe8ae6..5a81fa990f 100644 --- a/src/containers/collection-detail/collection-import-log.tsx +++ b/src/containers/collection-detail/collection-import-log.tsx @@ -27,15 +27,16 @@ class CollectionImportLog extends React.Component { const params = ParamHelper.parseParamString(props.location.search); this.state = { + actuallyCollection: null, + apiError: undefined, collection: null, collections: [], collectionsCount: 0, content: null, - params: params, loadingImports: true, - selectedImportDetail: undefined, + params, selectedImport: undefined, - apiError: undefined, + selectedImportDetail: undefined, }; } @@ -45,15 +46,16 @@ class CollectionImportLog extends React.Component { render() { const { + actuallyCollection, + apiError, collection, collections, collectionsCount, - params, + content, loadingImports, - selectedImportDetail, + params, selectedImport, - apiError, - content, + selectedImportDetail, } = this.state; if (!collection) { @@ -84,17 +86,18 @@ class CollectionImportLog extends React.Component { return ( this.loadData(true)} + activeTab='import-log' + actuallyCollection={actuallyCollection} + breadcrumbs={breadcrumbs} + collection={collection} collections={collections} collectionsCount={collectionsCount} - collection={collection} content={content} params={params} + reload={() => this.loadData(true)} updateParams={(params) => this.updateParams(params, () => this.loadData(true)) } - breadcrumbs={breadcrumbs} - activeTab='import-log' />
@@ -157,9 +160,21 @@ class CollectionImportLog extends React.Component { forceReload, matchParams: this.props.routeParams, navigate: this.props.navigate, - setCollection: (collections, collection, content, collectionsCount) => + setCollection: ( + collections, + collection, + content, + collectionsCount, + actuallyCollection, + ) => this.setState( - { collections, collection, content, collectionsCount }, + { + collections, + collection, + content, + collectionsCount, + actuallyCollection, + }, callback, ), stateParams: this.state.params,