From 1e337b82ec3c4e9ea9411c75fe70b56ce71ac7cf Mon Sep 17 00:00:00 2001 From: Amir Fefer Date: Thu, 13 Jan 2022 20:53:38 +0200 Subject: [PATCH] Fixes #34260 - add rex features dropdown to host page --- jsconfig.json | 8 ++ package.json | 13 ++-- webpack/global_index.js | 2 + .../components/FeaturesDropdown/actions.js | 13 ++++ .../components/FeaturesDropdown/constant.js | 2 + .../components/FeaturesDropdown/index.js | 73 +++++++++++++++++++ .../RecentJobsCard/RecentJobsCard.js | 7 +- .../RecentJobsCard/RecentJobsTable.js | 4 +- .../components/RecentJobsCard/constants.js | 1 + .../extend/fillRexFeaturesDropdown.js | 11 +++ 10 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 jsconfig.json create mode 100644 webpack/react_app/components/FeaturesDropdown/actions.js create mode 100644 webpack/react_app/components/FeaturesDropdown/constant.js create mode 100644 webpack/react_app/components/FeaturesDropdown/index.js create mode 100644 webpack/react_app/extend/fillRexFeaturesDropdown.js diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 000000000..eb206bd6d --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es6", + "paths": { + "foremanReact/*": ["../foreman/webpack/assets/javascripts/react_app/*"] + } + } +} diff --git a/package.json b/package.json index 019ca42f9..c42bedf30 100644 --- a/package.json +++ b/package.json @@ -21,20 +21,19 @@ }, "devDependencies": { "@babel/core": "^7.7.0", - "@theforeman/builder": "^8.16.0", - "@theforeman/eslint-plugin-foreman": "^8.16.0", - "@theforeman/stories": "^8.16.0", - "@theforeman/test": "^8.16.0", - "@theforeman/vendor-dev": "^8.16.0", + "@theforeman/builder": "^10.1.0", + "@theforeman/eslint-plugin-foreman": "^10.1.0", + "@theforeman/stories": "^10.1.0", + "@theforeman/test": "^10.1.0", + "@theforeman/vendor-dev": "^10.1.0", "babel-eslint": "^10.0.0", "eslint": "^6.8.0", "prettier": "^1.19.1", - "@patternfly/react-catalog-view-extension": "^4.8.126", "redux-mock-store": "^1.2.2", "graphql-tag": "^2.11.0", "graphql": "^15.5.0" }, "peerDependencies": { - "@theforeman/vendor": "^8.16.0" + "@theforeman/vendor": "^10.1.0" } } diff --git a/webpack/global_index.js b/webpack/global_index.js index 1cd88d8e8..ba5efda2f 100644 --- a/webpack/global_index.js +++ b/webpack/global_index.js @@ -2,9 +2,11 @@ import { registerRoutes } from 'foremanReact/routes/RoutingService'; import routes from './Routes/routes'; import fillregistrationAdvanced from './react_app/extend/fillregistrationAdvanced'; import fillRecentJobsCard from './react_app/extend/fillRecentJobsCard'; +import fillFeaturesDropdown from './react_app/extend/fillRexFeaturesDropdown'; import registerReducers from './react_app/extend/reducers'; registerReducers(); registerRoutes('foreman_remote_execution', routes); +fillFeaturesDropdown(); fillRecentJobsCard(); fillregistrationAdvanced(); diff --git a/webpack/react_app/components/FeaturesDropdown/actions.js b/webpack/react_app/components/FeaturesDropdown/actions.js new file mode 100644 index 000000000..a61e14ec5 --- /dev/null +++ b/webpack/react_app/components/FeaturesDropdown/actions.js @@ -0,0 +1,13 @@ +import { foremanUrl } from 'foremanReact/common/helpers'; +import { sprintf, translate as __ } from 'foremanReact/common/I18n'; +import { post } from 'foremanReact/redux/API'; + +export const runFeature = (hostId, feature, label) => dispatch => { + const url = foremanUrl( + `/job_invocations?feature=${feature}&host_ids%5B%5D=${hostId}` + ); + + const successToast = () => sprintf(__('%s job has been invoked'), label); + const errorToast = ({ message }) => message; + dispatch(post({ key: feature.toUpperCase(), url, successToast, errorToast })); +}; diff --git a/webpack/react_app/components/FeaturesDropdown/constant.js b/webpack/react_app/components/FeaturesDropdown/constant.js new file mode 100644 index 000000000..4ba1a916d --- /dev/null +++ b/webpack/react_app/components/FeaturesDropdown/constant.js @@ -0,0 +1,2 @@ +export const REX_FEATURES_API = '/api/remote_execution_features'; +export const NEW_JOB_PAGE = '/job_invocations/new?host_ids%5B%5D'; diff --git a/webpack/react_app/components/FeaturesDropdown/index.js b/webpack/react_app/components/FeaturesDropdown/index.js new file mode 100644 index 000000000..1be16db88 --- /dev/null +++ b/webpack/react_app/components/FeaturesDropdown/index.js @@ -0,0 +1,73 @@ +import PropTypes from 'prop-types'; +import React, { useState } from 'react'; +import { useDispatch } from 'react-redux'; +import { + DropdownItem, + Dropdown, + DropdownToggle, + DropdownToggleAction, +} from '@patternfly/react-core'; +import { push } from 'connected-react-router'; + +import { useAPI } from 'foremanReact/common/hooks/API/APIHooks'; +import { translate as __ } from 'foremanReact/common/I18n'; +import { foremanUrl } from 'foremanReact/common/helpers'; +import { STATUS } from 'foremanReact/constants'; + +import { REX_FEATURES_API, NEW_JOB_PAGE } from './constant'; +import { runFeature } from './actions'; + +const FeaturesDropdown = ({ hostId }) => { + const [isOpen, setIsOpen] = useState(false); + const { + response: { results: features }, + status, + } = useAPI('get', foremanUrl(REX_FEATURES_API)); + const dispatch = useDispatch(); + const dropdownItems = features + ?.filter(feature => feature.host_action_button) + ?.map(({ name, label, id, description }) => ( + dispatch(runFeature(hostId, label, name))} + key={id} + description={description} + > + {name} + + )); + const scheduleJob = [ + dispatch(push(`${NEW_JOB_PAGE}=${hostId}`))} + key="schedule-job-action" + > + {__('Schedule a job')} + , + ]; + + return ( + setIsOpen(false)} + toggle={ + setIsOpen(prev => !prev)} + isDisabled={status === STATUS.PENDING} + splitButtonVariant="action" + /> + } + isOpen={isOpen} + dropdownItems={dropdownItems} + /> + ); +}; + +FeaturesDropdown.propTypes = { + hostId: PropTypes.string, +}; +FeaturesDropdown.defaultProps = { + hostId: undefined, +}; + +export default FeaturesDropdown; diff --git a/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js b/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js index 6a11cbad7..6bb8b4d86 100644 --- a/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +++ b/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js @@ -52,7 +52,12 @@ const RecentJobsCard = ({ hostDetails: { name, id } }) => { , ]} > - + {__('Finished')}} diff --git a/webpack/react_app/components/RecentJobsCard/RecentJobsTable.js b/webpack/react_app/components/RecentJobsCard/RecentJobsTable.js index f8be49d4a..ec98c9114 100644 --- a/webpack/react_app/components/RecentJobsCard/RecentJobsTable.js +++ b/webpack/react_app/components/RecentJobsCard/RecentJobsTable.js @@ -19,7 +19,7 @@ import { translate as __ } from 'foremanReact/common/I18n'; import { foremanUrl } from 'foremanReact/common/helpers'; import JobStatusIcon from './JobStatusIcon'; -import { JOB_API_URL, JOBS_IN_CARD } from './constants'; +import { JOB_API_URL, JOBS_IN_CARD, RECENT_JOBS_KEY } from './constants'; const RecentJobsTable = ({ status, hostId }) => { const jobsUrl = @@ -30,7 +30,7 @@ const RecentJobsTable = ({ status, hostId }) => { const { response: { results: jobs }, status: responseStatus, - } = useAPI('get', jobsUrl); + } = useAPI('get', jobsUrl, RECENT_JOBS_KEY); return ( diff --git a/webpack/react_app/components/RecentJobsCard/constants.js b/webpack/react_app/components/RecentJobsCard/constants.js index e9a9279e4..b30178e44 100644 --- a/webpack/react_app/components/RecentJobsCard/constants.js +++ b/webpack/react_app/components/RecentJobsCard/constants.js @@ -10,3 +10,4 @@ export const JOB_BASE_URL = '/job_invocations?search=host+%3D+'; export const JOB_API_URL = '/api/job_invocations?order=start_at+DESC&search=targeted_host_id%3D'; export const JOBS_IN_CARD = 3; +export const RECENT_JOBS_KEY = { key: 'RECENT_JOBS_KEY' }; diff --git a/webpack/react_app/extend/fillRexFeaturesDropdown.js b/webpack/react_app/extend/fillRexFeaturesDropdown.js new file mode 100644 index 000000000..f62305ce1 --- /dev/null +++ b/webpack/react_app/extend/fillRexFeaturesDropdown.js @@ -0,0 +1,11 @@ +import React from 'react'; +import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill'; +import FeaturesDropdown from '../components/FeaturesDropdown'; + +export default () => + addGlobalFill( + '_rex-host-features', + '_rex-host-features', + , + 1000 + );