Skip to content

Commit

Permalink
Fixes #37861 - Update web UI for multi-CV activation key display
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremylenz committed Sep 27, 2024
1 parent c87ef0f commit 3a39a4b
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 106 deletions.
24 changes: 24 additions & 0 deletions app/views/katello/api/v2/activation_keys/base.json.rabl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@ node :multi_content_view_environment do |ak|
ak.multi_content_view_environment?
end

child :content_view_environments => :content_view_environments do
node :content_view do |cve|
{
id: cve.content_view&.id,
name: cve.content_view&.name,
composite: cve.content_view&.composite,
content_view_version: cve.content_view_version&.version,
content_view_version_id: cve.content_view_version&.id,
content_view_version_latest: cve.content_view_version&.latest?,
content_view_default: cve.content_view&.default?
}
end
node :lifecycle_environment do |cve|
{
id: cve.lifecycle_environment&.id,
name: cve.lifecycle_environment&.name,
lifecycle_environment_library: cve.lifecycle_environment&.library?
}
end
node :candlepin_name do |cve|
cve.candlepin_name
end
end

# single cv/lce for backward compatibility
node :content_view_id do |ak|
ak.single_content_view&.id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<div bst-alert="warning" ng-if="activationKey.multi_content_view_environment">
<span translate>
This activation key has multiple content view environments, which are not yet displayed in the web UI. Changing the content view or lifecycle environment here will overwrite the activation key's multiple environments. To avoid this, update the activation key via Hammer.
This activation key has multiple content view environments, which cannot yet be edited in the web UI. To change this key's content view environments, update the activation key via Hammer.
</span>
</div>

Expand Down Expand Up @@ -57,7 +57,6 @@ <h4 translate>Basic Information</h4>
</div>
</dd>


<div class="divider"></div>
<h4 translate>System Purpose</h4>

Expand Down Expand Up @@ -123,17 +122,18 @@ <h4 translate>Activation Key Content</h4>
on-delete="clearReleaseVersion()"
on-save="save(activationKey)">
</dd>

</dl>
<dl class="dl-horizontal dl-horizontal-left" ng-if="!activationKey.multi_content_view_environment">
<dt bst-feature-flag="lifecycle_environments">
<span translate>Environment</span>
</dt>
<dd bst-feature-flag="lifecycle_environments">
<div path-selector="environments"
ng-model="activationKey.environment"
mode="singleSelect"
selection-required="selectionRequired"
disabled="denied('edit_activation_keys', activationKey)"
disable-trigger="disableEnvironmentSelection">
ng-model="activationKey.environment"
mode="singleSelect"
selection-required="selectionRequired"
disabled="denied('edit_activation_keys', activationKey)"
disable-trigger="disableEnvironmentSelection">
</div>
</dd>

Expand All @@ -142,14 +142,14 @@ <h4 translate>Activation Key Content</h4>
</dt>
<dd bst-feature-flag="lifecycle_environments">
<div bst-edit-select="activationKey.content_view.name"
readonly="denied('edit_activation_keys', activationKey) || activationKey.environment === undefined || activationKey.environment === null"
selector="activationKey.content_view.id"
options="contentViews()"
on-cancel="cancelContentViewUpdate()"
on-save="saveContentView(activationKey)"
deletable="activationKey.content_view"
on-delete="resetEnvironment(activationKey)"
edit-trigger="editContentView">
readonly="denied('edit_activation_keys', activationKey) || activationKey.environment === undefined || activationKey.environment === null"
selector="activationKey.content_view.id"
options="contentViews()"
on-cancel="cancelContentViewUpdate()"
on-save="saveContentView(activationKey)"
deletable="activationKey.content_view"
on-delete="resetEnvironment(activationKey)"
edit-trigger="editContentView">
</div>

<div bst-alert="info" ng-show="editEnvironment">
Expand All @@ -160,6 +160,14 @@ <h4 translate>Activation Key Content</h4>
</div>
</dd>
</dl>
<dl class="dl-horizontal dl-horizontal-left">
<span id="ak-cve-details" data-ak-details="{{ activationKey }}" class="hidden"></span>
<foreman-react-component
name="CVEDetailsCard"
data-props=""
ng-if="activationKey.multi_content_view_environment"
></foreman-react-component>
</dl>
</div>
</div>

Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,103 @@ ContentViewEnvironmentDisplay.propTypes = {
}).isRequired,
};

