diff --git a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/resources/splunk/appserver/templates/base.html b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/resources/splunk/appserver/templates/base.html index 7c7416c72..ccef1a696 100644 --- a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/resources/splunk/appserver/templates/base.html +++ b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/resources/splunk/appserver/templates/base.html @@ -13,7 +13,7 @@ - + diff --git a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/ControlWrapper.jsx b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/ControlWrapper.jsx index 95705ce0b..981a13401 100644 --- a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/ControlWrapper.jsx +++ b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/ControlWrapper.jsx @@ -7,12 +7,16 @@ import CONTROL_TYPE_MAP from '../constants/ControlTypeMap'; const CustomElement = styled.div` margin-left: 30px; + div { - width: 100% !important; + width:100% !important } `; const ControlGroupWrapper = styled(ControlGroup)` + width: 100%; + max-width: 100%; + > * { &:first-child { width: 170px !important; diff --git a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/CustomCell.jsx b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/CustomCell.jsx new file mode 100644 index 000000000..370ea5cdc --- /dev/null +++ b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/CustomCell.jsx @@ -0,0 +1,74 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; + +import { getUnifiedConfigs } from '../util/util'; + +class CustomCell extends Component { + constructor(props) { + super(props); + this.state = { + loading: true, + }; + this.shouldRender = true; + } + + componentDidMount() { + const globalConfig = getUnifiedConfigs(); + this.setState({ loading: true }); + this.loadCustomControl().then((Control) => { + const customControl = new Control( + this.el, + this.props.field, + this.props.row, + this.props.serviceName, + globalConfig + ); + customControl.render(); + this.setState({ loading: false }); + }); + } + + shouldComponentUpdate(nextProps, nextState) { + if (!nextState.loading && this.shouldRender) { + this.shouldRender = false; + return true; + } + return false; + } + + loadCustomControl = () => { + const globalConfig = getUnifiedConfigs(); + const appName = globalConfig.meta.name; + return new Promise((resolve) => { + __non_webpack_require__( + [`app/${appName}/js/build/custom/${this.props.fileName}`], + (Control) => resolve(Control) + ); + }); + }; + + render() { + return ( + <> + {this.state.loading && 'Loading...'} + { + { + this.el = el; + }} + style={{ visibility: this.state.loading ? 'hidden' : 'visible' }} + /> + } + + ); + } +} + +CustomCell.propTypes = { + serviceName: PropTypes.string.isRequired, + row: PropTypes.object.isRequired, + field: PropTypes.string.isRequired, + fileName: PropTypes.string.isRequired, +}; + +export default CustomCell; diff --git a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/CustomTable.jsx b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/CustomTable.jsx index 6d4de4f91..74ea9f075 100644 --- a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/CustomTable.jsx +++ b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/CustomTable.jsx @@ -11,17 +11,25 @@ import PropTypes from 'prop-types'; import WaitSpinner from '@splunk/react-ui/WaitSpinner'; import { MODE_CLONE, MODE_EDIT } from '../../constants/modes'; -import { getUnifiedConfigs } from '../../util/util'; import { ActionButtonComponent } from './CustomTableStyle'; +import { getUnifiedConfigs } from '../../util/util'; import { getExpansionRow } from './TableExpansionRow'; import EntityModal from '../EntityModal'; import DeleteModal from '../DeleteModal'; +import CustomCell from '../CustomCell'; -function CustomTable({ page, serviceName, data, handleToggleActionClick }) { +function CustomTable({ + page, + serviceName, + data, + handleToggleActionClick, + handleSort, + sortDir, + sortKey, +}) { const [entityModal, setEntityModal] = useState({ open: false }); const [deleteModal, setDeleteModal] = useState({ open: false }); - const [sortKey, setSortKey] = useState('name'); - const [sortDir, setSortDir] = useState('asc'); + const unifiedConfigs = getUnifiedConfigs(); const tableConfig = page === 'inputs' @@ -100,14 +108,6 @@ function CustomTable({ page, serviceName, data, handleToggleActionClick }) { const columns = generateColumns(); - const handleSort = (e, val) => { - const prevSortKey = sortKey; - const prevSortDir = prevSortKey === val.sortKey ? sortDir : 'none'; - const nextSortDir = prevSortDir === 'asc' ? 'desc' : 'asc'; - setSortDir(nextSortDir); - setSortKey(val.sortKey); - }; - const getTableHeaders = () => { return ( @@ -188,6 +188,15 @@ function CustomTable({ page, serviceName, data, handleToggleActionClick }) { ); }; + const getCustomCell = (row, header) => { + return React.createElement(CustomCell, { + serviceName: row.serviceName, + field: row.name, + row, + fileName: header.customCell.src, + }); + }; + const getTableRow = (row) => { let statusContent = ''; // eslint-disable-next-line no-underscore-dangle @@ -200,6 +209,7 @@ function CustomTable({ page, serviceName, data, handleToggleActionClick }) { } else { statusContent = ; } + return ( { - if (header.field === 'disabled') { - return ( + let cellHTML = ''; + + if (header.customCell && header.customCell.src) { + cellHTML = ( + + {getCustomCell(row, header)} + + ); + } else if (header.field === 'disabled') { + cellHTML = ( ); + } else if (header.field === 'actions') { + cellHTML = rowActionsPrimaryButton(row); + } else { + cellHTML = ( + {row[header.field]} + ); } - - if (header.field === 'actions') { - return rowActionsPrimaryButton(row); - } - - return {row[header.field]}; + return cellHTML; })} ); @@ -251,21 +270,7 @@ function CustomTable({ page, serviceName, data, handleToggleActionClick }) { const getTableBody = () => { return ( - - {data && - data.length && - data - .sort((rowA, rowB) => { - if (sortDir === 'asc') { - return rowA[sortKey] > rowB[sortKey] ? 1 : -1; - } - if (sortDir === 'desc') { - return rowB[sortKey] > rowA[sortKey] ? 1 : -1; - } - return 0; - }) - .map((row) => getTableRow(row))} - + {data && data.length && data.map((row) => getTableRow(row))} ); }; @@ -288,6 +293,9 @@ CustomTable.propTypes = { serviceName: PropTypes.string.isRequired, data: PropTypes.array.isRequired, handleToggleActionClick: PropTypes.func, + handleSort: PropTypes.func, + sortDir: PropTypes.string, + sortKey: PropTypes.string, }; export default memo(CustomTable); diff --git a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/CustomTableStyle.jsx b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/CustomTableStyle.jsx index aadf05fc0..cb9eebb2b 100644 --- a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/CustomTableStyle.jsx +++ b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/CustomTableStyle.jsx @@ -19,7 +19,7 @@ export const TableCaptionComponent = styled.div` export const TableSelectBoxWrapper = styled.span` button { - margin-left: 30%; + margin-left: 80px; min-width: 100px; } `; diff --git a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/TableWrapper.jsx b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/TableWrapper.jsx index 07200a347..aacfd7828 100644 --- a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/TableWrapper.jsx +++ b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/components/table/TableWrapper.jsx @@ -3,16 +3,17 @@ import update from 'immutability-helper'; import axios from 'axios'; import PropTypes from 'prop-types'; -import { _ } from '@splunk/ui-utils/i18n'; - -import CustomTable from './CustomTable'; import { WaitSpinnerWrapper } from './CustomTableStyle'; -import { getUnifiedConfigs, generateToast } from '../../util/util'; -import TableContext from '../../context/TableContext'; import { axiosCallWrapper } from '../../util/axiosCallWrapper'; +import { getUnifiedConfigs, generateToast } from '../../util/util'; +import CustomTable from './CustomTable'; import TableHeader from './TableHeader'; +import TableContext from '../../context/TableContext'; function TableWrapper({ page, serviceName, handleRequestModalOpen }) { + + const [sortKey, setSortKey] = useState('name'); + const [sortDir, setSortDir] = useState('asc'); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -136,6 +137,14 @@ function TableWrapper({ page, serviceName, handleRequestModalOpen }) { }); }; + const handleSort = (e, val) => { + const prevSortKey = sortKey; + const prevSortDir = prevSortKey === val.sortKey ? sortDir : 'none'; + const nextSortDir = prevSortDir === 'asc' ? 'desc' : 'asc'; + setSortDir(nextSortDir); + setSortKey(val.sortKey); + }; + /** * * @param {Array} data @@ -176,12 +185,25 @@ function TableWrapper({ page, serviceName, handleRequestModalOpen }) { } else { arr = findByMatchingValue(rowData[searchType]); } - return [arr.slice(currentPage * pageSize, (currentPage + 1) * pageSize), arr.length]; + + // Sort the array based on the sort value + const sortedArr = arr.sort((rowA, rowB) => { + if (sortDir === 'asc') { + return rowA[sortKey] > rowB[sortKey] ? 1 : -1; + } + if (sortDir === 'desc') { + return rowB[sortKey] > rowA[sortKey] ? 1 : -1; + } + return 0; + }); + + return [sortedArr.slice(currentPage * pageSize, (currentPage + 1) * pageSize), arr.length]; }; if (error?.uccErrorCode) { throw error; } + if (loading) { return ; } @@ -201,6 +223,9 @@ function TableWrapper({ page, serviceName, handleRequestModalOpen }) { serviceName={serviceName} data={filteredData} handleToggleActionClick={(row) => changeToggleStatus(row)} + handleSort={handleSort} + sortDir={sortDir} + sortKey={sortKey} /> ); diff --git a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/pages/Input/InputPageStyle.jsx b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/pages/Input/InputPageStyle.jsx index aa84bb58e..7cf1f6f57 100644 --- a/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/pages/Input/InputPageStyle.jsx +++ b/splunk_add_on_ucc_framework/ucc_ui_lib/src/main/webapp/pages/Input/InputPageStyle.jsx @@ -3,12 +3,12 @@ import { variables } from '@splunk/themes'; export const TitleComponent = styled.div` font-size: ${variables.fontSizeXXLarge}; - margin-bottom: "20px"; + margin-bottom: 20px; `; export const SubTitleComponent = styled.div` font-size: ${variables.fontSize}; - margin-bottom: "10px"; + margin-bottom: 10px; `; export const TableCaptionComponent = styled.div`