From f4871aab8049377a204be3f68e66c7fdad186cf9 Mon Sep 17 00:00:00 2001 From: Samir Jha Date: Mon, 18 Sep 2023 15:51:22 +0000 Subject: [PATCH] Fixes #36758 - Add content counts to capsule content view UI (cherry picked from commit ad08dadbc2fd9a20750be8032ce97d6cb1ec2f6c) --- .../concerns/smart_proxy_extensions.rb | 2 +- .../v2/capsule_content/sync_status.json.rabl | 16 +++- webpack/scenes/Content/ContentConfig.js | 3 + .../SmartProxy/AdditionalCapsuleContent.js | 80 +++++++++++++++++++ .../scenes/SmartProxy/ExpandableCvDetails.js | 60 +++++++++----- .../ExpandedSmartProxyRepositories.js | 62 ++++++++++++++ .../SmartProxy/SmartProxyExpandableTable.js | 6 +- 7 files changed, 202 insertions(+), 27 deletions(-) create mode 100644 webpack/scenes/SmartProxy/AdditionalCapsuleContent.js create mode 100644 webpack/scenes/SmartProxy/ExpandedSmartProxyRepositories.js diff --git a/app/models/katello/concerns/smart_proxy_extensions.rb b/app/models/katello/concerns/smart_proxy_extensions.rb index b01d46fd54c..e92ad099df0 100644 --- a/app/models/katello/concerns/smart_proxy_extensions.rb +++ b/app/models/katello/concerns/smart_proxy_extensions.rb @@ -146,7 +146,7 @@ def update_content_counts! end end new_content_counts[:content_view_versions][repo.content_view_version_id] ||= { repositories: {}, cv_version_content_counts: {}} - new_content_counts[:content_view_versions][repo.content_view_version_id][:repositories][repo.id] = translated_counts + new_content_counts[:content_view_versions][repo.content_view_version_id][:repositories][repo.content_view_version.archived_repos.find_by(library_instance_id: repo.library_instance_id)&.id] = translated_counts new_content_counts = aggregated_cv_version_count!(repo.content_view_version_id, new_content_counts, translated_counts) end update(content_counts: new_content_counts) diff --git a/app/views/katello/api/v2/capsule_content/sync_status.json.rabl b/app/views/katello/api/v2/capsule_content/sync_status.json.rabl index e499e14b328..631f3841532 100644 --- a/app/views/katello/api/v2/capsule_content/sync_status.json.rabl +++ b/app/views/katello/api/v2/capsule_content/sync_status.json.rabl @@ -27,7 +27,8 @@ child @lifecycle_environments => :lifecycle_environments do if @capsule.has_feature?(SmartProxy::PULP_NODE_FEATURE) || @capsule.has_feature?(SmartProxy::PULP3_FEATURE) node :counts do |env| { - :content_views => env.content_views.non_default.count + :content_views => env.content_views.non_default.count, + :content_counts => @capsule.content_counts } end @@ -35,6 +36,7 @@ child @lifecycle_environments => :lifecycle_environments do env.content_views.ignore_generated.map do |content_view| attributes = { :id => content_view.id, + :cvv_id => ::Katello::ContentViewVersion.in_environment(env).find_by(:content_view => content_view)&.id, :label => content_view.label, :name => content_view.name, :composite => content_view.composite, @@ -42,9 +44,15 @@ child @lifecycle_environments => :lifecycle_environments do :default => content_view.default, :up_to_date => @capsule.repos_pending_sync(env, content_view).empty?, :counts => { - :repositories => ::Katello::ContentViewVersion.in_environment(env).find_by(:content_view => content_view)&.archived_repos&.count - }, - :content_counts => @capsule.content_counts + :repositories => ::Katello::ContentViewVersion.in_environment(env).find_by(:content_view => content_view)&.archived_repos&.count + }, + :repositories => ::Katello::ContentViewVersion.in_environment(env)&.find_by(:content_view => content_view)&.archived_repos&.map do |repo| + { + :id => repo.id, + :name => repo.name, + :library_id => repo.library_instance_id + } + end } attributes end diff --git a/webpack/scenes/Content/ContentConfig.js b/webpack/scenes/Content/ContentConfig.js index b7dfb1e6d4a..3ef957d8050 100644 --- a/webpack/scenes/Content/ContentConfig.js +++ b/webpack/scenes/Content/ContentConfig.js @@ -16,6 +16,7 @@ export default [ singularLowercase: __('Python package'), pluralLabel: 'python_packages', singularLabel: 'python_package', + capsuleCountLabel: 'python_package', }, columnHeaders: [ { title: __('Name'), getProperty: unit => ({unit?.name}) }, @@ -81,6 +82,7 @@ export default [ singularLowercase: __('OSTree ref'), pluralLabel: 'ostree_refs', singularLabel: 'ostree_ref', + capsuleCountLabel: 'ostree.refs', }, columnHeaders: [ { title: __('Name'), getProperty: unit => ({unit?.name}) }, @@ -142,6 +144,7 @@ export default [ singularLowercase: __('Ansible collection'), pluralLabel: 'ansible_collections', singularLabel: 'ansible_collection', + capsuleCountLabel: 'ansible.collection_version', }, columnHeaders: [ { title: __('Name'), getProperty: unit => ({unit?.name}) }, diff --git a/webpack/scenes/SmartProxy/AdditionalCapsuleContent.js b/webpack/scenes/SmartProxy/AdditionalCapsuleContent.js new file mode 100644 index 00000000000..5857b5bfda2 --- /dev/null +++ b/webpack/scenes/SmartProxy/AdditionalCapsuleContent.js @@ -0,0 +1,80 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { translate as __ } from 'foremanReact/common/I18n'; +import ContentConfig from '../Content/ContentConfig'; + +const AdditionalCapsuleContent = ({ counts }) => { + //console.log(counts); + const { + 'deb.package': debPackageCount = 0, + docker_manifest: dockerManifestCount = 0, + docker_tag: dockerTagCount = 0, + file: fileCount = 0, + erratum: errataCount = 0, + package_group: packageGroup = 0, + 'rpm.modulemd': moduleStreamCount = 0, + } = counts; + + const contentConfigTypes = ContentConfig.filter(({ names: { capsuleCountLabel } }) => + !!counts[`${capsuleCountLabel}`]) + .map(({ + names: { + capsuleCountLabel, pluralLowercase, + }, + }) => { + const countParam = `${capsuleCountLabel}`; + const count = counts[countParam]; + return { + pluralLowercase, + count, + }; + }); + //console.log(contentConfigTypes); + + return ( + <> + {errataCount > 0 && + <> + {`${errataCount} Errata`}
+ + } + {moduleStreamCount > 0 && + <> + {`${moduleStreamCount} Module streams`}
+ + } + {packageGroup > 0 && + <> + {`${packageGroup} Package groups`}
+ + } + {dockerTagCount > 0 && + <> + {`${dockerTagCount} Container tags`}
+ + } + {dockerManifestCount > 0 && + <> + {`${dockerManifestCount} Container manifests`}
+ + } + {fileCount > 0 && + <> + {`${fileCount} Files`}
+ + } + {debPackageCount > 0 && + <> + {`${debPackageCount} Debian packages`}
+ } + {contentConfigTypes?.length > 0 && + contentConfigTypes.map(({ count, pluralLowercase }) => ( + + {`${count} ${pluralLowercase}`}
+
)) + } + + ); +}; + +export default AdditionalCapsuleContent; diff --git a/webpack/scenes/SmartProxy/ExpandableCvDetails.js b/webpack/scenes/SmartProxy/ExpandableCvDetails.js index 273a68ebc05..25ef77f23e3 100644 --- a/webpack/scenes/SmartProxy/ExpandableCvDetails.js +++ b/webpack/scenes/SmartProxy/ExpandableCvDetails.js @@ -1,31 +1,36 @@ import React from 'react'; import PropTypes from 'prop-types'; import { translate as __ } from 'foremanReact/common/I18n'; -import { TableComposable, Thead, Tr, Th, Tbody, Td, TableVariant } from '@patternfly/react-table'; +import { TableComposable, Thead, Tr, Th, Tbody, Td, TableVariant, ExpandableRowContent } from '@patternfly/react-table'; import { CheckCircleIcon, TimesCircleIcon } from '@patternfly/react-icons'; import LongDateTime from 'foremanReact/components/common/dates/LongDateTime'; import { urlBuilder } from 'foremanReact/common/urlHelpers'; import ContentViewIcon from '../ContentViews/components/ContentViewIcon'; +import AdditionalCapsuleContent from './AdditionalCapsuleContent'; +import {useSet} from "../../components/Table/TableHooks"; +import ExpandedSmartProxyRepositories from "./ExpandedSmartProxyRepositories"; -const ExpandableCvDetails = ({ contentViews }) => { +const ExpandableCvDetails = ({ contentViews, counts }) => { const columnHeaders = [ __('Content view'), __('Last published'), - __('Repositories'), __('Synced to smart proxy'), ]; + const { content_counts: contentCounts } = counts; + //console.log(contentCounts); + const expandedTableRows = useSet([]); + const tableRowIsExpanded = id => expandedTableRows.has(id); return ( + {columnHeaders.map(col => ( {col} @@ -33,28 +38,43 @@ const ExpandableCvDetails = ({ contentViews }) => { ))} - - {contentViews.map((cv) => { + {contentViews.map((cv, rowIndex) => { const { - id, name: cvName, composite, up_to_date: upToDate, counts, + id, name: cvName, composite, up_to_date: upToDate, counts, cvv_id: version, repositories } = cv; - const { repositories } = counts; + const { repositories: repositoryCount } = counts; + //console.log(contentCounts.content_view_versions[version]); + const upToDateVal = upToDate ? : ; + const isExpanded = tableRowIsExpanded(version); return ( - - - {cvName}} + + + expandedTableRows.onToggle(isOpen, version), + }} /> - - - {repositories} - {upToDateVal} - + + {cvName}} + /> + + + {upToDateVal} + + + + + + + ); })} - + ); diff --git a/webpack/scenes/SmartProxy/ExpandedSmartProxyRepositories.js b/webpack/scenes/SmartProxy/ExpandedSmartProxyRepositories.js new file mode 100644 index 00000000000..4fa959f047b --- /dev/null +++ b/webpack/scenes/SmartProxy/ExpandedSmartProxyRepositories.js @@ -0,0 +1,62 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { translate as __ } from 'foremanReact/common/I18n'; +import {DataList, DataListItem, DataListItemRow, DataListItemCells, DataListCell} from '@patternfly/react-core'; +import { CheckCircleIcon, TimesCircleIcon } from '@patternfly/react-icons'; +import LongDateTime from 'foremanReact/components/common/dates/LongDateTime'; +import { urlBuilder } from 'foremanReact/common/urlHelpers'; +import ContentViewIcon from '../ContentViews/components/ContentViewIcon'; +import AdditionalCapsuleContent from './AdditionalCapsuleContent'; +import {useSet} from "../../components/Table/TableHooks"; + +const ExpandedSmartProxyRepositories = ({ contentCounts, repositories }) => { + const getRepositoryNameById = (id) => { + console.log("repos", repositories, typeof repositories); + console.log("id", id, typeof id); + console.log((repositories.find(repo => repo.id == id))); + console.log((repositories[id] || {}).name); + return (repositories.find(repo => repo.id == id) || {}).name; + }; + + const dataListCellLists = (repo) => { + var cellList= []; + //console.log("contentCounts",contentCounts, typeof contentCounts); + //console.log("repositories", repositories); + cellList.push({getRepositoryNameById(repo)}) + cellList.push({contentCounts[repo].rpm ? contentCounts[repo].rpm + " Packages" : "N/A"}) + cellList.push() + return cellList; + } + return ( + + + + + {__('Repositories')} + , + {__('Packages')}, + {__('Additional Content')} + ]} /> + + + {Object.keys(contentCounts).map((repo) => ( + + + + + + ))} + + ); +}; + +ExpandedSmartProxyRepositories.propTypes = { + contentViews: PropTypes.arrayOf(PropTypes.shape({})), +}; + +ExpandedSmartProxyRepositories.defaultProps = { + contentViews: [], +}; + +export default ExpandedSmartProxyRepositories; diff --git a/webpack/scenes/SmartProxy/SmartProxyExpandableTable.js b/webpack/scenes/SmartProxy/SmartProxyExpandableTable.js index 313aa5a329c..e90663acf60 100644 --- a/webpack/scenes/SmartProxy/SmartProxyExpandableTable.js +++ b/webpack/scenes/SmartProxy/SmartProxyExpandableTable.js @@ -71,7 +71,9 @@ const SmartProxyExpandableTable = ({ smartProxyId }) => { { results?.map((env, rowIndex) => { - const { name, id, content_views: contentViews } = env; + const { + name, id, content_views: contentViews, counts, + } = env; const isExpanded = tableRowIsExpanded(id); return ( @@ -88,7 +90,7 @@ const SmartProxyExpandableTable = ({ smartProxyId }) => { - +