From 08c37572112df667020b2aa065bbed33fdba1966 Mon Sep 17 00:00:00 2001 From: rohanm-crest Date: Tue, 11 Jun 2024 13:03:10 +0530 Subject: [PATCH] ADDON-70909: added condition to render custom row compoonent --- .../components/table/CustomTableControl.jsx | 162 ++++++++++++++---- ui/src/components/table/TableExpansionRow.jsx | 4 +- 2 files changed, 131 insertions(+), 35 deletions(-) diff --git a/ui/src/components/table/CustomTableControl.jsx b/ui/src/components/table/CustomTableControl.jsx index 149adf40d..385769aa0 100644 --- a/ui/src/components/table/CustomTableControl.jsx +++ b/ui/src/components/table/CustomTableControl.jsx @@ -1,9 +1,13 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import DL from '@splunk/react-ui/DefinitionList'; import { _ } from '@splunk/ui-utils/i18n'; +import ExclamationTriangle from '@splunk/react-icons/ExclamationTriangle'; import { getUnifiedConfigs } from '../../util/util'; import { getBuildDirPath } from '../../util/script'; +// eslint-disable-next-line import/no-cycle +import { getExpansionRowData } from './TableExpansionRow'; function onCustomControlError(params) { // eslint-disable-next-line no-console @@ -17,23 +21,64 @@ class CustomTableControl extends Component { super(props); this.state = { loading: true, + row: { ...props.row }, + checkMethodIsPresent: false, + methodNotPresentError: '', }; this.shouldRender = true; } componentDidMount() { const globalConfig = getUnifiedConfigs(); - this.setState({ loading: true }); - this.loadCustomControl().then((Control) => { - this.customControl = new Control( - globalConfig, - this.props.serviceName, - this.el, - this.props.row, - this.props.field + this.loadCustomControl() + .then((Control) => { + if (typeof Control === 'function') { + this.customControl = new Control( + globalConfig, + this.props.serviceName, + this.el, + this.state.row, + this.props.field + ); + + this.callCustomMethod('getDLRows') + .then((result) => { + // check if getDLRow is exist in the custom input row file + if (result && typeof result === 'object' && !Array.isArray(result)) { + this.setState({ + row: { ...result }, + checkMethodIsPresent: true, + loading: false, + }); + } else if (result !== null) { + // check if getDLRow return invalid object + this.setState({ + loading: false, + methodNotPresentError: + 'getDLRows method did not return a valid object', + }); + } else { + // if getDLRow is not present then check render method is present or not + this.handleNoGetDLRows(); + } + }) + .catch((error) => { + onCustomControlError({ methodName: 'getDLRows', error }); + this.handleNoGetDLRows(); + }); + } else { + this.setState({ + loading: false, + methodNotPresentError: 'Loaded module is not a constructor function', + }); + } + }) + .catch(() => + this.setState({ + loading: false, + methodNotPresentError: 'Error loading custom control', + }) ); - this.setState({ loading: false }); - }); } shouldComponentUpdate(nextProps, nextState) { @@ -48,45 +93,93 @@ class CustomTableControl extends Component { } loadCustomControl = () => - new Promise((resolve) => { - if (this.props.type === 'external') { - import( - /* webpackIgnore: true */ `${getBuildDirPath()}/custom/${ - this.props.fileName - }.js` - ).then((external) => { - const Control = external.default; - resolve(Control); - }); + new Promise((resolve, reject) => { + const { type, fileName } = this.props; + const globalConfig = getUnifiedConfigs(); + + if (type === 'external') { + import(/* webpackIgnore: true */ `${getBuildDirPath()}/custom/${fileName}.js`) + .then((external) => resolve(external.default)) + .catch((error) => reject(error)); } else { - const globalConfig = getUnifiedConfigs(); const appName = globalConfig.meta.name; __non_webpack_require__( - [`app/${appName}/js/build/custom/${this.props.fileName}`], - (Control) => resolve(Control) + [`app/${appName}/js/build/custom/${fileName}`], + (Control) => resolve(Control), + (error) => reject(error) ); } }); + callCustomMethod = async (methodName, ...args) => { + try { + if (typeof this.customControl[methodName] === 'function') { + return this.customControl[methodName](...args); + } + return null; + } catch (error) { + onCustomControlError({ methodName, error }); + return null; + } + }; + + handleNoGetDLRows = () => { + if (!this.customControl || typeof this.customControl.render !== 'function') { + this.setState((prevState) => ({ + ...prevState, + methodNotPresentError: + 'At least "render" either "getDLRows" method should be present.', + })); + } + this.setState((prevState) => ({ + ...prevState, + loading: false, + })); + }; + render() { - if (!this.state.loading) { + const { row, loading, checkMethodIsPresent, methodNotPresentError } = this.state; + const { moreInfo } = this.props; + + if ( + !loading && + !checkMethodIsPresent && + this.customControl && + typeof this.customControl.render === 'function' + ) { try { - this.customControl.render(this.props.row, this.props.field); + this.customControl.render(row, moreInfo); } catch (error) { onCustomControlError({ methodName: 'render', error }); } } + + let content; + + if (methodNotPresentError) { + content = ( + + + {methodNotPresentError} + + ); + } else if (checkMethodIsPresent) { + content =
{getExpansionRowData(row, moreInfo)}
; + } else { + content = ( + { + this.el = el; + }} + style={{ visibility: loading ? 'hidden' : 'visible' }} + /> + ); + } + return ( <> - {this.state.loading && _('Loading...')} - { - { - this.el = el; - }} - style={{ visibility: this.state.loading ? 'hidden' : 'visible' }} - /> - } + {loading && _('Loading...')} + {content} ); } @@ -98,6 +191,7 @@ CustomTableControl.propTypes = { field: PropTypes.string, fileName: PropTypes.string.isRequired, type: PropTypes.string, + moreInfo: PropTypes.array.isRequired, }; export default CustomTableControl; diff --git a/ui/src/components/table/TableExpansionRow.jsx b/ui/src/components/table/TableExpansionRow.jsx index 0e401e4fd..4f0582984 100644 --- a/ui/src/components/table/TableExpansionRow.jsx +++ b/ui/src/components/table/TableExpansionRow.jsx @@ -4,6 +4,7 @@ import Table from '@splunk/react-ui/Table'; import styled from 'styled-components'; import { _ } from '@splunk/ui-utils/i18n'; +// eslint-disable-next-line import/no-cycle import CustomTableControl from './CustomTableControl'; import { getUnifiedConfigs } from '../../util/util'; @@ -11,7 +12,7 @@ const TableCellWrapper = styled(Table.Cell)` border-top: none; `; -function getExpansionRowData(row, moreInfo) { +export function getExpansionRowData(row, moreInfo) { const DefinitionLists = []; if (moreInfo?.length) { @@ -50,6 +51,7 @@ export function getExpansionRow(colSpan, row, moreInfo) { row, fileName: customRow.src, type: customRow.type, + moreInfo, })} ) : (