You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by su...@apache.org on 2021/03/21 01:00:37 UTC
[apisix-dashboard] branch master updated: feat: save list page's
meta status (#1584)
This is an automated email from the ASF dual-hosted git repository.
sunyi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git
The following commit(s) were added to refs/heads/master by this push:
new 3da7370 feat: save list page's meta status (#1584)
3da7370 is described below
commit 3da737017121632a47a28bcd3460a10f6f309250
Author: guoqqqi <72...@users.noreply.github.com>
AuthorDate: Sun Mar 21 09:00:28 2021 +0800
feat: save list page's meta status (#1584)
---
web/cypress/fixtures/selector.json | 9 +-
.../plugin/create-edit-delete-plugin.spec.js | 6 +-
.../service/create-edit-delete-service.spec.js | 7 +-
.../service/save-paginator-status.spec.js | 98 ++++++++++++++++++++++
web/src/pages/Consumer/List.tsx | 18 +++-
web/src/pages/Plugin/List.tsx | 16 ++++
web/src/pages/PluginTemplate/List.tsx | 16 ++++
web/src/pages/Route/List.tsx | 20 ++++-
web/src/pages/SSL/List.tsx | 18 +++-
web/src/pages/Service/List.tsx | 18 +++-
web/src/pages/Upstream/List.tsx | 18 +++-
11 files changed, 232 insertions(+), 12 deletions(-)
diff --git a/web/cypress/fixtures/selector.json b/web/cypress/fixtures/selector.json
index 15de3f7..121adf1 100644
--- a/web/cypress/fixtures/selector.json
+++ b/web/cypress/fixtures/selector.json
@@ -71,5 +71,12 @@
"customSelector": "[title=Custom]",
"notificationClose": ".anticon-close",
"redirectURIInput": "#redirectURI",
- "redirectCodeSelector": "#ret_code"
+ "redirectCodeSelector": "#ret_code",
+
+ "paginationOptions": ".ant-pagination-options",
+ "fiftyPerPage": "[title=\"50 / page\"]",
+ "twentyPerPage": "[title=\"20 / page\"]",
+ "pageList": ".ant-table-pagination-right",
+ "pageTwo": ".ant-pagination-item-2",
+ "pageTwoActived": ".ant-pagination-item-2.ant-pagination-item-active"
}
diff --git a/web/cypress/integration/plugin/create-edit-delete-plugin.spec.js b/web/cypress/integration/plugin/create-edit-delete-plugin.spec.js
index dcde1b4..136ab49 100644
--- a/web/cypress/integration/plugin/create-edit-delete-plugin.spec.js
+++ b/web/cypress/integration/plugin/create-edit-delete-plugin.spec.js
@@ -52,8 +52,12 @@ context('Create and Delete Plugin List', () => {
it('should delete plugin list', function () {
cy.visit('/plugin/list');
-
cy.get(this.domSelector.refresh).click();
+ cy.get(this.domSelector.paginationOptions).click();
+ cy.contains('50 / page').should('be.visible').click();
+ cy.get(this.domSelector.fiftyPerPage).should('exist');
+ cy.location('href').should('include', 'pageSize=50');
+
cy.get(this.domSelector.deleteButton, { timeout }).should('exist').each(function ($el) {
cy.wrap($el).click().click({ timeout });
cy.contains('button', 'Confirm').click({ force: true });
diff --git a/web/cypress/integration/service/create-edit-delete-service.spec.js b/web/cypress/integration/service/create-edit-delete-service.spec.js
index e7e3507..83f5641 100644
--- a/web/cypress/integration/service/create-edit-delete-service.spec.js
+++ b/web/cypress/integration/service/create-edit-delete-service.spec.js
@@ -16,7 +16,7 @@
*/
/* eslint-disable no-undef */
-context('create and delete service ', () => {
+context('Create and Delete Service ', () => {
beforeEach(() => {
cy.login();
@@ -50,7 +50,7 @@ context('create and delete service ', () => {
cy.get(this.domSelector.drawer).should('be.visible');
cy.get(this.domSelector.codemirrorScroll).within(() => {
- cy.contains('upstream').should("exist");
+ cy.contains('upstream').should('exist');
cy.contains(this.data.serviceName).should('exist');
});
});
@@ -65,7 +65,7 @@ context('create and delete service ', () => {
// Confirm whether the created data is saved.
cy.get(this.domSelector.nodes_0_host).should('value', this.data.ip1);
- cy.get(this.domSelector.description).should('value', this.data.description)
+ cy.get(this.domSelector.description).should('value', this.data.description);
cy.get(this.domSelector.name).clear().type(this.data.serviceName2);
cy.get(this.domSelector.description).clear().type(this.data.description2);
cy.get(this.domSelector.nodes_0_host).click();
@@ -101,4 +101,3 @@ context('create and delete service ', () => {
cy.get(this.domSelector.notification).should('contain', this.data.deleteServiceSuccess);
});
});
-
diff --git a/web/cypress/integration/service/save-paginator-status.spec.js b/web/cypress/integration/service/save-paginator-status.spec.js
new file mode 100644
index 0000000..895768b
--- /dev/null
+++ b/web/cypress/integration/service/save-paginator-status.spec.js
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* eslint-disable no-undef */
+import defaultSettings from '../../../config/defaultSettings';
+
+context('Save Paginator Status', () => {
+ const timeout = 300;
+ const token = localStorage.getItem('token');
+ const { SERVE_ENV = 'dev' } = Cypress.env();
+
+ beforeEach(() => {
+ cy.login();
+
+ cy.fixture('selector.json').as('domSelector');
+ cy.fixture('data.json').as('data');
+ });
+
+ it('should create 11 test services', function () {
+ cy.visit('/');
+ cy.contains('Service').click();
+
+ for (let i = 0; i <= 10; i++) {
+ cy.request({
+ method: 'POST',
+ url: `${defaultSettings.serveUrlMap[SERVE_ENV]}/apisix/admin/services`,
+ headers: {
+ Authorization: token,
+ },
+ body: {
+ upstream: {
+ nodes: {"39.97.63.215:80": 1},
+ timeout: {connect: 6, read: 6, send: 6},
+ type: 'roundrobin',
+ pass_host: 'pass',
+ },
+ enable_websocket: true,
+ name: `${this.data.serviceName}${i}`,
+ }
+ }).then((res) => {
+ expect(res.body.code).to.equal(0);
+ });
+ }
+ cy.get(this.domSelector.pageList).should('be.visible');
+ });
+
+ it('should save paginator\' status', function () {
+ cy.visit('/');
+ cy.contains('Service').click();
+
+ // Test page status
+ cy.get(this.domSelector.pageList).should('be.visible');
+ cy.get(this.domSelector.pageTwo).click();
+ cy.get(this.domSelector.pageTwoActived).should('exist');
+ cy.location('href').should('include', 'page=2');
+
+ cy.reload();
+ cy.get(this.domSelector.pageTwoActived).should('exist');
+ cy.location('href').should('include', 'page=2');
+
+ // Test pageSize status
+ cy.get(this.domSelector.paginationOptions).click();
+ cy.contains('20 / page').should('be.visible').click();
+ cy.get(this.domSelector.twentyPerPage).should('exist');
+ cy.location('href').should('include', 'pageSize=20');
+
+ cy.reload();
+ cy.get(this.domSelector.twentyPerPage).should('exist');
+ cy.location('href').should('include', 'pageSize=20');
+ });
+
+ it('should delete test service', function () {
+ cy.visit('/service/list?page=1&pageSize=20');
+ cy.reload();
+ cy.contains('Service List').should('be.visible');
+ cy.get(this.domSelector.deleteButton, { timeout: 300 })
+ .should('exist')
+ .each(function ($el) {
+ cy.wrap($el).click().click({ timeout });
+ cy.contains('button', 'Confirm').click({ force: true });
+ cy.get(this.domSelector.notification).should('contain', this.data.deleteServiceSuccess);
+ cy.get(this.domSelector.notificationCloseIcon).click().should('not.exist');
+ });
+ });
+});
diff --git a/web/src/pages/Consumer/List.tsx b/web/src/pages/Consumer/List.tsx
index 26214d0..0957383 100644
--- a/web/src/pages/Consumer/List.tsx
+++ b/web/src/pages/Consumer/List.tsx
@@ -14,13 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React, { useRef, useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import type { ProColumns, ActionType } from '@ant-design/pro-table';
import { Popconfirm, Button, notification } from 'antd';
import { history, useIntl } from 'umi';
import { PlusOutlined } from '@ant-design/icons';
+import querystring from 'query-string'
import { timestampToLocaleString } from '@/helpers';
import { RawDataEditor } from '@/components/RawDataEditor';
@@ -32,6 +33,16 @@ const Page: React.FC = () => {
const { formatMessage } = useIntl();
const [rawDataEditorVisible, setRawDataEditorVisible] = useState(false);
const [rawData, setRawData] = useState({});
+ const [paginationConfig, setPaginationConfig] = useState({ pageSize: 10, current: 1 });
+
+ const savePageList = (page = 1, pageSize = 10) => {
+ history.replace(`/consumer/list?page=${page}&pageSize=${pageSize}`);
+ };
+
+ useEffect(() => {
+ const { page = 1, pageSize = 10 } = querystring.parse(window.location.search);
+ setPaginationConfig({ pageSize: Number(pageSize), current: Number(page) });
+ }, [window.location.search]);
const columns: ProColumns<ConsumerModule.ResEntity>[] = [
{
@@ -100,6 +111,11 @@ const Page: React.FC = () => {
columns={columns}
rowKey="id"
request={fetchList}
+ pagination={{
+ onChange: (page, pageSize?) => savePageList(page, pageSize),
+ pageSize: paginationConfig.pageSize,
+ current: paginationConfig.current,
+ }}
search={{
searchText: formatMessage({ id: 'component.global.search' }),
resetText: formatMessage({ id: 'component.global.reset' }),
diff --git a/web/src/pages/Plugin/List.tsx b/web/src/pages/Plugin/List.tsx
index 31e4fc0..b8917c8 100644
--- a/web/src/pages/Plugin/List.tsx
+++ b/web/src/pages/Plugin/List.tsx
@@ -22,6 +22,7 @@ import type { ActionType, ProColumns } from '@ant-design/pro-table';
import { Button, Popconfirm, Space, notification } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { omit } from 'lodash';
+import querystring from 'query-string'
import PluginDetail from '@/components/Plugin/PluginDetail';
@@ -34,6 +35,11 @@ const Page: React.FC = () => {
const [initialData, setInitialData] = useState({});
const [pluginList, setPluginList] = useState<PluginComponent.Meta[]>([]);
const [name, setName] = useState('');
+ const [paginationConfig, setPaginationConfig] = useState({ pageSize: 10, current: 1 });
+
+ const savePageList = (page = 1, pageSize = 10) => {
+ history.replace(`/plugin/list?page=${page}&pageSize=${pageSize}`);
+ };
useEffect(() => {
fetchPluginList().then(setPluginList);
@@ -51,6 +57,11 @@ const Page: React.FC = () => {
}
}, [name]);
+ useEffect(() => {
+ const { page = 1, pageSize = 10 } = querystring.parse(window.location.search);
+ setPaginationConfig({ pageSize: Number(pageSize), current: Number(page) });
+ }, [window.location.search]);
+
const columns: ProColumns<PluginModule.TransformedPlugin>[] = [
{
title: formatMessage({ id: 'component.global.name' }),
@@ -142,6 +153,11 @@ const Page: React.FC = () => {
search={false}
columns={columns}
request={fetchList}
+ pagination={{
+ onChange: (page, pageSize?) => savePageList(page, pageSize),
+ pageSize: paginationConfig.pageSize,
+ current: paginationConfig.current,
+ }}
toolBarRender={() => [
<Button type="primary" onClick={() => history.push('/plugin/market')}>
<PlusOutlined />
diff --git a/web/src/pages/PluginTemplate/List.tsx b/web/src/pages/PluginTemplate/List.tsx
index 6e0fa45..69f92d1 100644
--- a/web/src/pages/PluginTemplate/List.tsx
+++ b/web/src/pages/PluginTemplate/List.tsx
@@ -21,14 +21,25 @@ import ProTable from '@ant-design/pro-table';
import type { ActionType, ProColumns } from '@ant-design/pro-table';
import { Button, notification, Popconfirm, Select, Space, Tag } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
+import querystring from 'query-string'
import { fetchList, remove, fetchLabelList } from './service';
const Page: React.FC = () => {
const ref = useRef<ActionType>();
const [labelList, setLabelList] = useState<LabelList>({});
+ const [paginationConfig, setPaginationConfig] = useState({ pageSize: 10, current: 1 });
const { formatMessage } = useIntl();
+ const savePageList = (page = 1, pageSize = 10) => {
+ history.replace(`/plugin-template/list?page=${page}&pageSize=${pageSize}`);
+ };
+
+ useEffect(() => {
+ const { page = 1, pageSize = 10 } = querystring.parse(window.location.search);
+ setPaginationConfig({ pageSize: Number(pageSize), current: Number(page) });
+ }, [window.location.search]);
+
useEffect(() => {
fetchLabelList().then(setLabelList);
}, []);
@@ -142,6 +153,11 @@ const Page: React.FC = () => {
rowKey="id"
columns={columns}
request={fetchList}
+ pagination={{
+ onChange: (page, pageSize?) => savePageList(page, pageSize),
+ pageSize: paginationConfig.pageSize,
+ current: paginationConfig.current,
+ }}
search={{
searchText: formatMessage({ id: 'component.global.search' }),
resetText: formatMessage({ id: 'component.global.reset' }),
diff --git a/web/src/pages/Route/List.tsx b/web/src/pages/Route/List.tsx
index dcc8e3d..c799bf2 100644
--- a/web/src/pages/Route/List.tsx
+++ b/web/src/pages/Route/List.tsx
@@ -37,6 +37,7 @@ import { js_beautify } from 'js-beautify';
import yaml from 'js-yaml';
import moment from 'moment';
import { saveAs } from 'file-saver';
+import querystring from 'query-string'
import { timestampToLocaleString } from '@/helpers';
import type { RcFile } from 'antd/lib/upload';
@@ -75,11 +76,21 @@ const Page: React.FC = () => {
const [showImportModal, setShowImportModal] = useState(false);
const [rawDataEditorVisible, setRawDataEditorVisible] = useState(false);
const [rawData, setRawData] = useState({});
+ const [paginationConfig, setPaginationConfig] = useState({ pageSize: 10, current: 1 });
+
+ const savePageList = (page = 1, pageSize = 10) => {
+ history.replace(`/routes/list?page=${page}&pageSize=${pageSize}`);
+ };
useEffect(() => {
fetchLabelList().then(setLabelList);
}, []);
+ useEffect(() => {
+ const { page = 1, pageSize = 10 } = querystring.parse(window.location.search);
+ setPaginationConfig({ pageSize: Number(pageSize), current: Number(page) });
+ }, [window.location.search]);
+
const rowSelection = {
selectedRowKeys,
onChange: (currentSelectKeys: string[]) => {
@@ -317,8 +328,8 @@ const Page: React.FC = () => {
{record.status ? (
<Tag color="green">{formatMessage({ id: 'page.route.published' })}</Tag>
) : (
- <Tag color="red">{formatMessage({ id: 'page.route.unpublished' })}</Tag>
- )}
+ <Tag color="red">{formatMessage({ id: 'page.route.unpublished' })}</Tag>
+ )}
</>
),
renderFormItem: (_, { type }) => {
@@ -421,6 +432,11 @@ const Page: React.FC = () => {
rowKey="id"
columns={columns}
request={fetchList}
+ pagination={{
+ onChange: (page, pageSize?) => savePageList(page, pageSize),
+ pageSize: paginationConfig.pageSize,
+ current: paginationConfig.current,
+ }}
search={{
searchText: formatMessage({ id: 'component.global.search' }),
resetText: formatMessage({ id: 'component.global.reset' }),
diff --git a/web/src/pages/SSL/List.tsx b/web/src/pages/SSL/List.tsx
index f66cfa0..56e5737 100644
--- a/web/src/pages/SSL/List.tsx
+++ b/web/src/pages/SSL/List.tsx
@@ -14,13 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React, { useRef } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import type { ProColumns, ActionType } from '@ant-design/pro-table';
import { Button, Popconfirm, notification, Tag } from 'antd';
import { useIntl, history } from 'umi';
import { PlusOutlined } from '@ant-design/icons';
+import querystring from 'query-string'
import { fetchList, remove as removeSSL } from '@/pages/SSL/service';
import { timestampToLocaleString } from '@/helpers';
@@ -28,6 +29,16 @@ import { timestampToLocaleString } from '@/helpers';
const Page: React.FC = () => {
const tableRef = useRef<ActionType>();
const { formatMessage } = useIntl();
+ const [paginationConfig, setPaginationConfig] = useState({ pageSize: 10, current: 1 });
+
+ const savePageList = (page = 1, pageSize = 10) => {
+ history.replace(`/ssl/list?page=${page}&pageSize=${pageSize}`);
+ };
+
+ useEffect(() => {
+ const { page = 1, pageSize = 10 } = querystring.parse(window.location.search);
+ setPaginationConfig({ pageSize: Number(pageSize), current: Number(page) });
+ }, [window.location.search]);
const columns: ProColumns<SSLModule.ResponseBody>[] = [
{
@@ -103,6 +114,11 @@ const Page: React.FC = () => {
columns={columns}
actionRef={tableRef}
request={fetchList}
+ pagination={{
+ onChange: (page, pageSize?) => savePageList(page, pageSize),
+ pageSize: paginationConfig.pageSize,
+ current: paginationConfig.current,
+ }}
search={{
searchText: formatMessage({ id: 'component.global.search' }),
resetText: formatMessage({ id: 'component.global.reset' }),
diff --git a/web/src/pages/Service/List.tsx b/web/src/pages/Service/List.tsx
index 4917fba..467be78 100644
--- a/web/src/pages/Service/List.tsx
+++ b/web/src/pages/Service/List.tsx
@@ -14,13 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React, { useRef, useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import { history, useIntl } from 'umi';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import type { ActionType, ProColumns } from '@ant-design/pro-table';
import { PlusOutlined } from '@ant-design/icons';
import { Button, notification, Popconfirm, Space } from 'antd';
+import querystring from 'query-string'
import { RawDataEditor } from '@/components/RawDataEditor';
import { fetchList, remove } from './service';
@@ -30,6 +31,16 @@ const Page: React.FC = () => {
const { formatMessage } = useIntl();
const [rawDataEditorVisible, setRawDataEditorVisible] = useState(false);
const [rawData, setRawData] = useState({});
+ const [paginationConfig, setPaginationConfig] = useState({ pageSize: 10, current: 1 });
+
+ const savePageList = (page = 1, pageSize = 10) => {
+ history.replace(`/service/list?page=${page}&pageSize=${pageSize}`);
+ };
+
+ useEffect(() => {
+ const { page = 1, pageSize = 10 } = querystring.parse(window.location.search);
+ setPaginationConfig({ pageSize: Number(pageSize), current: Number(page) });
+ }, [window.location.search]);
const columns: ProColumns<ServiceModule.ResponseBody>[] = [
{
@@ -98,6 +109,11 @@ const Page: React.FC = () => {
rowKey="id"
columns={columns}
request={fetchList}
+ pagination={{
+ onChange: (page, pageSize?) => savePageList(page, pageSize),
+ pageSize: paginationConfig.pageSize,
+ current: paginationConfig.current,
+ }}
search={{
searchText: formatMessage({ id: 'component.global.search' }),
resetText: formatMessage({ id: 'component.global.reset' }),
diff --git a/web/src/pages/Upstream/List.tsx b/web/src/pages/Upstream/List.tsx
index 5158681..ce5d6e7 100644
--- a/web/src/pages/Upstream/List.tsx
+++ b/web/src/pages/Upstream/List.tsx
@@ -14,13 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React, { useRef, useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import type { ProColumns, ActionType } from '@ant-design/pro-table';
import { Popconfirm, Button, notification } from 'antd';
import { history, useIntl } from 'umi';
import { PlusOutlined } from '@ant-design/icons';
+import querystring from 'query-string'
import { RawDataEditor } from '@/components/RawDataEditor';
import { timestampToLocaleString } from '@/helpers';
@@ -31,9 +32,19 @@ const Page: React.FC = () => {
const ref = useRef<ActionType>();
const [rawDataEditorVisible, setRawDataEditorVisible] = useState(false);
const [rawData, setRawData] = useState({});
+ const [paginationConfig, setPaginationConfig] = useState({ pageSize: 10, current: 1 });
const { formatMessage } = useIntl();
+ const savePageList = (page = 1, pageSize = 10) => {
+ history.replace(`/upstream/list?page=${page}&pageSize=${pageSize}`);
+ };
+
+ useEffect(() => {
+ const { page = 1, pageSize = 10 } = querystring.parse(window.location.search);
+ setPaginationConfig({ pageSize: Number(pageSize), current: Number(page) });
+ }, [window.location.search]);
+
const columns: ProColumns<UpstreamModule.ResponseBody>[] = [
{
title: formatMessage({ id: 'page.upstream.list.name' }),
@@ -104,6 +115,11 @@ const Page: React.FC = () => {
columns={columns}
rowKey="id"
request={fetchList}
+ pagination={{
+ onChange: (page, pageSize?) => savePageList(page, pageSize),
+ pageSize: paginationConfig.pageSize,
+ current: paginationConfig.current,
+ }}
search={{
searchText: formatMessage({ id: 'component.global.search' }),
resetText: formatMessage({ id: 'component.global.reset' }),