diff --git a/app/javascript/components/AeInlineMethod/NamespaceSelector.jsx b/app/javascript/components/AeInlineMethod/NamespaceSelector.jsx index 1e47c7f7001..f58f3ffc560 100644 --- a/app/javascript/components/AeInlineMethod/NamespaceSelector.jsx +++ b/app/javascript/components/AeInlineMethod/NamespaceSelector.jsx @@ -1,20 +1,26 @@ import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; import { - TextInput, Select, SelectItem, + TextInput, Select, SelectItem, Loading, } from 'carbon-components-react'; import MiqDataTable from '../miq-data-table'; +import NotificationMessage from '../notification-message'; +import './style.scss'; -const NamespaceSelector = () => { +/** Component to search and select AeMethods. */ +const NamespaceSelector = ({ onSelectMethod }) => { const aeMethodsUrl = '/miq_ae_class/ae_methods'; const aeDomainsUrl = '/miq_ae_class/ae_domains'; const [data, setData] = useState({ + loading: true, domains: [], searchText: undefined, methods: [], selectedDomain: undefined, }); + /** Function to format the method data needed for the data-table list. */ const formatMethods = (methods) => (methods.map((item) => ({ id: item.id.toString(), name: { text: item.name, icon: 'icon node-icon fa-ruby' }, @@ -22,21 +28,22 @@ const NamespaceSelector = () => { code: item.data, }))); + /** Loads the 'domains' and 'methods' from its respective URL's during the component's onLoad event. */ useEffect(() => { Promise.all([ http.get(aeDomainsUrl), http.get(aeMethodsUrl)]) - // eslint-disable-next-line camelcase .then(([{ domains }, { methods }]) => { setData({ ...data, + loading: false, methods: formatMethods(methods), domains, }); }); }, []); - console.log(data); + /** Headers needed for the data-table list. */ const miqHeaders = [ { key: 'name', @@ -48,74 +55,89 @@ const NamespaceSelector = () => { }, ]; - return ( -
- { - const text = event.target.value; - let url = `${aeMethodsUrl}?search=${text}`; - if (data.selectedDomain) { - url = `${url}&domain_id=${data.selectedDomain}`; - } - http.get(url) - .then(({ methods }) => { - setData({ - ...data, - methods: formatMethods(methods), - searchText: text, - }); - }); - }} - /> - { - data.domains && ( - - ) - } + /** Function to return a conditional URL based on the selected filters. */ + const searchUrl = (selectedDomain, text) => { + const queryParams = []; + if (selectedDomain) { + queryParams.push(`domain_id=${selectedDomain}`); + } + if (text) { + queryParams.push(`search=${text}`); + } + const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : ''; + return `${aeMethodsUrl}${queryString}`; + }; + + /** Function to handle search text and drop-down item onchange events. */ + const handleInputChange = (text, selectedDomain) => { + const url = searchUrl(selectedDomain, text); + http.get(url) + .then(({ methods }) => { + setData({ + ...data, + methods: formatMethods(methods), + searchText: text, + selectedDomain, + }); + }); + }; + + /** Function to render the search text. */ + const renderSearchText = () => ( + handleInputChange(event.target.value, data.selectedDomain)} + /> + ); + /** Function to render the domain items in a drop-down list. */ + const renderDomainList = () => ( + + ); + + /** Function to render the contents of the list. */ + const renderContents = () => (data.methods && data.methods.length > 0 + ? ( + onSelectMethod(selectedRow)} + /> + ) + : ); + + return ( +
+
+ {renderSearchText()} + {data.domains && renderDomainList()} +
+
+ { + data.loading + ? + : renderContents() + } +
); }; export default NamespaceSelector; -// NamespaceSelector.propTypes = { -// type: PropTypes.string.isRequired, -// }; +NamespaceSelector.propTypes = { + onSelectMethod: PropTypes.func.isRequired, +}; diff --git a/app/javascript/components/AeInlineMethod/index.jsx b/app/javascript/components/AeInlineMethod/index.jsx index f1cd9b9d09a..0ef4ad55c86 100644 --- a/app/javascript/components/AeInlineMethod/index.jsx +++ b/app/javascript/components/AeInlineMethod/index.jsx @@ -36,7 +36,7 @@ const AeInlineMethod = ({ type }) => {
{renderAddButton()} 0} size="lg" modalHeading={__('Select item')} open={data.isModalOpen} @@ -44,11 +44,7 @@ const AeInlineMethod = ({ type }) => { secondaryButtonText={__('Cancel')} onRequestClose={() => showModal(false)} onRequestSubmit={() => { - console.log('on onRequestSubmit'); - setData({ - ...data, - list: data.list.push(data.selectedNode), - }); + console.log('on onRequestSubmit', data.list); showModal(false); }} onSecondarySubmit={() => { @@ -60,7 +56,15 @@ const AeInlineMethod = ({ type }) => { { data.isModalOpen && ( - + { + data.list.push(method); + setData({ + ...data, + list: [...data.list], + }); + }} + /> ) } diff --git a/app/javascript/components/AeInlineMethod/style.scss b/app/javascript/components/AeInlineMethod/style.scss new file mode 100644 index 00000000000..0e63cf75c3d --- /dev/null +++ b/app/javascript/components/AeInlineMethod/style.scss @@ -0,0 +1,25 @@ +.inline-method-selector { + display: flex; + flex-direction: column; + + .inline-filters { + display: flex; + flex-direction: row; + gap: 10px; + } + + .inline-contents-wrapper { + display: flex; + flex-direction: column; + margin-top: 20px; + + .miq-inline-method-list { + background: #FFF; + margin-top: 0; + } + + .miq-notification-message-container { + margin: 0; + } + } +}