Skip to content

Commit

Permalink
feat: Added custom cell feature in the table and fixed sorting issue
Browse files Browse the repository at this point in the history
  • Loading branch information
tbalar-splunk committed Mar 23, 2021
1 parent 05f29f7 commit 3711846
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<link rel="apple-touch-icon" href="apple-touch-icon.png">
</head>

<body>
<body style="min-width:960px">
<script src="${make_url('/config?autoload=1')}" crossorigin="use-credentials"></script>
<script src="${make_url('/static/js/i18n.js')}"></script>
<script src="${make_url('/i18ncatalog?autoload=1')}"></script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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...'}
{
<span
ref={(el) => {
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;
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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 (
<Table.Head>
Expand Down Expand Up @@ -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
Expand All @@ -200,6 +209,7 @@ function CustomTable({ page, serviceName, data, handleToggleActionClick }) {
} else {
statusContent = <WaitSpinner />;
}

return (
<Table.Row
key={row.id}
Expand All @@ -210,8 +220,16 @@ function CustomTable({ page, serviceName, data, handleToggleActionClick }) {
{columns &&
columns.length &&
columns.map((header) => {
if (header.field === 'disabled') {
return (
let cellHTML = '';

if (header.customCell && header.customCell.src) {
cellHTML = (
<Table.Cell key={header.field}>
{getCustomCell(row, header)}
</Table.Cell>
);
} else if (header.field === 'disabled') {
cellHTML = (
<Table.Cell key={header.field}>
<Switch
key={row.name}
Expand All @@ -237,35 +255,22 @@ function CustomTable({ page, serviceName, data, handleToggleActionClick }) {
</Switch>
</Table.Cell>
);
} else if (header.field === 'actions') {
cellHTML = rowActionsPrimaryButton(row);
} else {
cellHTML = (
<Table.Cell key={header.field}>{row[header.field]}</Table.Cell>
);
}

if (header.field === 'actions') {
return rowActionsPrimaryButton(row);
}

return <Table.Cell key={header.field}>{row[header.field]}</Table.Cell>;
return cellHTML;
})}
</Table.Row>
);
};

const getTableBody = () => {
return (
<Table.Body>
{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))}
</Table.Body>
<Table.Body>{data && data.length && data.map((row) => getTableRow(row))}</Table.Body>
);
};

Expand All @@ -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);
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const TableCaptionComponent = styled.div`

export const TableSelectBoxWrapper = styled.span`
button {
margin-left: 30%;
margin-left: 80px;
min-width: 100px;
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 <WaitSpinnerWrapper size="large" />;
}
Expand All @@ -201,6 +223,9 @@ function TableWrapper({ page, serviceName, handleRequestModalOpen }) {
serviceName={serviceName}
data={filteredData}
handleToggleActionClick={(row) => changeToggleStatus(row)}
handleSort={handleSort}
sortDir={sortDir}
sortKey={sortKey}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down

0 comments on commit 3711846

Please sign in to comment.