const HostContentViewDetails = ({
export const CVEDetailsBareCard = ({
contentViewEnvironments, hostPermissions, permissions, dropdownItems,
isDropdownOpen, toggleHamburger,
}) => {
const userPermissions = { ...hostPermissions, ...permissions };
const showKebab = hasRequiredPermissions(requiredPermissions, userPermissions);

return (
<Card ouiaId="content-view-details-card">
<CardHeader>
<Flex
alignItems={{ default: 'alignItemsCenter' }}
justifyContent={{ default: 'justifyContentSpaceBetween' }}
style={{ width: '100%' }}
>
<FlexItem>
<Flex
alignItems={{ default: 'alignItemsCenter' }}
justifyContent={{ default: 'justifyContentSpaceBetween' }}
>
<FlexItem>
<CardTitle>
<FormattedMessage
id="cv-card-title"
defaultMessage="{count, plural, =0 {Content view environments} one {Content view environment} other {Content view environments}}"
values={{
count: contentViewEnvironments.length,
}}
/>
</CardTitle>
</FlexItem>
</Flex>
</FlexItem>
{showKebab && dropdownItems && (
<FlexItem>
<Dropdown
toggle={<KebabToggle aria-label="change_content_view_hamburger" onToggle={toggleHamburger} />}
isOpen={isDropdownOpen}
isPlain
ouiaId="change-host-content-view-kebab"
position="right"
dropdownItems={dropdownItems}
/>
</FlexItem>
)}
</Flex>
</CardHeader>
<CardBody>
<Flex direction={{ default: 'column' }}>
{contentViewEnvironments.map(env => (
<ContentViewEnvironmentDisplay
key={`${env.lifecycle_environment.name}-${env.content_view.name}`}
contentView={env.content_view}
lifecycleEnvironment={env.lifecycle_environment}
/>
))}
</Flex>
</CardBody>
</Card>
);
};

CVEDetailsBareCard.propTypes = {
contentViewEnvironments: PropTypes.arrayOf(PropTypes.shape({
content_view: PropTypes.shape({
name: PropTypes.string,
id: PropTypes.number,
composite: PropTypes.bool,
}),
lifecycle_environment: PropTypes.shape({
name: PropTypes.string,
id: PropTypes.number,
}),
})),
hostPermissions: PropTypes.shape({
edit_hosts: PropTypes.bool,
}),
permissions: PropTypes.shape({
view_content_views: PropTypes.bool,
view_lifecycle_environments: PropTypes.bool,
promote_or_remove_content_views_to_environments: PropTypes.bool,
}),
dropdownItems: PropTypes.arrayOf(PropTypes.node),
isDropdownOpen: PropTypes.bool,
toggleHamburger: PropTypes.func,
};

CVEDetailsBareCard.defaultProps = {
contentViewEnvironments: [],
hostPermissions: {},
permissions: {},
dropdownItems: [],
isDropdownOpen: false,
toggleHamburger: () => {},
};

export const ContentViewEnvironmentDetails = ({
contentViewEnvironments, hostId, hostName, orgId, hostEnvId,
hostPermissions, permissions, contentSourceId,
}) => {
Expand Down Expand Up @@ -126,57 +222,14 @@ const HostContentViewDetails = ({

return (
<GridItem rowSpan={1} md={6} lg={4} xl2={3} >
<Card ouiaId="content-view-details-card">
<CardHeader>
<Flex
alignItems={{ default: 'alignItemsCenter' }}
justifyContent={{ default: 'justifyContentSpaceBetween' }}
style={{ width: '100%' }}
>
<FlexItem>
<Flex
alignItems={{ default: 'alignItemsCenter' }}
justifyContent={{ default: 'justifyContentSpaceBetween' }}
>
<FlexItem>
<CardTitle>
<FormattedMessage
id="cv-card-title"
defaultMessage="{count, plural, =0 {Content view environments} one {Content view environment} other {Content view environments}}"
values={{
count: contentViewEnvironments.length,
}}
/>
</CardTitle>
</FlexItem>
</Flex>
</FlexItem>
{showKebab && (
<FlexItem>
<Dropdown
toggle={<KebabToggle aria-label="change_content_view_hamburger" onToggle={toggleHamburger} />}
isOpen={isDropdownOpen}
isPlain
ouiaId="change-host-content-view-kebab"
position="right"
dropdownItems={dropdownItems}
/>
</FlexItem>
)}
</Flex>
</CardHeader>
<CardBody>
<Flex direction={{ default: 'column' }}>
{contentViewEnvironments.map(env => (
<ContentViewEnvironmentDisplay
key={`${env.lifecycle_environment.name}-${env.content_view.name}`}
contentView={env.content_view}
lifecycleEnvironment={env.lifecycle_environment}
/>
))}
</Flex>
</CardBody>
</Card>
<CVEDetailsBareCard
isDropdownOpen={isDropdownOpen}
toggleHamburger={toggleHamburger}
contentViewEnvironments={contentViewEnvironments}
hostPermissions={hostPermissions}
permissions={permissions}
dropdownItems={showKebab ? dropdownItems : []}
/>
{hostId &&
<ChangeHostCVModal
isOpen={isModalOpen}
Expand All @@ -194,7 +247,7 @@ const HostContentViewDetails = ({
);
};

HostContentViewDetails.propTypes = {
ContentViewEnvironmentDetails.propTypes = {
contentViewEnvironments: PropTypes.arrayOf(PropTypes.shape({
content_view: PropTypes.shape({
name: PropTypes.string,
Expand All @@ -221,7 +274,7 @@ HostContentViewDetails.propTypes = {
contentSourceId: PropTypes.number,
};

HostContentViewDetails.defaultProps = {
ContentViewEnvironmentDetails.defaultProps = {
contentViewEnvironments: [],
hostId: null,
hostName: '',
Expand All @@ -232,10 +285,11 @@ HostContentViewDetails.defaultProps = {
contentSourceId: null,
};


const ContentViewDetailsCard = ({ hostDetails }) => {
if (hostIsRegistered({ hostDetails })
&& hostDetails.content_facet_attributes && hostDetails.organization_id) {
return (<HostContentViewDetails
return (<ContentViewEnvironmentDetails
hostId={hostDetails.id}
hostName={hostDetails.name}
contentSourceId={hostDetails.content_facet_attributes.content_source?.id}
Expand All @@ -248,37 +302,6 @@ const ContentViewDetailsCard = ({ hostDetails }) => {
return null;
};

HostContentViewDetails.propTypes = {
contentView: PropTypes.shape({
name: PropTypes.string,
id: PropTypes.number,
composite: PropTypes.bool,
}).isRequired,
hostId: PropTypes.number,
hostName: PropTypes.string,
contentSourceId: PropTypes.number,
orgId: PropTypes.number,
hostEnvId: PropTypes.number,
hostPermissions: PropTypes.shape({
edit_hosts: PropTypes.bool,
}),
permissions: PropTypes.shape({
view_content_views: PropTypes.bool,
view_lifecycle_environments: PropTypes.bool,
promote_or_remove_content_views_to_environments: PropTypes.bool,
}),
};

HostContentViewDetails.defaultProps = {
hostEnvId: null,
hostId: null,
hostName: '',
orgId: null,
contentSourceId: null,
hostPermissions: {},
permissions: {},
};

ContentViewDetailsCard.propTypes = {
hostDetails: PropTypes.shape({
id: PropTypes.number,
Expand Down
15 changes: 11 additions & 4 deletions webpack/global_index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import BulkChangeHostCVModal from './components/extensions/Hosts/BulkActions/Bul
import BulkPackagesWizardModal from './components/extensions/Hosts/BulkActions/BulkPackagesWizard/index.js';
import BulkErrataWizardModal from './components/extensions/Hosts/BulkActions/BulkErrataWizard/index.js';
import ActivationKeysSearch from './components/ActivationKeysSearch';
import { CVEDetailsCard } from './scenes/ActivationKeys/Details/components/CVEDetailsCard.js';

registerReducer('katelloExtends', extendReducer);
registerReducer('katello', rootReducer);
Expand Down Expand Up @@ -102,8 +103,14 @@ registerGetActions({
tableName: 'hosts',
});

componentRegistry.register({
name: 'ActivationKeysSearch',
type: ActivationKeysSearch,
});
componentRegistry.registerMultiple([
{
name: 'ActivationKeysSearch',
type: ActivationKeysSearch,
},
{
name: 'CVEDetailsCard',
type: CVEDetailsCard,
},
]);

Loading

0 comments on commit 3a39a4b

Please sign in to comment.