From 17c541fb25f0b643f1588a02d308d36450cd042e Mon Sep 17 00:00:00 2001 From: Pierre Larboulette Date: Thu, 18 Mar 2021 20:29:00 +0100 Subject: [PATCH] feat(ui): add a query string for pagination (#636) --- .../Connect/ConnectList/ConnectList.jsx | 60 +++++++++---------- .../ConsumerGroupList/ConsumerGroupList.jsx | 34 +++++------ .../Schema/SchemaList/SchemaList.jsx | 48 +++++++-------- .../containers/Topic/TopicList/TopicList.jsx | 38 ++++++------ client/src/utils/Routes.js | 6 +- client/src/utils/functions.js | 6 +- client/src/utils/localstorage.js | 4 +- client/src/utils/pagination.js | 16 +++++ 8 files changed, 109 insertions(+), 103 deletions(-) create mode 100644 client/src/utils/pagination.js diff --git a/client/src/containers/Connect/ConnectList/ConnectList.jsx b/client/src/containers/Connect/ConnectList/ConnectList.jsx index 45c5f0b45..ae5512bcf 100644 --- a/client/src/containers/Connect/ConnectList/ConnectList.jsx +++ b/client/src/containers/Connect/ConnectList/ConnectList.jsx @@ -14,6 +14,7 @@ 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" class ConnectList extends Root { state = { @@ -44,9 +45,12 @@ class ConnectList extends Root { } componentDidMount() { - const { searchData } = this.state; + 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 }}, () => { + this.setState({ + searchData: { search: (query.get('search'))? query.get('search') : searchData.search }, + pageNumber: (query.get('page'))? parseInt(query.get('page')) : parseInt(pageNumber) + }, () => { this.getConnectDefinitions(); }); } @@ -58,9 +62,15 @@ class ConnectList extends Root { this.setState({ loading: true }); let response = await this.getApi(uriConnectDefinitions(clusterId, connectId, search, pageNumber)); - if (response.data.results) { - this.handleData(response.data.results); - this.setState({ clusterId, totalPageNumber: response.data.page }); + let data = response.data; + if (data.results) { + this.handleData(data); + this.setState({ selectedCluster: clusterId, totalPageNumber: data.page }, () => { + 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 }); } @@ -70,20 +80,20 @@ 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(); + .then(() => { + toast.success(`Definition '${definition}' is deleted`); + this.setState({ showDeleteModal: false, definitionToDelete: '' }, () => { + this.getConnectDefinitions(); + }); + }) + .catch(() => { + this.setState({ showDeleteModal: false, topicToDelete: {} }); }); - }) - .catch(() => { - this.setState({ showDeleteModal: false, topicToDelete: {} }); - }); }; handleData = data => { let tableData = []; - tableData = data.map(connectDefinition => { + tableData = data.results.map(connectDefinition => { return { id: connectDefinition.name || '', config: JSON.stringify(connectDefinition.configs) || '', @@ -96,7 +106,7 @@ class ConnectList extends Root { }; }); - this.setState({ tableData, loading: false }); + this.setState({ tableData, loading: false, totalPageNumber: data.page }); }; showDeleteModal = deleteMessage => { @@ -131,30 +141,16 @@ class ConnectList extends Root { }); } - handlePageChange = ({ currentTarget: input }) => { - const { value } = input; - this.setState({ pageNumber: value }); - }; - handleSearch = data => { const { searchData } = data; this.setState({ pageNumber: 1, searchData }, () => { this.getConnectDefinitions(); - this.props.history.push({ - pathname: `/ui/${this.state.clusterId}/connect/${this.state.connectId}`, - search: `search=${searchData.search}` - }); }); }; handlePageChangeSubmission = value => { - const { totalPageNumber } = this.state; - if (value <= 0) { - value = 1; - } else if (value > totalPageNumber) { - value = totalPageNumber; - } - this.setState({ pageNumber: value }, () => { + let pageNumber = getPageNumber(value, this.state.totalPageNumber); + this.setState({ pageNumber: pageNumber }, () => { this.getConnectDefinitions(); }); }; @@ -213,7 +209,7 @@ class ConnectList extends Root { diff --git a/client/src/containers/ConsumerGroup/ConsumerGroupList/ConsumerGroupList.jsx b/client/src/containers/ConsumerGroup/ConsumerGroupList/ConsumerGroupList.jsx index c54e1e0f8..a2171f867 100644 --- a/client/src/containers/ConsumerGroup/ConsumerGroupList/ConsumerGroupList.jsx +++ b/client/src/containers/ConsumerGroup/ConsumerGroupList/ConsumerGroupList.jsx @@ -11,6 +11,7 @@ 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" class ConsumerGroupList extends Root { state = { @@ -30,10 +31,13 @@ class ConsumerGroupList extends Root { componentDidMount() { const { clusterId } = this.props.match.params; - const { search } = this.state; + const { search, pageNumber} = this.state; const query = new URLSearchParams(this.props.location.search); - this.setState({ selectedCluster: clusterId, search: (query.get('search'))? query.get('search') : search }, () => { + this.setState({ selectedCluster: clusterId, + search: (query.get('search'))? query.get('search') : search, + pageNumber: (query.get('page'))? parseInt(query.get('page')) : parseInt(pageNumber) + }, () => { this.getConsumerGroup(); }); } @@ -41,29 +45,16 @@ class ConsumerGroupList extends Root { handleSearch = data => { this.setState({ pageNumber: 1, search: data.searchData.search }, () => { this.getConsumerGroup(); - this.props.history.push({ - pathname: `/ui/${this.state.selectedCluster}/group`, - search: `search=${data.searchData.search}` - }); }); }; handlePageChangeSubmission = value => { - const { totalPageNumber } = this.state; - if (value <= 0) { - value = 1; - } else if (value > totalPageNumber) { - value = totalPageNumber; - } - this.setState({ pageNumber: value }, () => { + let pageNumber = getPageNumber(value, this.state.totalPageNumber); + this.setState({ pageNumber: pageNumber }, () => { this.getConsumerGroup(); }); }; - handlePageChange = ({ currentTarget: input }) => { - const { value } = input; - this.setState({ pageNumber: value }); - }; async getConsumerGroup() { const { selectedCluster, pageNumber, search } = this.state; @@ -73,7 +64,12 @@ class ConsumerGroupList extends Root { response = response.data; if (response.results) { this.handleConsumerGroup(response.results); - this.setState({ selectedCluster, totalPageNumber: response.page }); + this.setState({ selectedCluster, totalPageNumber: response.page }, () => + this.props.history.push({ + pathname: `/ui/${this.state.selectedCluster}/group`, + search: `search=${this.state.search}&page=${pageNumber}` + }) + ); } else { this.setState({ selectedCluster, consumerGroups: [], totalPageNumber: 0, loading: false }); } @@ -193,7 +189,7 @@ class ConsumerGroupList extends Root { diff --git a/client/src/containers/Schema/SchemaList/SchemaList.jsx b/client/src/containers/Schema/SchemaList/SchemaList.jsx index 01cb9146b..0ba89e3f8 100644 --- a/client/src/containers/Schema/SchemaList/SchemaList.jsx +++ b/client/src/containers/Schema/SchemaList/SchemaList.jsx @@ -15,6 +15,8 @@ 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" + class SchemaList extends Root { state = { @@ -41,10 +43,14 @@ class SchemaList extends Root { componentDidMount() { let { clusterId } = this.props.match.params; - const { searchData } = this.state; + const { searchData, pageNumber } = this.state; const query = new URLSearchParams(this.props.location.search); - this.setState({ selectedCluster: clusterId, searchData: { search: (query.get('search'))? query.get('search') : searchData.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(); }); } @@ -53,31 +59,18 @@ class SchemaList extends Root { const { searchData } = data; this.setState({ pageNumber: 1, searchData }, () => { this.getSchemaRegistry(); - this.props.history.push({ - pathname: `/ui/${this.state.selectedCluster}/schema`, - search: `search=${searchData.search}` - }); }); }; handlePageChangeSubmission = value => { - const { totalPageNumber } = this.state; - if (value <= 0) { - value = 1; - } else if (value > totalPageNumber) { - value = totalPageNumber; - } - this.setState({ pageNumber: value }, () => { + let pageNumber = parseInt(getPageNumber(value, this.state.totalPageNumber)); + this.setState({pageNumber: pageNumber}, () => { this.getSchemaRegistry(); - }); - }; - - handlePageChange = ({ currentTarget: input }) => { - const { value } = input; - this.setState({ pageNumber: value }); - }; + }) + } async getSchemaRegistry() { + const { selectedCluster, pageNumber } = this.state; const { search } = this.state.searchData; @@ -87,12 +80,19 @@ class SchemaList extends Root { endpoints.uriSchemaRegistry(selectedCluster, search, pageNumber) ); - if (response.data.results) { - this.handleSchemaRegistry(response.data.results); - this.setState({ selectedCluster, totalPageNumber: response.data.page }); + let data = response.data; + if (data.results) { + this.handleSchemaRegistry(data.results); + this.setState({ selectedCluster, totalPageNumber: data.page }, () => { + 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) { @@ -180,7 +180,7 @@ class SchemaList extends Root { diff --git a/client/src/containers/Topic/TopicList/TopicList.jsx b/client/src/containers/Topic/TopicList/TopicList.jsx index 820586258..7838390e3 100644 --- a/client/src/containers/Topic/TopicList/TopicList.jsx +++ b/client/src/containers/Topic/TopicList/TopicList.jsx @@ -14,6 +14,7 @@ import 'react-toastify/dist/ReactToastify.css'; import {Collapse} from 'react-bootstrap'; import Root from '../../../components/Root'; import {getClusterUIOptions} from "../../../utils/functions"; +import {handlePageChange, getPageNumber} from "./../../../utils/pagination" class TopicList extends Root { state = { @@ -68,10 +69,11 @@ class TopicList extends Root { const { clusterId } = this.props.match.params; const query = new URLSearchParams(this.props.location.search); const {searchData, keepSearch} = this.state; + let { pageNumber } = this.state; const uiOptions = await getClusterUIOptions(clusterId) + let searchDataTmp; let keepSearchTmp = keepSearch; - const topicListSearch = localStorage.getItem('topicListSearch'); if(topicListSearch) { searchDataTmp = JSON.parse(topicListSearch); @@ -82,9 +84,10 @@ class TopicList extends Root { topicListView: (query.get('topicListView'))? query.get('topicListView') : (uiOptions && uiOptions.topic && uiOptions.topic.defaultView)? uiOptions.topic.defaultView : searchData.topicListView, } + pageNumber = (query.get('page'))? parseInt(query.get('page')) : parseInt(pageNumber) } - this.setState({selectedCluster: clusterId, searchData: searchDataTmp, keepSearch: keepSearchTmp, uiOptions: (uiOptions)? uiOptions.topic : {}}, callBackFunction); + this.setState({selectedCluster: clusterId, searchData: searchDataTmp, keepSearch: keepSearchTmp, uiOptions: (uiOptions)? uiOptions.topic : {}, pageNumber: pageNumber}, callBackFunction); } showDeleteModal = deleteMessage => { @@ -124,36 +127,31 @@ class TopicList extends Root { this.handleKeepSearchChange(data.keepSearch); this.props.history.push({ pathname: `/ui/${this.state.selectedCluster}/topic`, - search: `search=${searchData.search}&topicListView=${searchData.topicListView}` + search: `search=${searchData.search}&topicListView=${this.state.searchData.topicListView}&page=${this.state.pageNumber}` }); + }); }; handlePageChangeSubmission = value => { - const { totalPageNumber } = this.state; - if (value <= 0) { - value = 1; - } else if (value > totalPageNumber) { - value = totalPageNumber; - } + let pageNumber = getPageNumber(value, this.state.totalPageNumber); - this.setState({ pageNumber: value }, () => { + this.setState({ pageNumber: pageNumber }, () => { this.getTopics(); + this.props.history.push({ + pathname: `/ui/${this.state.selectedCluster}/topic`, + search: `search=${this.state.searchData.search}&topicListView=${this.state.searchData.topicListView}&page=${pageNumber}` + }); }); }; - handlePageChange = ({ currentTarget: input }) => { - const { value } = input; - this.setState({ pageNumber: value }); - }; - async getTopics() { const { selectedCluster, pageNumber } = this.state; const { search, topicListView } = this.state.searchData; this.setState({ loading: true } ); - let data = await this.getApi(uriTopics(selectedCluster, search, topicListView, pageNumber)); - data = data.data; + let response = await this.getApi(uriTopics(selectedCluster, search, topicListView, pageNumber)); + let data = response.data; if (data) { if (data.results) { @@ -421,13 +419,13 @@ class TopicList extends Root { }} onKeepSearchChange={value => { this.handleKeepSearchChange(value); - }} - doSubmit={this.handleSearch} + }} + doSubmit={this.handleSearch} /> diff --git a/client/src/utils/Routes.js b/client/src/utils/Routes.js index 65132e046..f3374f450 100644 --- a/client/src/utils/Routes.js +++ b/client/src/utils/Routes.js @@ -23,10 +23,10 @@ import SchemaCreate from '../containers/Schema/SchemaCreate/SchemaCreate'; import ConsumerGroupUpdate from '../containers/ConsumerGroup/ConsumerGroupDetail/ConsumerGroupUpdate'; import AclDetails from '../containers/Acl/AclDetail'; import Login from '../containers/Login'; -import Settings from "../containers/Settings/Settings"; +import Settings from '../containers/Settings/Settings'; import { organizeRoles } from './converters'; import {uriAuths, uriClusters, uriCurrentUser} from './endpoints'; -import Root from "../components/Root"; +import Root from '../components/Root'; class Routes extends Root { state = { @@ -62,7 +62,7 @@ class Routes extends Root { } console.error('Error:', err); } - }; + } _initUserAndAuth() { const requests = [this.getApi(uriCurrentUser()), this.getApi(uriAuths())]; diff --git a/client/src/utils/functions.js b/client/src/utils/functions.js index c500688ad..41a54a432 100644 --- a/client/src/utils/functions.js +++ b/client/src/utils/functions.js @@ -1,6 +1,6 @@ -import {uriUIOptions} from "./endpoints"; -import {getUIOptions, setUIOptions} from "./localstorage"; -import {get} from "./api"; +import {uriUIOptions} from './endpoints'; +import {getUIOptions, setUIOptions} from './localstorage'; +import {get} from './api'; export const getSelectedTab = (props, tabs) => { const url = props.location.pathname.split('/'); diff --git a/client/src/utils/localstorage.js b/client/src/utils/localstorage.js index ab92d4683..c3ee2ff4f 100644 --- a/client/src/utils/localstorage.js +++ b/client/src/utils/localstorage.js @@ -1,7 +1,7 @@ export const getUIOptions = (cluster) => { const uiOptions = localStorage.getItem('uiOptions'); - if(uiOptions != null) { + if(uiOptions !== null) { const objParsed = JSON.parse(uiOptions); return objParsed[cluster]; } else { @@ -12,7 +12,7 @@ export const getUIOptions = (cluster) => { export const setUIOptions = (cluster, newUIOptions) => { const uiOptions = localStorage.getItem('uiOptions'); - if(uiOptions != null) { + if(uiOptions !== null) { const objParsed = JSON.parse(uiOptions); objParsed[cluster] = newUIOptions; localStorage.setItem('uiOptions', JSON.stringify(objParsed)); diff --git a/client/src/utils/pagination.js b/client/src/utils/pagination.js new file mode 100644 index 000000000..35ccb6e66 --- /dev/null +++ b/client/src/utils/pagination.js @@ -0,0 +1,16 @@ + +export const handlePageChange = ({ currentTarget: input, state }) => { + const { value } = input; + state.pageNumber = value; +}; + +export const getPageNumber = (value, totalPageNumber) => { + if (value <= 0) { + value = 1; + } else if (value > totalPageNumber) { + value = totalPageNumber; + } + return value; +}; + +export default {handlePageChange, getPageNumber};