- {children}
-
- );
+ return
{children}
;
}
+Modal.propTypes = {
+ children: PropTypes.any,
+ show: PropTypes.bool
+};
+
export default Modal;
diff --git a/client/src/components/PageSize/PageSize.jsx b/client/src/components/PageSize/PageSize.jsx
index b7a2aec91..49be4520b 100644
--- a/client/src/components/PageSize/PageSize.jsx
+++ b/client/src/components/PageSize/PageSize.jsx
@@ -1,18 +1,14 @@
import React from 'react';
+import PropTypes from 'prop-types';
import './styles.scss';
const PageSize = ({
- pageNumber,
- totalPageNumber,
currentPageSize,
- totalRecords,
ranges = [10, 25, 50, 100, 150, 200],
onChange,
- editPageNumber,
- showTotalPageNumber = true
}) => {
- var pageSizeOptions = [];
- var pageSizeOptionsList = [];
+ let pageSizeOptions = [];
+ let pageSizeOptionsList = [];
ranges.forEach(element => pageSizeOptions[element] = element );
//if server's pageSize does not belong to ranges, it should be added - when the page is loaded for the first
if(!ranges.includes(currentPageSize)){
@@ -24,11 +20,19 @@ const PageSize = ({
return (
Results
-
);
};
+PageSize.propTypes = {
+ ranges: PropTypes.array,
+ currentPageSize: PropTypes.number,
+ onChange: PropTypes.func,
+}
+
export default PageSize;
\ No newline at end of file
diff --git a/client/src/components/Pagination/Pagination.jsx b/client/src/components/Pagination/Pagination.jsx
index 7fedcfec9..2925b0709 100644
--- a/client/src/components/Pagination/Pagination.jsx
+++ b/client/src/components/Pagination/Pagination.jsx
@@ -1,4 +1,5 @@
import React from 'react';
+import PropTypes from 'prop-types';
import './styles.scss';
const Pagination = ({
@@ -14,10 +15,6 @@ const Pagination = ({
editPageNumber = true;
}
- if (totalRecords !== undefined) {
-
- }
-
return (
-
@@ -65,4 +62,14 @@ const Pagination = ({
);
};
+Pagination.propTypes = {
+ pageNumber: PropTypes.number,
+ totalPageNumber: PropTypes.number,
+ totalRecords: PropTypes.number,
+ onChange: PropTypes.func,
+ onSubmit: PropTypes.func,
+ editPageNumber: PropTypes.bool,
+ showTotalPageNumber: PropTypes.bool
+}
+
export default Pagination;
diff --git a/client/src/components/SearchBar/SearchBar.jsx b/client/src/components/SearchBar/SearchBar.jsx
index 65bb356d8..323efae9d 100644
--- a/client/src/components/SearchBar/SearchBar.jsx
+++ b/client/src/components/SearchBar/SearchBar.jsx
@@ -42,10 +42,14 @@ class SearchBar extends Form {
this.setState({ formData: this.setupProps() });
}
- componentDidUpdate(prevProps, prevState) {
+ componentDidUpdate(prevProps) {
const { search, topicListView, keepSearch } = this.props;
- if(search !== prevProps.search || topicListView !== prevProps.topicListView || keepSearch !== prevProps.keepSearch) {
+ if (
+ search !== prevProps.search ||
+ topicListView !== prevProps.topicListView ||
+ keepSearch !== prevProps.keepSearch
+ ) {
this.setupProps();
}
}
@@ -63,7 +67,7 @@ class SearchBar extends Form {
formData['topicListView'] = topicListView;
this.schema['topicListView'] = Joi.string().required();
}
- if(showKeepSearch) {
+ if (showKeepSearch) {
formData['keepSearch'] = this.props.keepSearch;
this.schema['keepSearch'] = Joi.boolean();
}
@@ -156,14 +160,18 @@ class SearchBar extends Form {
Search
- {showKeepSearch && this.props.onKeepSearchChange(event.target.checked)}
- defaultChecked={formData['keepSearch']}
- /> Keep search
- }
+ {showKeepSearch && (
+
+ this.props.onKeepSearchChange(event.target.checked)}
+ defaultChecked={formData['keepSearch']}
+ />{' '}
+ Keep search
+
+ )}
diff --git a/client/src/components/Table/Table.jsx b/client/src/components/Table/Table.jsx
index a6d1f469c..22d5f64b5 100644
--- a/client/src/components/Table/Table.jsx
+++ b/client/src/components/Table/Table.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import * as constants from '../../utils/constants';
import './styles.scss';
import Spinner from '../Spinner';
-import {Link} from 'react-router-dom';
+import { Link } from 'react-router-dom';
class Table extends Component {
state = {
@@ -132,16 +132,23 @@ class Table extends Component {
}
renderRow(row, index) {
- const { actions, columns, extraRow, onExpand, noRowBackgroundChange, onDetails, handleExtraExpand, handleExtraCollapse, reduce } = this.props;
+ const {
+ actions,
+ columns,
+ extraRow,
+ onExpand,
+ noRowBackgroundChange,
+ onDetails,
+ handleExtraExpand,
+ handleExtraCollapse,
+ reduce
+ } = this.props;
const { extraExpanded } = this.state;
let extraRowColCollapsed;
let extraRowColExpanded;
const items = [
-
+
{columns.map((column, colIndex) => {
let extraStyles = [];
if (noRowBackgroundChange) {
@@ -215,11 +222,7 @@ class Table extends Component {
) {
items.push(
-
+ |
{onExpand(row)}
|
@@ -232,29 +235,43 @@ class Table extends Component {
onClick={() => {
if (
!extraExpanded ||
- !JSON.stringify(extraExpanded.find(expanded => expanded.subject ? expanded.subject === row.subject : expanded === row.id)) ||
- !JSON.stringify(extraExpanded.find(expanded => expanded.subject ? expanded.subject === row.subject : expanded === row.id)).length > 0) {
- typeof handleExtraExpand === 'function'
- ? this.setState({ extraExpanded: handleExtraExpand(extraExpanded, row)})
- : this.handleExtraExpand(row);
+ !JSON.stringify(
+ extraExpanded.find(expanded =>
+ expanded.subject ? expanded.subject === row.subject : expanded === row.id
+ )
+ ) ||
+ !JSON.stringify(
+ extraExpanded.find(expanded =>
+ expanded.subject ? expanded.subject === row.subject : expanded === row.id
+ )
+ ).length > 0
+ ) {
+ typeof handleExtraExpand === 'function'
+ ? this.setState({ extraExpanded: handleExtraExpand(extraExpanded, row) })
+ : this.handleExtraExpand(row);
}
}}
key={'row-expanded-' + row.id}
>
-
+ |
{' '}
{extraExpanded &&
- JSON.stringify(extraExpanded.find(expanded => expanded.subject ? expanded.subject === row.subject : expanded === row.id)) &&
- JSON.stringify(extraExpanded.find(expanded => expanded.subject ? expanded.subject === row.subject : expanded === row.id)).length > 0 ? (
+ JSON.stringify(
+ extraExpanded.find(expanded =>
+ expanded.subject ? expanded.subject === row.subject : expanded === row.id
+ )
+ ) &&
+ JSON.stringify(
+ extraExpanded.find(expanded =>
+ expanded.subject ? expanded.subject === row.subject : expanded === row.id
+ )
+ ).length > 0 ? (
{
typeof handleExtraCollapse === 'function'
- ? this.setState({ extraExpanded: handleExtraCollapse(extraExpanded, row)})
- : this.handleExtraCollapse(row);
+ ? this.setState({ extraExpanded: handleExtraCollapse(extraExpanded, row) })
+ : this.handleExtraCollapse(row);
}}
aria-hidden="true"
>
@@ -265,15 +282,31 @@ class Table extends Component {
expanded.subject ? expanded.subject === row.subject : expanded === row.id)) &&
- JSON.stringify(extraExpanded.find(expanded => expanded.subject ? expanded.subject === row.subject : expanded === row.id)).length > 0
+ JSON.stringify(
+ extraExpanded.find(expanded =>
+ expanded.subject ? expanded.subject === row.subject : expanded === row.id
+ )
+ ) &&
+ JSON.stringify(
+ extraExpanded.find(expanded =>
+ expanded.subject ? expanded.subject === row.subject : expanded === row.id
+ )
+ ).length > 0
? ''
: 'collapsed-extra-row'
}
>
{extraExpanded &&
- JSON.stringify(extraExpanded.find(expanded => expanded.subject ? expanded.subject === row.subject : expanded === row.id)) &&
- JSON.stringify(extraExpanded.find(expanded => expanded.subject ? expanded.subject === row.subject : expanded === row.id)).length > 0
+ JSON.stringify(
+ extraExpanded.find(expanded =>
+ expanded.subject ? expanded.subject === row.subject : expanded === row.id
+ )
+ ) &&
+ JSON.stringify(
+ extraExpanded.find(expanded =>
+ expanded.subject ? expanded.subject === row.subject : expanded === row.id
+ )
+ ).length > 0
? extraRowColExpanded
: extraRowColCollapsed}
@@ -286,11 +319,23 @@ class Table extends Component {
}
renderContent(content) {
- return content !== undefined ? content :
+ return content !== undefined ? content : ;
}
renderActions(row) {
- const { actions, onAdd, onDetails, onConfig, onDelete, onEdit, onRestart, onShare, onDownload, onCopy, idCol } = this.props;
+ const {
+ actions,
+ onAdd,
+ onDetails,
+ onConfig,
+ onDelete,
+ onEdit,
+ onRestart,
+ onShare,
+ onDownload,
+ onCopy,
+ idCol
+ } = this.props;
let idColVal = idCol ? row[this.props.idCol] : row.id;
@@ -298,7 +343,8 @@ class Table extends Component {
<>
{actions.find(el => el === constants.TABLE_ADD) && (
- {
onAdd && onAdd();
@@ -310,27 +356,22 @@ class Table extends Component {
)}
{actions.find(el => el === constants.TABLE_DETAILS) && (
|
-
+
|
)}
{actions.find(el => el === constants.TABLE_CONFIG) && (
-
+
|
)}
{actions.find(el => el === constants.TABLE_DELETE) && (
- {
onDelete && onDelete(row);
@@ -342,7 +383,8 @@ class Table extends Component {
)}
{actions.find(el => el === constants.TABLE_EDIT) && (
|
- {
onEdit && onEdit();
@@ -354,7 +396,8 @@ class Table extends Component {
)}
{actions.find(el => el === constants.TABLE_RESTART) && (
|
- {
onRestart && onRestart(row);
@@ -365,53 +408,56 @@ class Table extends Component {
|
)}
{actions.find(el => el === constants.TABLE_COPY) && (
-
- {
- onCopy && onCopy(row);
- }}
+ |
+ {
+ onCopy && onCopy(row);
+ }}
>
- |
+ |
)}
{actions.find(el => el === constants.TABLE_SHARE) && (
-
- {
- onShare && onShare(row);
- }}
+ |
+ {
+ onShare && onShare(row);
+ }}
>
- |
+
)}
{actions.find(el => el === constants.TABLE_DOWNLOAD) && (
-
- {
- onDownload && onDownload(row);
- }}
+ |
+ {
+ onDownload && onDownload(row);
+ }}
>
- |
+
)}
>
);
}
renderLoading() {
- return (
-
-
-
- |
-
- );
+ return (
+
+
+
+ |
+
+ );
}
renderNoContent() {
@@ -445,7 +491,10 @@ class Table extends Component {
colspan() {
const { actions, columns } = this.props;
- return columns.filter(column => !column.extraRow).length + (actions && actions.length ? actions.length : 0)
+ return (
+ columns.filter(column => !column.extraRow).length +
+ (actions && actions.length ? actions.length : 0)
+ );
}
render() {
@@ -470,14 +519,18 @@ class Table extends Component {
if (noStripes) classNames += ' no-stripes';
return (
-
-
- {this.renderHeader()}
-
- {loading? this.renderLoading() : ((data && data.length > 0) ? allItemRows : this.renderNoContent())}
-
-
-
+
+
+ {this.renderHeader()}
+
+ {loading
+ ? this.renderLoading()
+ : data && data.length > 0
+ ? allItemRows
+ : this.renderNoContent()}
+
+
+
);
}
}
@@ -522,6 +575,13 @@ Table.propTypes = {
loading: PropTypes.bool,
history: PropTypes.object,
rowId: PropTypes.func,
+
+ updateData: PropTypes.func,
+ extraRow: PropTypes.bool,
+ noRowBackgroundChange: PropTypes.bool,
+ onExpand: PropTypes.func,
+ reduce: PropTypes.bool,
+ noStripes: PropTypes.bool
};
export default Table;
diff --git a/client/src/containers/Acl/AclDetail/AclClusters/AclClusters.jsx b/client/src/containers/Acl/AclDetail/AclClusters/AclClusters.jsx
index e04e9f685..956113b2e 100644
--- a/client/src/containers/Acl/AclDetail/AclClusters/AclClusters.jsx
+++ b/client/src/containers/Acl/AclDetail/AclClusters/AclClusters.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import Table from '../../../../components/Table/Table';
import { uriAclsByPrincipal } from '../../../../utils/endpoints';
-import Root from "../../../../components/Root";
+import Root from '../../../../components/Root';
class AclClusters extends Root {
state = {
diff --git a/client/src/containers/Acl/AclDetail/AclDetails.jsx b/client/src/containers/Acl/AclDetail/AclDetails.jsx
index c031488bf..6b78f5e01 100644
--- a/client/src/containers/Acl/AclDetail/AclDetails.jsx
+++ b/client/src/containers/Acl/AclDetail/AclDetails.jsx
@@ -1,10 +1,11 @@
import React, { Component } from 'react';
+import PropTypes from 'prop-types';
import Header from '../../Header';
import AclGroups from './AclGroups/AclGroups';
import AclTopics from './AclTopics/AclTopics';
import AclClusters from './AclClusters/AclClusters';
import AclTransactionalIds from './AclTransactionalIds/AclTransactionalIds';
-import {getSelectedTab} from "../../../utils/functions";
+import {getSelectedTab} from '../../../utils/functions';
import { Link } from 'react-router-dom';
class AclDetails extends Component {
@@ -29,7 +30,7 @@ class AclDetails extends Component {
);
}
- componentDidUpdate(prevProps, prevState) {
+ componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
const tabSelected = getSelectedTab(this.props, this.tabs);
this.setState({ selectedTab: tabSelected });
@@ -119,4 +120,11 @@ class AclDetails extends Component {
}
}
+AclDetails.propTypes = {
+ match: PropTypes.object,
+ location: PropTypes.object,
+ history: PropTypes.object,
+
+}
+
export default AclDetails;
diff --git a/client/src/containers/Acl/AclDetail/AclGroups/AclGroups.jsx b/client/src/containers/Acl/AclDetail/AclGroups/AclGroups.jsx
index bb20e34fb..5ca9011f5 100644
--- a/client/src/containers/Acl/AclDetail/AclGroups/AclGroups.jsx
+++ b/client/src/containers/Acl/AclDetail/AclGroups/AclGroups.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import Table from '../../../../components/Table/Table';
import { uriAclsByPrincipal } from '../../../../utils/endpoints';
-import Root from "../../../../components/Root";
+import Root from '../../../../components/Root';
class AclGroups extends Root {
state = {
diff --git a/client/src/containers/Acl/AclDetail/AclTopics/AclTopics.jsx b/client/src/containers/Acl/AclDetail/AclTopics/AclTopics.jsx
index 6abbee8ab..3db677c5e 100644
--- a/client/src/containers/Acl/AclDetail/AclTopics/AclTopics.jsx
+++ b/client/src/containers/Acl/AclDetail/AclTopics/AclTopics.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import Table from '../../../../components/Table/Table';
import { uriAclsByPrincipal } from '../../../../utils/endpoints';
-import Root from "../../../../components/Root";
+import Root from '../../../../components/Root';
class AclTopics extends Root {
state = {
diff --git a/client/src/containers/Acl/AclDetail/AclTransactionalIds/AclTransactionalIds.jsx b/client/src/containers/Acl/AclDetail/AclTransactionalIds/AclTransactionalIds.jsx
index a8a1d0026..68f13dc73 100644
--- a/client/src/containers/Acl/AclDetail/AclTransactionalIds/AclTransactionalIds.jsx
+++ b/client/src/containers/Acl/AclDetail/AclTransactionalIds/AclTransactionalIds.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import Table from '../../../../components/Table/Table';
import { uriAclsByPrincipal } from '../../../../utils/endpoints';
-import Root from "../../../../components/Root";
+import Root from '../../../../components/Root';
class AclTransactionalIds extends Root {
state = {
diff --git a/client/src/containers/Acl/AclList/Acls.jsx b/client/src/containers/Acl/AclList/Acls.jsx
index ee6663180..2637233f7 100644
--- a/client/src/containers/Acl/AclList/Acls.jsx
+++ b/client/src/containers/Acl/AclList/Acls.jsx
@@ -4,7 +4,7 @@ import Table from '../../../components/Table';
import * as constants from '../../../utils/constants';
import { uriAclsList } from '../../../utils/endpoints';
import SearchBar from '../../../components/SearchBar';
-import Root from "../../../components/Root";
+import Root from '../../../components/Root';
class Acls extends Root {
state = {
@@ -18,12 +18,18 @@ class Acls extends Root {
componentDidMount() {
const { searchData } = this.state;
- const query = new URLSearchParams(this.props.location.search);
+ const query = new URLSearchParams(this.props.location.search);
const { clusterId } = this.props.match.params;
- this.setState({ selectedCluster: clusterId, searchData: { search: (query.get('search'))? query.get('search') : searchData.search }}, () => {
- this.getAcls();
- });
+ this.setState(
+ {
+ selectedCluster: clusterId,
+ searchData: { search: query.get('search') ? query.get('search') : searchData.search }
+ },
+ () => {
+ this.getAcls();
+ }
+ );
}
async getAcls() {
@@ -99,8 +105,8 @@ class Acls extends Root {
- No ACLS found, or the "authorizer.class.name" parameter is not configured on the
- cluster.
+ No ACLS found, or the "authorizer.class.name" parameter is not
+ configured on the cluster.
|
diff --git a/client/src/containers/Connect/ConnectCreate/ConnectCreate.jsx b/client/src/containers/Connect/ConnectCreate/ConnectCreate.jsx
index b5eb62aa5..0df39e572 100644
--- a/client/src/containers/Connect/ConnectCreate/ConnectCreate.jsx
+++ b/client/src/containers/Connect/ConnectCreate/ConnectCreate.jsx
@@ -13,7 +13,7 @@ import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/theme-merbivore_soft';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
-import Root from "../../../components/Root";
+import Root from '../../../components/Root';
class ConnectCreate extends Root {
state = {
@@ -243,7 +243,7 @@ class ConnectCreate extends Root {
handleGroup(group) {
let { formData } = this.state;
let groupDisplay = [
-
+
{group[0].group} |
];
diff --git a/client/src/containers/Connect/ConnectDetail/Connect.jsx b/client/src/containers/Connect/ConnectDetail/Connect.jsx
index c5ff156e9..56178fa4c 100644
--- a/client/src/containers/Connect/ConnectDetail/Connect.jsx
+++ b/client/src/containers/Connect/ConnectDetail/Connect.jsx
@@ -1,9 +1,10 @@
import React, { Component } from 'react';
+import PropTypes from 'prop-types';
import Header from '../../Header/Header';
import ConnectTasks from './ConnectTasks/ConnectTasks';
import ConnectConfigs from './ConnectConfigs/ConnectConfigs';
-import {getSelectedTab} from "../../../utils/functions";
-import {Link} from "react-router-dom";
+import { getSelectedTab } from '../../../utils/functions';
+import { Link } from 'react-router-dom';
class Connect extends Component {
state = {
@@ -18,13 +19,14 @@ class Connect extends Component {
componentDidMount() {
const { clusterId, connectId, definitionId } = this.props.match.params;
const tabSelected = getSelectedTab(this.props, this.tabs);
- this.setState({ selectedTab: (tabSelected)? tabSelected : 'tasks' },
- () => {
- this.props.history.replace(`/ui/${clusterId}/connect/${connectId}/definition/${definitionId}/${this.state.selectedTab}`);
- });
+ this.setState({ selectedTab: tabSelected ? tabSelected : 'tasks' }, () => {
+ this.props.history.replace(
+ `/ui/${clusterId}/connect/${connectId}/definition/${definitionId}/${this.state.selectedTab}`
+ );
+ });
}
- componentDidUpdate(prevProps, prevState) {
+ componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
const tabSelected = getSelectedTab(this.props, this.tabs);
this.setState({ selectedTab: tabSelected });
@@ -83,14 +85,16 @@ class Connect extends Component {
-
-
Tasks
-
-
Configs
@@ -109,4 +113,10 @@ class Connect extends Component {
}
}
+Connect.propTypes = {
+ history: PropTypes.object,
+ location: PropTypes.object,
+ match: PropTypes.object
+};
+
export default Connect;
diff --git a/client/src/containers/Connect/ConnectDetail/ConnectConfigs/ConnectConfigs.jsx b/client/src/containers/Connect/ConnectDetail/ConnectConfigs/ConnectConfigs.jsx
index 7c332ca59..7c8d53ffe 100644
--- a/client/src/containers/Connect/ConnectDetail/ConnectConfigs/ConnectConfigs.jsx
+++ b/client/src/containers/Connect/ConnectDetail/ConnectConfigs/ConnectConfigs.jsx
@@ -85,14 +85,14 @@ class ConnectConfigs extends Form {
getTransformAdditionalProperties() {
const { configs } = this.state;
- const filtered = Object.keys(configs).filter(configKey => configKey.startsWith('transforms.'))
- .reduce((obj, configKey) => {
- obj[configKey] = configs[configKey];
- return obj;
- }, {});
+ const filtered = Object.keys(configs)
+ .filter(configKey => configKey.startsWith('transforms.'))
+ .reduce((obj, configKey) => {
+ obj[configKey] = configs[configKey];
+ return obj;
+ }, {});
return JSON.stringify(filtered, null, 2);
- };
-
+ }
handleDefinition = definition => {
let def = '';
@@ -201,7 +201,11 @@ class ConnectConfigs extends Form {
className="form-control"
value={formData[plugin.name]}
name={plugin.name}
- disabled={plugin.name === 'name' || plugin.name === 'connector.class' || !(roles.connect && roles.connect['connect/update']) }
+ disabled={
+ plugin.name === 'name' ||
+ plugin.name === 'connector.class' ||
+ !(roles.connect && roles.connect['connect/update'])
+ }
placeholder={plugin.defaultValue > 0 ? plugin.defaultValue : ''}
onChange={({ currentTarget: input }) => {
let { formData } = this.state;
@@ -254,7 +258,7 @@ class ConnectConfigs extends Form {
handleGroup(group) {
let { formData } = this.state;
let groupDisplay = [
-
+
{group[0].group} |
];
@@ -363,7 +367,7 @@ class ConnectConfigs extends Form {
await this.postApi(uriUpdateDefinition(clusterId, connectId, definitionId), body);
history.push({
- pathname: `/ui/${clusterId}/connect/${connectId}`,
+ pathname: `/ui/${clusterId}/connect/${connectId}`
});
toast.success(`${`Definition '${formData.name}' is updated`}`);
diff --git a/client/src/containers/Connect/ConnectDetail/ConnectTasks/ConnectTasks.jsx b/client/src/containers/Connect/ConnectDetail/ConnectTasks/ConnectTasks.jsx
index 1d64dadb0..22cf18f37 100644
--- a/client/src/containers/Connect/ConnectDetail/ConnectTasks/ConnectTasks.jsx
+++ b/client/src/containers/Connect/ConnectDetail/ConnectTasks/ConnectTasks.jsx
@@ -10,11 +10,10 @@ import {
uriRestartTask
} from '../../../../utils/endpoints';
import ConfirmModal from '../../../../components/Modal/ConfirmModal/ConfirmModal';
-import './styles.scss';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import AceEditor from 'react-ace';
-import Root from "../../../../components/Root";
+import Root from '../../../../components/Root';
class ConnectTasks extends Root {
state = {
diff --git a/client/src/containers/Connect/ConnectList/ConnectList.jsx b/client/src/containers/Connect/ConnectList/ConnectList.jsx
index a53d0eb1e..3581c5e97 100644
--- a/client/src/containers/Connect/ConnectList/ConnectList.jsx
+++ b/client/src/containers/Connect/ConnectList/ConnectList.jsx
@@ -11,10 +11,10 @@ import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/theme-merbivore_soft';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
-import Root from "../../../components/Root";
-import SearchBar from "../../../components/SearchBar";
-import Pagination from "../../../components/Pagination";
-import {handlePageChange, getPageNumber} from "./../../../utils/pagination"
+import Root from '../../../components/Root';
+import SearchBar from '../../../components/SearchBar';
+import Pagination from '../../../components/Pagination';
+import { handlePageChange, getPageNumber } from './../../../utils/pagination';
class ConnectList extends Root {
state = {
@@ -31,10 +31,10 @@ class ConnectList extends Root {
history: this.props,
searchData: {
search: ''
- },
+ }
};
- static getDerivedStateFromProps(nextProps, prevState) {
+ static getDerivedStateFromProps(nextProps) {
const clusterId = nextProps.match.params.clusterId;
const connectId = nextProps.match.params.connectId;
@@ -46,16 +46,19 @@ class ConnectList extends Root {
componentDidMount() {
const { searchData, pageNumber } = this.state;
- const query = new URLSearchParams(this.props.location.search);
- this.setState({
- searchData: { search: (query.get('search'))? query.get('search') : searchData.search },
- pageNumber: (query.get('page')) ? parseInt(query.get('page')) : parseInt(pageNumber)
- }, () => {
- this.getConnectDefinitions();
- });
+ const query = new URLSearchParams(this.props.location.search);
+ this.setState(
+ {
+ searchData: { search: query.get('search') ? query.get('search') : searchData.search },
+ pageNumber: query.get('page') ? parseInt(query.get('page')) : parseInt(pageNumber)
+ },
+ () => {
+ this.getConnectDefinitions();
+ }
+ );
}
- componentDidUpdate(prevProps, prevState) {
+ componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
this.cancelAxiosRequests();
this.renewCancelToken();
@@ -72,7 +75,9 @@ class ConnectList extends Root {
this.setState({ loading: true });
- let response = await this.getApi(uriConnectDefinitions(clusterId, connectId, search, pageNumber));
+ let response = await this.getApi(
+ uriConnectDefinitions(clusterId, connectId, search, pageNumber)
+ );
let data = response.data;
if (data.results) {
this.handleData(data);
@@ -80,7 +85,7 @@ class ConnectList extends Root {
this.props.history.push({
pathname: `/ui/${this.state.clusterId}/connect/${this.state.connectId}`,
search: `search=${this.state.searchData.search}&page=${pageNumber}`
- })
+ });
});
} else {
this.setState({ clusterId, tableData: [], totalPageNumber: 0, loading: false });
@@ -91,15 +96,15 @@ class ConnectList extends Root {
const { clusterId, connectId, definitionToDelete: definition } = this.state;
this.removeApi(uriDeleteDefinition(clusterId, connectId, definition))
- .then(() => {
- toast.success(`Definition '${definition}' is deleted`);
- this.setState({ showDeleteModal: false, definitionToDelete: '' }, () => {
- this.getConnectDefinitions();
- });
- })
- .catch(() => {
- this.setState({ showDeleteModal: false, topicToDelete: {} });
+ .then(() => {
+ toast.success(`Definition '${definition}' is deleted`);
+ this.setState({ showDeleteModal: false, definitionToDelete: '' }, () => {
+ this.getConnectDefinitions();
});
+ })
+ .catch(() => {
+ this.setState({ showDeleteModal: false, topicToDelete: {} });
+ });
};
handleData = data => {
@@ -198,7 +203,8 @@ class ConnectList extends Root {
};
render() {
- const { clusterId, connectId, tableData, loading, searchData, pageNumber, totalPageNumber } = this.state;
+ const { clusterId, connectId, tableData, loading, searchData, pageNumber, totalPageNumber } =
+ this.state;
const roles = this.state.roles || {};
const { history } = this.props;
@@ -206,22 +212,22 @@ class ConnectList extends Root {
@@ -305,16 +311,17 @@ class ConnectList extends Root {
this.setState({ tableData: data });
}}
actions={this.getTableActions()}
- onDetails={name => `/ui/${clusterId}/connect/${connectId}/definition/${name}` }
+ onDetails={name => `/ui/${clusterId}/connect/${connectId}/definition/${name}`}
onDelete={row => {
this.handleOnDelete(row.id);
}}
extraRow
noStripes
onExpand={obj => {
- return Object.keys(obj.headers).map(header => {
+ return Object.keys(obj.headers).map((header, i) => {
return (
{
- this.props.history.replace(`/ui/${clusterId}/group/${consumerGroupId}/${this.state.selectedTab}`);
- }
+ {
+ selectedTab: tabSelected ? tabSelected : 'topics'
+ },
+ () => {
+ this.props.history.replace(
+ `/ui/${clusterId}/group/${consumerGroupId}/${this.state.selectedTab}`
+ );
+ }
);
}
- componentDidUpdate(prevProps, prevState) {
+ componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
const tabSelected = getSelectedTab(this.props, this.tabs);
this.setState({ selectedTab: tabSelected });
@@ -88,18 +91,23 @@ class ConsumerGroup extends Component {
const roles = this.state.roles || {};
return (
-
+
-
-
Topics
-
-
Members
@@ -107,7 +115,8 @@ class ConsumerGroup extends Component {
{roles.acls && roles.acls['acls/read'] && (
-
-
ACLS
@@ -123,31 +132,40 @@ class ConsumerGroup extends Component {
- {roles.group && (roles.group['group/offsets/delete'] || roles.group['group/offsets/update']) && (
-
- )}
+ {roles.group &&
+ (roles.group['group/offsets/delete'] || roles.group['group/offsets/update']) && (
+
+ )}
);
}
}
+ConsumerGroup.propTypes = {
+ history: PropTypes.object,
+ match: PropTypes.object,
+ location: PropTypes.object,
+ clusters: PropTypes.array,
+ children: PropTypes.any
+};
+
export default ConsumerGroup;
diff --git a/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupAcls/ConsumerGroupAcls.jsx b/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupAcls/ConsumerGroupAcls.jsx
index d55167839..c82f38b38 100644
--- a/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupAcls/ConsumerGroupAcls.jsx
+++ b/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupAcls/ConsumerGroupAcls.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import Table from '../../../../components/Table';
import { uriConsumerGroupAcls } from '../../../../utils/endpoints';
-import Root from "../../../../components/Root";
+import Root from '../../../../components/Root';
class TopicAcls extends Root {
state = {
@@ -85,8 +85,8 @@ class TopicAcls extends Root {
- No ACLS found, or the "authorizer.class.name" parameter is not configured on the
- cluster.
+ No ACLS found, or the "authorizer.class.name" parameter is not
+ configured on the cluster.
|
diff --git a/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupMembers/ConsumerGroupMembers.jsx b/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupMembers/ConsumerGroupMembers.jsx
index d2513253a..0926c10b3 100644
--- a/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupMembers/ConsumerGroupMembers.jsx
+++ b/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupMembers/ConsumerGroupMembers.jsx
@@ -4,7 +4,7 @@ import { uriConsumerGroupMembers } from '../../../../utils/endpoints';
import constants from '../../../../utils/constants';
import { Link } from 'react-router-dom';
import './styles.scss';
-import Root from "../../../../components/Root";
+import Root from '../../../../components/Root';
class ConsumerGroupMembers extends Root {
state = {
@@ -40,7 +40,7 @@ class ConsumerGroupMembers extends Root {
handlePartitions(partitions) {
return partitions.map(partition => {
- return
{partition}
;
+ return
{partition}
;
});
}
@@ -55,7 +55,7 @@ class ConsumerGroupMembers extends Root {
}
});
}
- return topics.map(topic => {
+ return topics.map((topic, i) => {
let partitions = [];
assignments.forEach(assignment => {
if (assignment.topic === topic) {
@@ -64,7 +64,7 @@ class ConsumerGroupMembers extends Root {
});
return (
-
{
history.push({
pathname: `/ui/${this.state.selectedCluster}/topic/${topic}`,
diff --git a/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupOffsetDelete/ConsumerGroupOffsetDelete.jsx b/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupOffsetDelete/ConsumerGroupOffsetDelete.jsx
index a076fea3c..01d55febb 100644
--- a/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupOffsetDelete/ConsumerGroupOffsetDelete.jsx
+++ b/client/src/containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupOffsetDelete/ConsumerGroupOffsetDelete.jsx
@@ -1,14 +1,12 @@
import React from 'react';
import Header from '../../../Header/Header';
-import {
- uriConsumerGroup, uriDeleteGroupOffsets,
-} from '../../../../utils/endpoints';
+import { uriConsumerGroup, uriDeleteGroupOffsets } from '../../../../utils/endpoints';
import 'react-toastify/dist/ReactToastify.css';
-import Root from "../../../../components/Root";
-import Table from "../../../../components/Table";
-import constants from "../../../../utils/constants";
-import ConfirmModal from "../../../../components/Modal/ConfirmModal";
-import {toast} from "react-toastify";
+import Root from '../../../../components/Root';
+import Table from '../../../../components/Table';
+import constants from '../../../../utils/constants';
+import ConfirmModal from '../../../../components/Modal/ConfirmModal';
+import { toast } from 'react-toastify';
class ConsumerGroupOffsetDelete extends Root {
state = {
@@ -17,13 +15,13 @@ class ConsumerGroupOffsetDelete extends Root {
topicIds: [],
deleteAllOffsetsForTopic: '',
showDeleteModal: false,
- deleteMessage: '',
+ deleteMessage: ''
};
componentDidMount() {
- const {clusterId, consumerGroupId} = this.props.match.params;
+ const { clusterId, consumerGroupId } = this.props.match.params;
- this.setState({clusterId, consumerGroupId}, () => {
+ this.setState({ clusterId, consumerGroupId }, () => {
this.getTopics();
});
}
@@ -54,15 +52,20 @@ class ConsumerGroupOffsetDelete extends Root {
const { clusterId, consumerGroupId, deleteAllOffsetsForTopic } = this.state;
this.removeApi(uriDeleteGroupOffsets(clusterId, consumerGroupId, deleteAllOffsetsForTopic))
.then(() => {
- toast.success(`Offsets for topic '${deleteAllOffsetsForTopic}' and consumer group '${consumerGroupId}' are deleted`);
- this.setState({ showDeleteModal: false, deleteMessage: '', deleteAllOffsetsForTopic: '' }, () => {
- this.getTopics();
- });
+ toast.success(
+ `Offsets for topic '${deleteAllOffsetsForTopic}' and consumer group '${consumerGroupId}' are deleted`
+ );
+ this.setState(
+ { showDeleteModal: false, deleteMessage: '', deleteAllOffsetsForTopic: '' },
+ () => {
+ this.getTopics();
+ }
+ );
})
.catch(() => {
this.setState({ showDeleteModal: false, deleteMessage: '', deleteAllOffsetsForTopic: '' });
});
- }
+ };
handleOnDelete(topicId) {
this.setState({ deleteAllOffsetsForTopic: topicId }, () => {
@@ -75,13 +78,12 @@ class ConsumerGroupOffsetDelete extends Root {
}
render() {
- const {consumerGroupId} = this.state;
+ const { consumerGroupId } = this.state;
return (
-
}
- onDelete={(row) => {
- this.handleOnDelete(row.topic)
+ onDelete={row => {
+ this.handleOnDelete(row.topic);
}}
- actions={
- [constants.TABLE_DELETE]
- }
+ actions={[constants.TABLE_DELETE]}
/>
{
if (obj.offset !== undefined && obj.offset !== '') {
return (
-
+
{obj.offset}
);
diff --git a/client/src/containers/ConsumerGroup/ConsumerGroupList/ConsumerGroupList.jsx b/client/src/containers/ConsumerGroup/ConsumerGroupList/ConsumerGroupList.jsx
index 20f407e78..a65e6ebd7 100644
--- a/client/src/containers/ConsumerGroup/ConsumerGroupList/ConsumerGroupList.jsx
+++ b/client/src/containers/ConsumerGroup/ConsumerGroupList/ConsumerGroupList.jsx
@@ -9,9 +9,9 @@ import Pagination from '../../../components/Pagination';
import ConfirmModal from '../../../components/Modal/ConfirmModal';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
-import Root from "../../../components/Root";
-import {Link} from "react-router-dom";
-import {handlePageChange, getPageNumber} from "./../../../utils/pagination"
+import Root from '../../../components/Root';
+import {Link} from 'react-router-dom';
+import {handlePageChange, getPageNumber} from './../../../utils/pagination'
class ConsumerGroupList extends Root {
state = {
diff --git a/client/src/containers/Header/Header.jsx b/client/src/containers/Header/Header.jsx
index a06db742a..0729973dd 100644
--- a/client/src/containers/Header/Header.jsx
+++ b/client/src/containers/Header/Header.jsx
@@ -6,7 +6,7 @@ import { logout } from '../../utils/api';
import { uriCurrentUser, uriLogout } from '../../utils/endpoints';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
-import Root from "../../components/Root";
+import Root from '../../components/Root';
class Header extends Root {
state = {
diff --git a/client/src/containers/Loading/Loading.jsx b/client/src/containers/Loading/Loading.jsx
index 9f7bf94df..b9c86ece8 100644
--- a/client/src/containers/Loading/Loading.jsx
+++ b/client/src/containers/Loading/Loading.jsx
@@ -1,6 +1,8 @@
import React, { Component } from 'react';
+import PropTypes from 'prop-types';
import './styles.scss';
import image from '../../images/icon.svg';
+
class Loading extends Component {
render() {
const { show } = this.props;
@@ -24,4 +26,9 @@ class Loading extends Component {
}
}
+Loading.propTypes = {
+ show: PropTypes.bool,
+ children: PropTypes.any,
+}
+
export default Loading;
diff --git a/client/src/containers/Login/Login.jsx b/client/src/containers/Login/Login.jsx
index e4579c65c..e9632bfb4 100644
--- a/client/src/containers/Login/Login.jsx
+++ b/client/src/containers/Login/Login.jsx
@@ -24,12 +24,8 @@ class Login extends Form {
};
schema = {
- username: Joi.string()
- .required()
- .label('Username'),
- password: Joi.string()
- .required()
- .label('Password')
+ username: Joi.string().required().label('Username'),
+ password: Joi.string().required().label('Password')
};
login() {
@@ -41,10 +37,9 @@ class Login extends Form {
password: formData.password
};
- login(uriLogin(), body)
- .then(() => {
- this.getData();
- });
+ login(uriLogin(), body).then(() => {
+ this.getData();
+ });
} catch (err) {
toast.error('Wrong Username or Password!');
}
@@ -63,7 +58,7 @@ class Login extends Form {
sessionStorage.removeItem('returnTo');
this.props.history.push({
- pathname: (returnTo || '/ui'),
+ pathname: returnTo || '/ui'
});
window.location.reload(true);
@@ -75,11 +70,11 @@ class Login extends Form {
componentDidMount() {
const auths = JSON.parse(sessionStorage.getItem('auths'));
if (auths && auths.loginEnabled) {
- const { loginEnabled, ...config } = auths;
+ const { ...config } = auths;
this.setState({ config });
} else {
this.props.history.push({
- pathname: '/ui',
+ pathname: '/ui'
});
}
}
@@ -154,8 +149,10 @@ class Login extends Form {
}
_renderOidc(oidcsAuths) {
- return oidcsAuths.map(auth => (
- {auth.label}
+ return oidcsAuths.map((auth, i) => (
+
+ {auth.label}
+
));
}
diff --git a/client/src/containers/Node/NodeDetail/Node.jsx b/client/src/containers/Node/NodeDetail/Node.jsx
index baa6841ed..9c67e4301 100644
--- a/client/src/containers/Node/NodeDetail/Node.jsx
+++ b/client/src/containers/Node/NodeDetail/Node.jsx
@@ -1,9 +1,10 @@
import React, { Component } from 'react';
+import PropTypes from 'prop-types';
import Header from '../../Header';
import NodeConfigs from './/NodeConfigs/NodeConfigs';
import NodeLogs from './/NodeLogs/NodeLogs';
-import {getSelectedTab} from "../../../utils/functions";
-import {Link} from "react-router-dom";
+import { getSelectedTab } from '../../../utils/functions';
+import { Link } from 'react-router-dom';
class Node extends Component {
state = {
@@ -21,16 +22,16 @@ class Node extends Component {
const { clusterId, nodeId } = this.props.match.params;
const tabSelected = getSelectedTab(this.props, this.tabs);
this.setState(
- {
- selectedTab: (tabSelected)? tabSelected : 'configs'
- },
- () => {
- this.props.history.replace(`/ui/${clusterId}/node/${nodeId}/${this.state.selectedTab}`);
- }
+ {
+ selectedTab: tabSelected ? tabSelected : 'configs'
+ },
+ () => {
+ this.props.history.replace(`/ui/${clusterId}/node/${nodeId}/${this.state.selectedTab}`);
+ }
);
}
- componentDidUpdate(prevProps, prevState) {
+ componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
const tabSelected = getSelectedTab(this.props, this.tabs);
this.setState({ selectedTab: tabSelected });
@@ -81,14 +82,16 @@ class Node extends Component {
-
-
Configs
-
-
Logs
@@ -107,4 +110,12 @@ class Node extends Component {
}
}
+Node.propTypes = {
+ history: PropTypes.object,
+ match: PropTypes.object,
+ location: PropTypes.object,
+ clusters: PropTypes.array,
+ children: PropTypes.any
+};
+
export default Node;
diff --git a/client/src/containers/Node/NodeDetail/NodeLogs/NodeLogs.jsx b/client/src/containers/Node/NodeDetail/NodeLogs/NodeLogs.jsx
index 836fa04cd..6da7eb470 100644
--- a/client/src/containers/Node/NodeDetail/NodeLogs/NodeLogs.jsx
+++ b/client/src/containers/Node/NodeDetail/NodeLogs/NodeLogs.jsx
@@ -3,7 +3,7 @@ import { uriNodesLogs } from '../../../../utils/endpoints';
import Table from '../../../../components/Table';
import { showBytes } from '../../../../utils/converters';
import { sortBy } from '../../../../utils/constants';
-import Root from "../../../../components/Root";
+import Root from '../../../../components/Root';
class NodeLogs extends Root {
state = {
diff --git a/client/src/containers/Node/NodeList/NodesList.jsx b/client/src/containers/Node/NodeList/NodesList.jsx
index 759cf7150..33e577286 100644
--- a/client/src/containers/Node/NodeList/NodesList.jsx
+++ b/client/src/containers/Node/NodeList/NodesList.jsx
@@ -2,8 +2,7 @@ import React from 'react';
import Header from '../../Header';
import Table from '../../../components/Table';
import * as constants from '../../../utils/constants';
-import { uriNodes } from '../../../utils/endpoints';
-import { uriNodePartitions } from '../../../utils/endpoints';
+import { uriNodes, uriNodePartitions } from '../../../utils/endpoints';
import Root from '../../../components/Root';
class NodesList extends Root {
diff --git a/client/src/containers/Schema/SchemaDetail/Schema.jsx b/client/src/containers/Schema/SchemaDetail/Schema.jsx
index 3a1ef8cb6..4e372e564 100644
--- a/client/src/containers/Schema/SchemaDetail/Schema.jsx
+++ b/client/src/containers/Schema/SchemaDetail/Schema.jsx
@@ -3,9 +3,9 @@ import Header from '../../Header';
import SchemaVersions from './SchemaVersions';
import SchemaUpdate from './SchemaUpdate';
import endpoints from '../../../utils/endpoints';
-import {getSelectedTab} from "../../../utils/functions";
-import {Link} from "react-router-dom";
-import Root from "../../../components/Root";
+import { getSelectedTab } from '../../../utils/functions';
+import { Link } from 'react-router-dom';
+import Root from '../../../components/Root';
class Schema extends Root {
state = {
@@ -23,7 +23,7 @@ class Schema extends Root {
this.getSchemaVersions();
}
- componentDidUpdate(prevProps, prevState) {
+ componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
const tabSelected = getSelectedTab(this.props, this.tabs);
this.setState({ selectedTab: tabSelected });
@@ -40,19 +40,23 @@ class Schema extends Root {
const { clusterId, schemaId, roles } = this.state;
let tabSelected = getSelectedTab(this.props, this.tabs);
- if(!roles.registry['registry/update'] && tabSelected === 'update') {
+ if (!roles.registry['registry/update'] && tabSelected === 'update') {
tabSelected = 'versions';
}
schemas = await this.getApi(endpoints.uriSchemaVersions(clusterId, schemaId));
- this.setState({
- schemaVersions: schemas.data,
- totalVersions: schemas.data.length,
- selectedTab: tabSelected === 'versions' ? tabSelected : 'update'
- },
- () => {
- this.props.history.replace(`/ui/${clusterId}/schema/details/${schemaId}/${this.state.selectedTab}`);
- });
+ this.setState(
+ {
+ schemaVersions: schemas.data,
+ totalVersions: schemas.data.length,
+ selectedTab: tabSelected === 'versions' ? tabSelected : 'update'
+ },
+ () => {
+ this.props.history.replace(
+ `/ui/${clusterId}/schema/details/${schemaId}/${this.state.selectedTab}`
+ );
+ }
+ );
}
renderSelectedTab() {
@@ -64,33 +68,35 @@ class Schema extends Root {
switch (selectedTab) {
case 'update':
return (
- {
- this.getSchemaVersions();
- }}
- schemaId={schemaId}
- history={history}
- match={match}
- />
+ {
+ this.getSchemaVersions();
+ }}
+ schemaId={schemaId}
+ history={history}
+ match={match}
+ />
);
case 'versions':
return (
-
+
);
default:
- return ;
+ />
+ );
}
}
@@ -98,34 +104,37 @@ class Schema extends Root {
const { clusterId, schemaId, totalVersions, roles } = this.state;
return (
-
-
-
-
- {roles.registry['registry/update'] && (
- -
-
- Update
-
-
)}
+
+
+
+
+ {roles.registry['registry/update'] && (
-
-
- Versions {totalVersions}
+ Update
-
+ )}
+
-
+
+ Versions {totalVersions}
+
+
+
-
-
- {this.renderSelectedTab()}
-
+
+
+ {this.renderSelectedTab()}
+
);
}
}
diff --git a/client/src/containers/Schema/SchemaDetail/SchemaUpdate/SchemaUpdate.jsx b/client/src/containers/Schema/SchemaDetail/SchemaUpdate/SchemaUpdate.jsx
index c225f2122..3def6931c 100644
--- a/client/src/containers/Schema/SchemaDetail/SchemaUpdate/SchemaUpdate.jsx
+++ b/client/src/containers/Schema/SchemaDetail/SchemaUpdate/SchemaUpdate.jsx
@@ -50,19 +50,11 @@ class SchemaUpdate extends Form {
};
schema = {
- subject: Joi.string()
- .required()
- .label('Subject'),
- compatibility: Joi.string()
- .required()
- .label('Compatibility Level'),
- schema: Joi.string()
- .required()
- .label('Latest Schema'),
- schemaType: Joi.string()
- .label('Schema Type'),
- references: Joi.any()
- .label('Refecences')
+ subject: Joi.string().required().label('Subject'),
+ compatibility: Joi.string().required().label('Compatibility Level'),
+ schema: Joi.string().required().label('Latest Schema'),
+ schemaType: Joi.string().label('Schema Type'),
+ references: Joi.any().label('Refecences')
};
componentDidMount() {
@@ -87,7 +79,10 @@ class SchemaUpdate extends Form {
formData.subject = latestSchemaVersion.subject;
formData.compatibility = latestSchemaVersion.compatibilityLevel;
formData.schemaType = latestSchemaVersion.schemaType;
- formData.schema = "PROTOBUF" === formData.schemaType?latestSchemaVersion.schema :JSON.stringify(JSON.parse(latestSchemaVersion.schema), null, 2);
+ formData.schema =
+ 'PROTOBUF' === formData.schemaType
+ ? latestSchemaVersion.schema
+ : JSON.stringify(JSON.parse(latestSchemaVersion.schema), null, 2);
formData.references = latestSchemaVersion.references;
this.setState(formData);
@@ -104,57 +99,59 @@ class SchemaUpdate extends Form {
references: formData.references
};
- this.postApi(uriUpdateSchema(clusterId, formData.subject), body)
- .then(() => {
- toast.success(`Schema '${formData.subject}' is updated`);
- this.props.getSchemaVersions();
- window.location.reload(false);
- });
+ this.postApi(uriUpdateSchema(clusterId, formData.subject), body).then(() => {
+ toast.success(`Schema '${formData.subject}' is updated`);
+ this.props.getSchemaVersions();
+ window.location.reload(false);
+ });
}
render() {
const { compatibilityOptions, roles } = this.state;
return (
-
+
);
}
}
diff --git a/client/src/containers/Schema/SchemaDetail/SchemaVersions/SchemaVersions.jsx b/client/src/containers/Schema/SchemaDetail/SchemaVersions/SchemaVersions.jsx
index 0e4367734..e162c14fe 100644
--- a/client/src/containers/Schema/SchemaDetail/SchemaVersions/SchemaVersions.jsx
+++ b/client/src/containers/Schema/SchemaDetail/SchemaVersions/SchemaVersions.jsx
@@ -9,7 +9,7 @@ import 'react-toastify/dist/ReactToastify.css';
import 'ace-builds/webpack-resolver';
import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/theme-merbivore_soft';
-import Root from "../../../../components/Root";
+import Root from '../../../../components/Root';
class SchemaVersions extends Root {
state = {
@@ -29,14 +29,16 @@ class SchemaVersions extends Root {
}
handleData(schemas) {
-
if (schemas) {
let data = schemas.map(schema => {
return {
id: schema.id,
version: schema.version,
schemaType: schema.schemaType,
- schema: "PROTOBUF" === schema.schemaType ? schema.schema : JSON.stringify(JSON.parse(schema.schema), null, 2)
+ schema:
+ 'PROTOBUF' === schema.schemaType
+ ? schema.schema
+ : JSON.stringify(JSON.parse(schema.schema), null, 2)
};
});
this.setState({ data, loading: false });
@@ -82,7 +84,7 @@ class SchemaVersions extends Root {
uriDeleteSchemaVersion(selectedCluster, selectedSchema, schemaToDelete.version),
deleteData
)
- .then(res => {
+ .then(() => {
toast.success(`Version'${schemaToDelete.version}' is deleted`);
this.setState({ showDeleteModal: false, schemaToDelete: {} });
history.push({
@@ -145,7 +147,9 @@ class SchemaVersions extends Root {
return (
- {obj["schemaType"] === "PROTOBUF" ? obj[col.accessor] : JSON.stringify(JSON.parse(obj[col.accessor]))}
+ {obj['schemaType'] === 'PROTOBUF'
+ ? obj[col.accessor]
+ : JSON.stringify(JSON.parse(obj[col.accessor]))}
);
@@ -167,9 +171,10 @@ class SchemaVersions extends Root {
extraRow
noStripes
onExpand={obj => {
- return Object.keys(obj.headers).map(header => {
+ return Object.keys(obj.headers).map((header, i) => {
return (
|
-
);
}
diff --git a/client/src/containers/Schema/SchemaList/SchemaList.jsx b/client/src/containers/Schema/SchemaList/SchemaList.jsx
index bc8a99720..929d3bb63 100644
--- a/client/src/containers/Schema/SchemaList/SchemaList.jsx
+++ b/client/src/containers/Schema/SchemaList/SchemaList.jsx
@@ -15,9 +15,8 @@ import 'ace-builds/src-noconflict/mode-protobuf';
import 'ace-builds/src-noconflict/theme-merbivore_soft';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
-import Root from "../../../components/Root";
-import {handlePageChange, getPageNumber} from "./../../../utils/pagination"
-
+import Root from '../../../components/Root';
+import { handlePageChange, getPageNumber } from './../../../utils/pagination';
class SchemaList extends Root {
state = {
@@ -45,15 +44,18 @@ class SchemaList extends Root {
componentDidMount() {
let { clusterId } = this.props.match.params;
const { searchData, pageNumber } = this.state;
- const query = new URLSearchParams(this.props.location.search);
+ const query = new URLSearchParams(this.props.location.search);
- this.setState({
- selectedCluster: clusterId,
- searchData: { search: (query.get('search'))? query.get('search') : searchData.search },
- pageNumber: (query.get('page'))? parseInt(query.get('page')) : parseInt(pageNumber)
- }, () => {
- this.getSchemaRegistry();
- });
+ this.setState(
+ {
+ selectedCluster: clusterId,
+ searchData: { search: query.get('search') ? query.get('search') : searchData.search },
+ pageNumber: query.get('page') ? parseInt(query.get('page')) : parseInt(pageNumber)
+ },
+ () => {
+ this.getSchemaRegistry();
+ }
+ );
}
handleSearch = data => {
@@ -65,13 +67,12 @@ class SchemaList extends Root {
handlePageChangeSubmission = value => {
let pageNumber = parseInt(getPageNumber(value, this.state.totalPageNumber));
- this.setState({pageNumber: pageNumber}, () => {
+ this.setState({ pageNumber: pageNumber }, () => {
this.getSchemaRegistry();
- })
- }
+ });
+ };
async getSchemaRegistry() {
-
const { selectedCluster, pageNumber } = this.state;
const { search } = this.state.searchData;
@@ -88,12 +89,11 @@ class SchemaList extends Root {
this.props.history.push({
pathname: `/ui/${this.state.selectedCluster}/schema`,
search: `search=${this.state.searchData.search}&page=${pageNumber}`
- })
+ });
});
} else {
this.setState({ selectedCluster, schemasRegistry: [], totalPageNumber: 0, loading: false });
}
-
}
handleSchemaRegistry(schemas) {
@@ -108,7 +108,12 @@ class SchemaList extends Root {
version: schema.version,
exception: schema.exception,
schemaType: schema.schemaType,
- schema: schema.schemaType === "PROTOBUF" ? schema.schema : (schema.schema ? JSON.stringify(JSON.parse(schema.schema), null, 2) : null)
+ schema:
+ schema.schemaType === 'PROTOBUF'
+ ? schema.schema
+ : schema.schema
+ ? JSON.stringify(JSON.parse(schema.schema), null, 2)
+ : null
});
});
this.setState({ schemasRegistry: tableSchemaRegistry, loading: false });
@@ -150,13 +155,7 @@ class SchemaList extends Root {
});
};
render() {
- const {
- selectedCluster,
- searchData,
- pageNumber,
- totalPageNumber,
- loading
- } = this.state;
+ const { selectedCluster, searchData, pageNumber, totalPageNumber, loading } = this.state;
const roles = this.state.roles || {};
const { history } = this.props;
const { clusterId } = this.props.match.params;
@@ -224,7 +223,7 @@ class SchemaList extends Root {
extraRowContent: (obj, col, index) => {
return (
- { obj.schemaType === "PROTOBUF"? obj[col.accessor] : JSON.stringify(JSON.parse(obj[col.accessor]))}
+ {obj.schemaType === 'PROTOBUF'
+ ? obj[col.accessor]
+ : JSON.stringify(JSON.parse(obj[col.accessor]))}
);
@@ -316,7 +317,6 @@ class SchemaList extends Root {
handleConfirm={this.deleteSchemaRegistry}
message={this.state.deleteMessage}
/>
-
);
}
diff --git a/client/src/containers/SideBar/Sidebar.jsx b/client/src/containers/SideBar/Sidebar.jsx
index 964fb9f8f..40f277a06 100644
--- a/client/src/containers/SideBar/Sidebar.jsx
+++ b/client/src/containers/SideBar/Sidebar.jsx
@@ -1,4 +1,5 @@
import React, { Component } from 'react';
+import PropTypes from 'prop-types';
import { Link, withRouter } from 'react-router-dom';
import { matchPath } from 'react-router';
import constants from '../../utils/constants';
@@ -332,4 +333,15 @@ class Sidebar extends Component {
}
}
+Sidebar.propTypes = {
+ history: PropTypes.object,
+ match: PropTypes.object,
+ location: PropTypes.object,
+ clusters: PropTypes.array,
+ children: PropTypes.any,
+ expanded: PropTypes.bool,
+ toggleSidebar: PropTypes.func,
+ selectedTab: PropTypes.string,
+}
+
export default withRouter(Sidebar);
diff --git a/client/src/containers/Tail/Tail.jsx b/client/src/containers/Tail/Tail.jsx
index 12e1661ee..afd632e4b 100644
--- a/client/src/containers/Tail/Tail.jsx
+++ b/client/src/containers/Tail/Tail.jsx
@@ -39,13 +39,13 @@ class Tail extends Root {
componentDidMount = async () => {
const { clusterId } = this.props.match.params;
- const query = new URLSearchParams(this.props.location.search);
+ const query = new URLSearchParams(this.props.location.search);
let data = await this.getApi(uriTopicsName(clusterId));
data = data.data;
let topics = [];
if (query && query.get('topicId')) {
- topics = [ query.get('topicId') ];
+ topics = [query.get('topicId')];
}
if (data) {
@@ -65,17 +65,17 @@ class Tail extends Root {
}
this.initDateTimeFormat();
- }
+ };
initDateTimeFormat = async () => {
const { clusterId } = this.props.match.params;
- const uiOptions = await getClusterUIOptions(clusterId)
- if(uiOptions.topicData && uiOptions.topicData.dateTimeFormat) {
- this.setState(({
+ const uiOptions = await getClusterUIOptions(clusterId);
+ if (uiOptions.topicData && uiOptions.topicData.dateTimeFormat) {
+ this.setState({
dateTimeFormat: uiOptions.topicData.dateTimeFormat
- }));
+ });
}
- }
+ };
componentWillUnmount = () => {
super.componentWillUnmount();
@@ -89,11 +89,10 @@ class Tail extends Root {
uriLiveTail(clusterId, search, selectedTopics, JSON.stringify(maxRecords))
);
let self = this;
- this.eventSource.addEventListener('tailBody', function(e) {
+ this.eventSource.addEventListener('tailBody', function (e) {
let res = JSON.parse(e.data);
let { data } = self.state;
-
if (res.records) {
data = data.concat(res.records);
if (data.length > maxRecords) {
@@ -105,7 +104,7 @@ class Tail extends Root {
self.scrollToBottom();
});
- this.eventSource.onerror = e => {
+ this.eventSource.onerror = () => {
this.setState({ selectedStatus: STATUS.STOPPED });
};
};
@@ -119,13 +118,14 @@ class Tail extends Root {
};
scrollToBottom = () => {
- const followScroll = (document.body.scrollTop || document.documentElement.scrollTop) + window.innerHeight >=
- (document.documentElement.scrollHeight - document.documentElement.clientHeight)
+ const followScroll =
+ (document.body.scrollTop || document.documentElement.scrollTop) + window.innerHeight >=
+ document.documentElement.scrollHeight - document.documentElement.clientHeight;
if (followScroll) {
this.messagesEnd.scrollIntoView({ behavior: 'smooth' });
}
- }
+ };
handleChange = e => {
this.setState({ [e.target.name]: [e.target.value] });
@@ -422,10 +422,10 @@ class Tail extends Root {
cell: obj => {
return (
-
+ />
);
}
@@ -493,9 +493,10 @@ class Tail extends Root {
}}
noContent={
|
}
onExpand={obj => {
- return Object.keys(obj.headers).map(header => {
+ return Object.keys(obj.headers).map((header, i) => {
return (
|
)}
-
{ this.messagesEnd = el; }}>
-
+
{
+ this.messagesEnd = el;
+ }}
+ >
);
}
diff --git a/client/src/containers/Topic/Topic/Topic.jsx b/client/src/containers/Topic/Topic/Topic.jsx
index 2393fd6f4..21d3c5ade 100644
--- a/client/src/containers/Topic/Topic/Topic.jsx
+++ b/client/src/containers/Topic/Topic/Topic.jsx
@@ -9,9 +9,9 @@ import TopicLogs from './TopicLogs';
import { uriTopicsConfigs, uriTopicDataEmpty } from '../../../utils/endpoints';
import ConfirmModal from '../../../components/Modal/ConfirmModal';
import { toast } from 'react-toastify';
-import {getSelectedTab} from "../../../utils/functions";
+import { getSelectedTab } from '../../../utils/functions';
import { Link } from 'react-router-dom';
-import Root from "../../../components/Root";
+import Root from '../../../components/Root';
class Topic extends Root {
state = {
@@ -27,7 +27,7 @@ class Topic extends Root {
configs: []
};
- tabs = ['data','partitions','groups','configs','acls','logs'];
+ tabs = ['data', 'partitions', 'groups', 'configs', 'acls', 'logs'];
constructor(props) {
super(props);
@@ -55,7 +55,7 @@ class Topic extends Root {
() => {
this.getTopicsConfig();
let uri = `/ui/${clusterId}/topic/${topicId}/${this.state.selectedTab}`;
- if(searchParams) {
+ if (searchParams) {
uri = uri + searchParams;
}
this.props.history.replace(uri);
@@ -66,9 +66,9 @@ class Topic extends Root {
handleOnEmpty() {
this.setState(() => {
this.showDeleteModal(
-
- Do you want to empty the Topic: {{this.state.topicId}
} ?
-
+
+ Do you want to empty the Topic: {{this.state.topicId}
} ?
+
);
});
}
@@ -83,29 +83,27 @@ class Topic extends Root {
canEmptyTopic = () => {
const { configs } = this.state;
- const res = configs.filter( config => config.name === 'cleanup.policy');
- if(res && res.length === 1 && res[0].value === 'delete') return true;
+ const res = configs.filter(config => config.name === 'cleanup.policy');
+ if (res && res.length === 1 && res[0].value === 'delete') return true;
return false;
- }
+ };
emptyTopic = () => {
const { clusterId, topicId } = this.props.match.params;
- this.removeApi(
- uriTopicDataEmpty(clusterId, topicId)
- )
- .then(() => {
- toast.success(`Topic '${topicId}' will be emptied`);
- this.setState({ showDeleteModal: false }, () => {
- this.topicData.current.getMessages();
- });
- })
- .catch(() => {
- this.setState({ showDeleteModal: false });
+ this.removeApi(uriTopicDataEmpty(clusterId, topicId))
+ .then(() => {
+ toast.success(`Topic '${topicId}' will be emptied`);
+ this.setState({ showDeleteModal: false }, () => {
+ this.topicData.current.getMessages();
});
+ })
+ .catch(() => {
+ this.setState({ showDeleteModal: false });
+ });
};
- componentDidUpdate(prevProps, prevState) {
+ componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
const tabSelected = getSelectedTab(this.props, this.tabs);
this.setState({ selectedTab: tabSelected });
@@ -125,7 +123,6 @@ class Topic extends Root {
selectTab = tab => {
this.setState({ selectedTab: tab });
-
};
tabClassName = tab => {
@@ -139,17 +136,13 @@ class Topic extends Root {
switch (selectedTab) {
case 'data':
- return ;
+ return (
+
+ );
case 'partitions':
return ;
case 'groups':
- return (
-
- );
+ return ;
case 'configs':
return (
;
default:
return roles.topic && roles.topic['topic/data/read'] ? (
-
+
) : (
);
@@ -183,7 +176,8 @@ class Topic extends Root {
{roles.topic && roles.topic['topic/data/read'] && (
-
-
Data
@@ -191,21 +185,24 @@ class Topic extends Root {
)}
-
-
Partitions
-
-
Consumer Groups
-
-
Configs
@@ -213,7 +210,8 @@ class Topic extends Root {
{roles.acls && roles.acls['acls/read'] && (
-
-
ACLS
@@ -221,7 +219,8 @@ class Topic extends Root {
)}
-
-
Logs
@@ -238,46 +237,51 @@ class Topic extends Root {
{selectedTab !== 'configs' && roles.topic && roles.topic['topic/data/insert'] && (
)}
-
);
diff --git a/client/src/containers/Topic/Topic/TopicAcls/TopicAcls.jsx b/client/src/containers/Topic/Topic/TopicAcls/TopicAcls.jsx
index 900a00d57..1e57777b0 100644
--- a/client/src/containers/Topic/Topic/TopicAcls/TopicAcls.jsx
+++ b/client/src/containers/Topic/Topic/TopicAcls/TopicAcls.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import Table from '../../../../components/Table';
import { uriTopicsAcls } from '../../../../utils/endpoints';
-import Root from "../../../../components/Root";
+import Root from '../../../../components/Root';
class TopicAcls extends Root {
state = {
@@ -86,8 +86,8 @@ class TopicAcls extends Root {
- No ACLS found, or the "authorizer.class.name" parameter is not configured on the
- cluster.
+ No ACLS found, or the "authorizer.class.name" parameter is not
+ configured on the cluster.
|
diff --git a/client/src/containers/Topic/Topic/TopicData/TopicData.jsx b/client/src/containers/Topic/Topic/TopicData/TopicData.jsx
index 4739b723d..a36807b92 100644
--- a/client/src/containers/Topic/Topic/TopicData/TopicData.jsx
+++ b/client/src/containers/Topic/Topic/TopicData/TopicData.jsx
@@ -8,7 +8,8 @@ import {
uriSchemaId,
uriTopicData,
uriTopicDataDelete,
- uriTopicDataSearch, uriTopicDataSingleRecord,
+ uriTopicDataSearch,
+ uriTopicDataSingleRecord,
uriTopicsPartitions,
basePath
} from '../../../../utils/endpoints';
@@ -28,9 +29,9 @@ import 'react-toastify/dist/ReactToastify.css';
import Root from '../../../../components/Root';
import DateTime from '../../../../components/DateTime';
import { capitalizeTxt, getClusterUIOptions } from '../../../../utils/functions';
-import { setProduceToTopicValues, setUIOptions} from '../../../../utils/localstorage';
+import { setProduceToTopicValues, setUIOptions } from '../../../../utils/localstorage';
import Select from '../../../../components/Form/Select';
-import * as LosslessJson from 'lossless-json'
+import * as LosslessJson from 'lossless-json';
class TopicData extends Root {
state = {
@@ -42,10 +43,10 @@ class TopicData extends Root {
offsetsOptions: [],
timestamp: '',
search: {
- key: { text: '', type: 'C'},
- value: { text: '', type: 'C'},
- headerKey: { text: '', type: 'C'},
- headerValue: { text: '', type: 'C'}
+ key: { text: '', type: 'C' },
+ value: { text: '', type: 'C' },
+ headerKey: { text: '', type: 'C' },
+ headerValue: { text: '', type: 'C' }
},
offsets: {},
offsetsSearch: '',
@@ -82,7 +83,8 @@ class TopicData extends Root {
{
_id: 'E',
name: 'Equals'
- }];
+ }
+ ];
eventSource;
@@ -97,32 +99,40 @@ class TopicData extends Root {
async _checkProps() {
const { clusterId, topicId } = this.props.match.params;
- const query = new URLSearchParams(this.props.location.search);
+ const query = new URLSearchParams(this.props.location.search);
const uiOptions = await getClusterUIOptions(clusterId);
- this.setState((prevState) =>
- ({
- selectedCluster: clusterId,
- selectedTopic: topicId,
- sortBy: (query.get('sort'))? query.get('sort') : (uiOptions && uiOptions.topicData && uiOptions.topicData.sort)?
- uiOptions.topicData.sort : this.state.sortBy,
- partition: (query.get('partition'))? query.get('partition') : this.state.partition,
- datetime: (query.get('timestamp'))? new Date(query.get('timestamp')) : this.state.datetime,
- offsetsSearch: (query.get('after'))? query.get('after') : this.state.offsetsSearch,
- search: this._buildSearchFromQueryString(query),
- offsets: (query.get('offset'))? this._getOffsetsByOffset(query.get('partition'), query.get('offset')) :
- ((query.get('after'))? this._getOffsetsByAfterString(query.get('after')): this.state.offsets),
- dateTimeFormat: (uiOptions && uiOptions.topicData && uiOptions.topicData.dateTimeFormat)?
- uiOptions.topicData.dateTimeFormat : prevState.dateTimeFormat
- }),
- () => {
- if(query.get('single') !== null) {
- this._getSingleMessage(query.get('partition'), query.get('offset'));
- this.setState({ canDownload: true })
- } else {
- this._getMessages();
- }
+ this.setState(
+ prevState => ({
+ selectedCluster: clusterId,
+ selectedTopic: topicId,
+ sortBy: query.get('sort')
+ ? query.get('sort')
+ : uiOptions && uiOptions.topicData && uiOptions.topicData.sort
+ ? uiOptions.topicData.sort
+ : this.state.sortBy,
+ partition: query.get('partition') ? query.get('partition') : this.state.partition,
+ datetime: query.get('timestamp') ? new Date(query.get('timestamp')) : this.state.datetime,
+ offsetsSearch: query.get('after') ? query.get('after') : this.state.offsetsSearch,
+ search: this._buildSearchFromQueryString(query),
+ offsets: query.get('offset')
+ ? this._getOffsetsByOffset(query.get('partition'), query.get('offset'))
+ : query.get('after')
+ ? this._getOffsetsByAfterString(query.get('after'))
+ : this.state.offsets,
+ dateTimeFormat:
+ uiOptions && uiOptions.topicData && uiOptions.topicData.dateTimeFormat
+ ? uiOptions.topicData.dateTimeFormat
+ : prevState.dateTimeFormat
+ }),
+ () => {
+ if (query.get('single') !== null) {
+ this._getSingleMessage(query.get('partition'), query.get('offset'));
+ this.setState({ canDownload: true });
+ } else {
+ this._getMessages();
}
+ }
);
}
@@ -131,7 +141,7 @@ class TopicData extends Root {
Object.keys(search).forEach(value => {
const searchFilter = query.get(`searchBy${capitalizeTxt(value)}`);
- if(searchFilter) {
+ if (searchFilter) {
const pos = searchFilter.lastIndexOf('_');
search[value].text = searchFilter.substr(0, pos);
search[value].type = searchFilter.substr(pos + 1);
@@ -140,46 +150,64 @@ class TopicData extends Root {
return search;
}
- _startEventSource = (changePage) => {
+ _startEventSource = changePage => {
let { selectedCluster, selectedTopic, nextPage } = this.state;
let lastPercentVal = 0.0;
const percentUpdateDelta = 0.5;
let self = this;
- this.setState({ messages: [], pageNumber: 1, percent: 0, isSearching: true, recordCount: 0 }, () => {
- const filters = this._buildFilters();
- if (changePage) {
- this._setUrlHistory(filters + '&after=' + nextPage );
- } else {
- this._setUrlHistory(filters);
- }
- this.eventSource = new EventSource(uriTopicDataSearch(selectedCluster, selectedTopic, filters, (changePage)? nextPage: undefined));
-
- this.eventSource.addEventListener('searchBody', function(e) {
- const res = JSON.parse(e.data);
- const records = res.records || [];
- const nextPage = (res.after) ? res.after : self.state.nextPage;
-
- const percentDiff = res.percent - lastPercentVal;
-
- // to avoid UI slowdowns, only update the percentage in fixed increments
- if(percentDiff >= percentUpdateDelta) {
- lastPercentVal = res.percent;
- self.setState({ nextPage, recordCount: self.state.recordCount + records.length , percent: res.percent.toFixed(2) });
+ this.setState(
+ { messages: [], pageNumber: 1, percent: 0, isSearching: true, recordCount: 0 },
+ () => {
+ const filters = this._buildFilters();
+ if (changePage) {
+ this._setUrlHistory(filters + '&after=' + nextPage);
+ } else {
+ this._setUrlHistory(filters);
}
+ this.eventSource = new EventSource(
+ uriTopicDataSearch(
+ selectedCluster,
+ selectedTopic,
+ filters,
+ changePage ? nextPage : undefined
+ )
+ );
+
+ this.eventSource.addEventListener('searchBody', function (e) {
+ const res = JSON.parse(e.data);
+ const records = res.records || [];
+ const nextPage = res.after ? res.after : self.state.nextPage;
+
+ const percentDiff = res.percent - lastPercentVal;
+
+ // to avoid UI slowdowns, only update the percentage in fixed increments
+ if (percentDiff >= percentUpdateDelta) {
+ lastPercentVal = res.percent;
+ self.setState({
+ nextPage,
+ recordCount: self.state.recordCount + records.length,
+ percent: res.percent.toFixed(2)
+ });
+ }
- if(records.length) {
- const tableMessages = self._handleMessages(records, true, self.state.sortBy === "Oldest");
- self.setState({messages: tableMessages});
- }
- });
+ if (records.length) {
+ const tableMessages = self._handleMessages(
+ records,
+ true,
+ self.state.sortBy === 'Oldest'
+ );
+ self.setState({ messages: tableMessages });
+ }
+ });
- this.eventSource.addEventListener('searchEnd', function(e) {
- self.eventSource.close();
- self.setState({ percent: 100, isSearching: false, loading: false });
- });
- });
+ this.eventSource.addEventListener('searchEnd', function () {
+ self.eventSource.close();
+ self.setState({ percent: 100, isSearching: false, loading: false });
+ });
+ }
+ );
};
_stopEventSource = () => {
@@ -190,15 +218,20 @@ class TopicData extends Root {
};
_clearSearch = () => {
- this.setState({ search: {
- key: { text: '', type: 'C'},
- value: { text: '', type: 'C'},
- headerKey: { text: '', type: 'C'},
- headerValue: { text: '', type: 'C'}
- } }, () => {
+ this.setState(
+ {
+ search: {
+ key: { text: '', type: 'C' },
+ value: { text: '', type: 'C' },
+ headerKey: { text: '', type: 'C' },
+ headerValue: { text: '', type: 'C' }
+ }
+ },
+ () => {
this._searchMessages();
- });
- }
+ }
+ );
+ };
_hasAnyFilterFilled() {
const { search } = this.state;
@@ -206,13 +239,7 @@ class TopicData extends Root {
}
_buildFilters() {
- const {
- sortBy,
- partition,
- datetime,
- offsetsSearch,
- search
- } = this.state;
+ const { sortBy, partition, datetime, offsetsSearch, search } = this.state;
const filters = [];
@@ -222,30 +249,36 @@ class TopicData extends Root {
if (datetime) {
let timestamp = datetime.toString().length > 0 ? moment(datetime) : '';
- timestamp = formatDateTime(
- {
- year: timestamp.year(),
- monthValue: timestamp.month(),
- dayOfMonth: timestamp.date(),
- hour: timestamp.hour(),
- minute: timestamp.minute(),
- second: timestamp.second(),
- milli: timestamp.millisecond()
- },
- 'YYYY-MM-DDTHH:mm:ss.SSS',
- true
- ) + 'Z';
+ timestamp =
+ formatDateTime(
+ {
+ year: timestamp.year(),
+ monthValue: timestamp.month(),
+ dayOfMonth: timestamp.date(),
+ hour: timestamp.hour(),
+ minute: timestamp.minute(),
+ second: timestamp.second(),
+ milli: timestamp.millisecond()
+ },
+ 'YYYY-MM-DDTHH:mm:ss.SSS',
+ true
+ ) + 'Z';
filters.push(`timestamp=${timestamp}`);
}
- Object.keys(search).filter(value => search[value].text.length > 0)
- .forEach(value => {
- filters.push(`searchBy${capitalizeTxt(value)}=${encodeURIComponent(search[value].text)}_${search[value].type}`)
- })
+ Object.keys(search)
+ .filter(value => search[value].text.length > 0)
+ .forEach(value => {
+ filters.push(
+ `searchBy${capitalizeTxt(value)}=${encodeURIComponent(search[value].text)}_${
+ search[value].type
+ }`
+ );
+ });
return filters.join('&');
}
- _searchMessages(changePage = false){
+ _searchMessages(changePage = false) {
this._stopEventSource();
if (this._hasAnyFilterFilled()) {
this._startEventSource(changePage);
@@ -255,27 +288,24 @@ class TopicData extends Root {
}
_getSingleMessage(partition, offset) {
- const {
- selectedCluster,
- selectedTopic,
- } = this.state;
+ const { selectedCluster, selectedTopic } = this.state;
- const requests = [this.getApi(uriTopicDataSingleRecord(selectedCluster, selectedTopic, partition, offset)),
- this.getApi(uriTopicsPartitions(selectedCluster, selectedTopic))];
+ const requests = [
+ this.getApi(uriTopicDataSingleRecord(selectedCluster, selectedTopic, partition, offset)),
+ this.getApi(uriTopicsPartitions(selectedCluster, selectedTopic))
+ ];
this._fetchMessages(requests);
}
_getMessages(changePage = false) {
- const {
- selectedCluster,
- selectedTopic,
- nextPage
- } = this.state;
+ const { selectedCluster, selectedTopic, nextPage } = this.state;
const filters = this._buildFilters();
const requests = [
- this.getApi(uriTopicData(selectedCluster, selectedTopic, filters, changePage ? nextPage : undefined)),
+ this.getApi(
+ uriTopicData(selectedCluster, selectedTopic, filters, changePage ? nextPage : undefined)
+ ),
this.getApi(uriTopicsPartitions(selectedCluster, selectedTopic))
];
@@ -289,85 +319,79 @@ class TopicData extends Root {
}
_fetchMessages(requests, changePage = false) {
- const {
- nextPage,
- pageNumber,
- partitionCount,
- recordCount,
- offsets
- } = this.state;
+ const { nextPage, pageNumber, partitionCount, recordCount, offsets } = this.state;
- Promise.all(requests)
- .then(data => {
- let tableMessages = [],
- pageNumberTemp, offsetsTemp, partitionCountTemp, nextPageTemp, recordCountTemp;
+ Promise.all(requests).then(data => {
+ let tableMessages = [],
+ pageNumberTemp,
+ offsetsTemp,
+ partitionCountTemp,
+ nextPageTemp,
+ recordCountTemp;
- const messagesData = data[0].data;
- const partitionData = data[1].data;
+ const messagesData = data[0].data;
+ const partitionData = data[1].data;
- if (messagesData.results) {
- tableMessages = this._handleMessages(messagesData.results);
- } else {
- pageNumberTemp = 1;
- }
- if (partitionData) {
- if (changePage) {
- offsetsTemp = this._getNextPageOffsets(nextPage);
- }
- partitionCountTemp = partitionData.length;
- nextPageTemp = messagesData.after;
- recordCountTemp = messagesData.size;
+ if (messagesData.results) {
+ tableMessages = this._handleMessages(messagesData.results);
+ } else {
+ pageNumberTemp = 1;
+ }
+ if (partitionData) {
+ if (changePage) {
+ offsetsTemp = this._getNextPageOffsets(nextPage);
}
- this.setState({
- messages: tableMessages,
- canDeleteRecords: messagesData.canDeleteRecords,
- pageNumber: (pageNumberTemp) ? pageNumberTemp : pageNumber,
- partitionCount: (partitionCountTemp) ? partitionCountTemp : partitionCount,
- nextPage: (nextPageTemp) ? nextPageTemp : nextPage,
- recordCount: (recordCountTemp) ? recordCountTemp : recordCount,
- offsets: (offsetsTemp) ? offsetsTemp : offsets,
- loading: false
- });
+ partitionCountTemp = partitionData.length;
+ nextPageTemp = messagesData.after;
+ recordCountTemp = messagesData.size;
+ }
+ this.setState({
+ messages: tableMessages,
+ canDeleteRecords: messagesData.canDeleteRecords,
+ pageNumber: pageNumberTemp ? pageNumberTemp : pageNumber,
+ partitionCount: partitionCountTemp ? partitionCountTemp : partitionCount,
+ nextPage: nextPageTemp ? nextPageTemp : nextPage,
+ recordCount: recordCountTemp ? recordCountTemp : recordCount,
+ offsets: offsetsTemp ? offsetsTemp : offsets,
+ loading: false
+ });
});
}
_handleOnDelete(message) {
this.setState({ compactMessageToDelete: message }, () => {
this._showDeleteModal(
-
- Do you want to delete message: {{message.key}
} ?
-
+
+ Do you want to delete message: {{message.key}
} ?
+
);
});
}
_copyToClipboard(code) {
- const textField = document.createElement('textarea')
- textField.innerText = code
- document.body.appendChild(textField)
- textField.select()
- document.execCommand('copy')
- textField.remove()
+ const textField = document.createElement('textarea');
+ textField.innerText = code;
+ document.body.appendChild(textField);
+ textField.select();
+ document.execCommand('copy');
+ textField.remove();
}
_handleOnShare(row) {
- const {
- selectedCluster,
- selectedTopic
- } = this.state;
+ const { selectedCluster, selectedTopic } = this.state;
- const pathToShare = `${basePath}/ui/${selectedCluster}/topic/${selectedTopic}/data?single=true&partition=${row.partition}&offset=${row.offset}`;
+ const pathToShare = `${basePath}/ui/${selectedCluster}/topic/${selectedTopic}/data?single=true&partition=${row.partition}&offset=${row.offset}`; // eslint-disable-line max-len
try {
- this._copyToClipboard(`${window.location.host}${pathToShare}`)
+ this._copyToClipboard(`${window.location.host}${pathToShare}`);
toast.info('Message url is copied to your clipboard!');
} catch (err) {
console.error('Failed to copy: ', err);
}
- this.setState({ canDownload: true })
+ this.setState({ canDownload: true });
- this.props.history.push(pathToShare)
+ this.props.history.push(pathToShare);
this._getSingleMessage(row.partition, row.offset);
}
@@ -375,7 +399,7 @@ class TopicData extends Root {
const hasKey = key && key !== null && key !== 'null';
const a = document.createElement('a');
- a.href = URL.createObjectURL( new Blob([data], { type:'text/json' }) );
+ a.href = URL.createObjectURL(new Blob([data], { type: 'text/json' }));
a.download = `${hasKey ? key : 'file'}.json`;
a.click();
@@ -384,33 +408,33 @@ class TopicData extends Root {
async _handleOnDateTimeFormatChanged(newDateTimeFormat) {
const { clusterId } = this.props.match.params;
- this.setState(({
+ this.setState({
dateTimeFormat: newDateTimeFormat
- }));
+ });
const currentUiOptions = await getClusterUIOptions(clusterId);
const newUiOptions = {
...currentUiOptions,
topicData: {
- ...(currentUiOptions.topicData),
+ ...currentUiOptions.topicData,
dateTimeFormat: newDateTimeFormat
}
- }
+ };
setUIOptions(clusterId, newUiOptions);
}
_handleCopy(row) {
- const data = {
+ const data = {
partition: row.partition,
key: row.key,
header: row.headers,
keySchemaId: row.schema.key,
valueSchemaId: row.schema.value,
- value: row.value,
- }
- setProduceToTopicValues(data)
+ value: row.value
+ };
+ setProduceToTopicValues(data);
const { clusterId, topicId } = this.props.match.params;
- this.props.history.push(`/ui/${clusterId}/topic/${topicId}/produce`)
+ this.props.history.push(`/ui/${clusterId}/topic/${topicId}/produce`);
}
_showDeleteModal = deleteMessage => {
@@ -427,18 +451,20 @@ class TopicData extends Root {
const encodedkey = new Buffer(message.key).toString('base64');
const deleteData = { partition: parseInt(message.partition), key: encodedkey };
this.removeApi(
- uriTopicDataDelete(selectedCluster, selectedTopic, parseInt(message.partition), encodedkey),
- deleteData
+ uriTopicDataDelete(selectedCluster, selectedTopic, parseInt(message.partition), encodedkey),
+ deleteData
)
- .then(() => {
- toast.success(`Record '${message.partition}-${message.offset}' will be deleted on compaction`);
- this.setState({ showDeleteModal: false, compactMessageToDelete: '' }, () => {
- this._getMessages();
- });
- })
- .catch(() => {
- this.setState({ showDeleteModal: false, messageToDelete: {} });
+ .then(() => {
+ toast.success(
+ `Record '${message.partition}-${message.offset}' will be deleted on compaction`
+ );
+ this.setState({ showDeleteModal: false, compactMessageToDelete: '' }, () => {
+ this._getMessages();
});
+ })
+ .catch(() => {
+ this.setState({ showDeleteModal: false, messageToDelete: {} });
+ });
};
_handleMessages = (messages, append = false, insertAtEnd = true) => {
@@ -447,7 +473,7 @@ class TopicData extends Root {
let messageToPush = {
key: message.key || '',
value: message.truncated
- ? message.value + '...\nToo large message. Full body in share button.' || ''
+ ? message.value + '...\nToo large message. Full body in share button.' || ''
: message.value || '',
timestamp: message.timestamp,
partition: JSON.stringify(message.partition) || '',
@@ -466,13 +492,13 @@ class TopicData extends Root {
return tableMessages;
};
- _getNextPageOffsets = (nextPage) => {
+ _getNextPageOffsets = nextPage => {
let aux = nextPage.substring(nextPage.indexOf('after=') + 6);
let afterString = aux.substring(0, aux.indexOf('&'));
return this._getOffsetsByAfterString(afterString);
};
- _getOffsetsByAfterString = (afterString) => {
+ _getOffsetsByAfterString = afterString => {
let offsets = [];
const offsetsByPartition = afterString.split('_');
@@ -481,13 +507,13 @@ class TopicData extends Root {
offsets[`partition${offset[0]}`] = offset[1];
});
return offsets;
- }
+ };
_getOffsetsByOffset = (partition, offset) => {
let offsets = [];
offsets[`partition${partition}`] = offset;
return offsets;
- }
+ };
_createPartitionOptions = () => {
const { partitionCount } = this.state;
@@ -507,11 +533,8 @@ class TopicData extends Root {
return offsetsOptions;
};
- _setUrlHistory(filters){
- const {
- selectedCluster,
- selectedTopic
- } = this.state;
+ _setUrlHistory(filters) {
+ const { selectedCluster, selectedTopic } = this.state;
this.props.history.push({
pathname: `/ui/${selectedCluster}/topic/${selectedTopic}/data`,
@@ -522,17 +545,16 @@ class TopicData extends Root {
_redirectToSchema(id) {
const { selectedCluster } = this.state;
- this.getApi(uriSchemaId(selectedCluster, id))
- .then(response => {
- if (response.data) {
- this.props.history.push({
- pathname: `/ui/${selectedCluster}/schema/details/${response.data.subject}`,
- schemaId: response.data.subject
- });
- } else {
- toast.warn(`Unable to find the registry schema with id ${id} !`);
- }
- })
+ this.getApi(uriSchemaId(selectedCluster, id)).then(response => {
+ if (response.data) {
+ this.props.history.push({
+ pathname: `/ui/${selectedCluster}/schema/details/${response.data.subject}`,
+ schemaId: response.data.subject
+ });
+ } else {
+ toast.warn(`Unable to find the registry schema with id ${id} !`);
+ }
+ });
}
_renderSortOptions() {
@@ -541,14 +563,16 @@ class TopicData extends Root {
let renderedOptions = [];
for (let option of sortOptions) {
renderedOptions.push(
- this.setState({ sortBy: option }, () => {
- this._clearSearch();
- })}
- >
- {option}
-
+
+ this.setState({ sortBy: option }, () => {
+ this._clearSearch();
+ })
+ }
+ >
+ {option}
+
);
}
return renderedOptions;
@@ -560,14 +584,16 @@ class TopicData extends Root {
let renderedOptions = [];
for (let option of partitionOptions) {
renderedOptions.push(
- this.setState({ partition: option }, () => {
- this._searchMessages();
- })}
- >
- {option}
-
+
+ this.setState({ partition: option }, () => {
+ this._searchMessages();
+ })
+ }
+ >
+ {option}
+
);
}
return renderedOptions;
@@ -589,23 +615,23 @@ class TopicData extends Root {
}
renderedOptions.push(
-
- {option} : |
-
- {
- let { offsets } = this.state;
- offsets[camelcaseOption] = input.value;
- this.setState(offsets);
- }}
- />
- |
-
+
+ {option} : |
+
+ {
+ let { offsets } = this.state;
+ offsets[camelcaseOption] = input.value;
+ this.setState(offsets);
+ }}
+ />
+ |
+
);
}
return renderedOptions;
@@ -624,30 +650,30 @@ class TopicData extends Root {
const { search } = this.state;
return (
-
-
- {
- search[name].text = input.value;
- this.setState({ search });
- }}
- />
- {
- search[name].type = value.target.value;
- this.setState({ search });
- }}
- />
-
+
+
+ {
+ search[name].text = input.value;
+ this.setState({ search });
+ }}
+ />
+ {
+ search[name].type = value.target.value;
+ this.setState({ search });
+ }}
+ />
+
);
}
@@ -656,48 +682,48 @@ class TopicData extends Root {
return (
-
{this._renderSearchFilter('key', 'Key')}
- {this._renderSearchFilter('value','Value')}
+ {this._renderSearchFilter('value', 'Value')}
{this._renderSearchFilter('headerKey', 'Header Key')}
{this._renderSearchFilter('headerValue', 'Header Value')}
-
+
-
);
+
+ );
}
_renderCurrentSearchText() {
const { search } = this.state;
const filterKey = Object.keys(search).find(value => search[value].text.length > 0);
- return (filterKey !== undefined)? search[filterKey].text : '';
+ return filterKey !== undefined ? search[filterKey].text : '';
}
render() {
@@ -717,9 +743,9 @@ class TopicData extends Root {
loading
} = this.state;
- let actions = [constants.TABLE_SHARE, constants.TABLE_COPY]
- if (canDeleteRecords) actions.push(constants.TABLE_DELETE)
- if (canDownload) actions.push(constants.TABLE_DOWNLOAD)
+ let actions = [constants.TABLE_SHARE, constants.TABLE_COPY];
+ if (canDeleteRecords) actions.push(constants.TABLE_DELETE);
+ if (canDownload) actions.push(constants.TABLE_DOWNLOAD);
let date = moment(datetime);
const { history } = this.props;
@@ -733,80 +759,82 @@ class TopicData extends Root {
{ colName: 'Schema', colSpan: 1 }
];
return (
-
-