This is an automated email from the ASF dual-hosted git repository. juzhiyuan 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 2f112ff feat: improve upstream i18n (#1097) 2f112ff is described below commit 2f112ffcb4942a392c3a21acece5a712a5d5c1ab Author: guoqqqi <72343596+guoq...@users.noreply.github.com> AuthorDate: Mon Dec 28 22:47:29 2020 +0800 feat: improve upstream i18n (#1097) * feat: "upstream" i18n * feat: "menu" i18n * feat: "button" i18n * fix: 'query' button for 'search' * fix: e2e text * fix: i18n * fix: i18n * Update web/src/components/RightContent/AvatarDropdown.tsx * Update web/src/locales/en-US/menu.ts * Update web/src/locales/zh-CN/menu.ts * style: format codes (#1) Co-authored-by: 琚致远 <juzhiy...@apache.org> Co-authored-by: liuxiran <belovedx...@126.com> --- web/cypress.json | 8 +- web/cypress/fixtures/certificate.json | 18 +- .../consumer/create_and_delete_consumer.spec.js | 30 +-- .../integration/metrics/metrics-smoketest.spec.js | 10 +- .../route/create-and-delete-route.spec.js | 20 +- .../settings/settings-smoketest.spec.js | 14 +- web/cypress/integration/ssl/ssl-smoketest.spec.js | 11 +- .../upstream/create_and_delete_upstream.spec.js | 14 +- web/cypress/integration/user/login.spec.js | 4 +- web/cypress/integration/user/logout.spec.js | 6 +- web/cypress/plugins/index.js | 2 +- web/cypress/support/commands.js | 25 +-- web/cypress/support/index.js | 6 +- web/src/components/Plugin/PluginPage.tsx | 6 +- web/src/components/RightContent/AvatarDropdown.tsx | 11 +- web/src/components/Upstream/UpstreamForm.tsx | 223 +++++++++++++-------- web/src/helpers.tsx | 16 +- web/src/locales/en-US/component.ts | 2 + web/src/locales/en-US/menu.ts | 1 - web/src/locales/zh-CN/component.ts | 2 + web/src/locales/zh-CN/menu.ts | 1 - web/src/pages/Consumer/List.tsx | 4 + web/src/pages/Route/Create.tsx | 11 +- web/src/pages/Route/List.tsx | 26 ++- .../Route/components/DebugViews/DebugDrawView.tsx | 2 +- .../pages/Route/components/Step1/LabelsDrawer.tsx | 8 +- web/src/pages/Route/components/Step1/MetaView.tsx | 2 +- .../Route/components/Step1/RequestConfigView.tsx | 21 +- web/src/pages/Route/constants.ts | 5 +- web/src/pages/Route/service.ts | 10 +- web/src/pages/Route/transform.ts | 12 +- web/src/pages/Route/typing.d.ts | 10 +- web/src/pages/SSL/List.tsx | 4 + web/src/pages/ServerInfo/List.tsx | 2 +- web/src/pages/ServerInfo/service.ts | 6 +- web/src/pages/Service/Create.tsx | 81 ++++---- web/src/pages/Service/List.tsx | 41 ++-- web/src/pages/Service/components/Step1.tsx | 46 ++--- web/src/pages/Service/locales/en-US.ts | 8 +- web/src/pages/Service/locales/zh-CN.ts | 8 +- web/src/pages/Service/service.ts | 5 +- web/src/pages/Service/typing.d.ts | 51 +++-- web/src/pages/Upstream/Create.tsx | 12 +- web/src/pages/Upstream/List.tsx | 28 +-- web/src/pages/Upstream/components/Step1.tsx | 10 +- web/src/pages/Upstream/locales/en-US.ts | 155 +++++++------- web/src/pages/Upstream/locales/zh-CN.ts | 154 +++++++------- 47 files changed, 627 insertions(+), 525 deletions(-) diff --git a/web/cypress.json b/web/cypress.json index a326fda..b937532 100644 --- a/web/cypress.json +++ b/web/cypress.json @@ -1,6 +1,6 @@ { - "viewportWidth": 1920, - "viewportHeight": 1080, - "baseUrl": "http://localhost:8000", - "video": false + "viewportWidth": 1920, + "viewportHeight": 1080, + "baseUrl": "http://localhost:8000", + "video": false } diff --git a/web/cypress/fixtures/certificate.json b/web/cypress/fixtures/certificate.json index a7a36d7..b29126e 100644 --- a/web/cypress/fixtures/certificate.json +++ b/web/cypress/fixtures/certificate.json @@ -1,11 +1,11 @@ { - "valid": { - "cert": "-----BEGIN CERTIFICATE-----\nMIIENzCCAx+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCQ04x\nEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRQwEgYDVQQK\nDAtGaXNoZHJvd25lZDEcMBoGA1UEAwwTRmlzaGRyb3duZWQgUk9PVCBDQTAeFw0y\nMDExMDYwOTQ3NDhaFw0yMjExMDYwOTQ3NDhaMH8xCzAJBgNVBAYTAkNOMRIwEAYD\nVQQIDAlHdWFuZ2RvbmcxEjAQBgNVBAcMCUd1YW5nemhvdTEUMBIGA1UECgwLRmlz\naGRyb3duZWQxFzAVBgNVBAsMDnd3dy50ZXN0aGouY29tMRkwFwYDVQQDDBAqLnd3\ndy50ZXN0aGouY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC [...] - "key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzt2VU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0oh\nWMKzjmzauaMYXUDPfQ8yc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaW\nSNuPm73C26R6en/Jgu8I09c+gsBkhNykcnLevR5YPw2mOOKgLllmpCJsjqMkUUF1\nSLI503ZK2hVH6FdSntBSYDbQVJVQ8j3M71eKr/D8Z5wN4Px41Y2bTke+xXm/2x5Y\nRkZdtLCx/rbXPnYLruhG/C7aLqlA/ykQV0AWQgu1tc5gnAcT3mb/3y7GlybC8poM\nNPcEWic05hBJhpxlDNllwmUpcLEI3orAfbZnBwIDAQABAoIBAQCGvLCMP3iB0oOW\nLC4pAwelpuV+8d/MhOjajurCmEoKqMSs+K2roHVPKPt1uhMeeh4q+ [...] - "sni": "*.www.testhj.com" - }, - "invalid": { - "cert": "-----BEGIN CERTIFICATE-----\nMIIENzCCAx+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCQ04x\nEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRQwEgYDVQQK\n-----END CERTIFICATE-----", - "key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzt2VU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0oh\nWMKzjmzauaMYXUDPfQ8yc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaW\n-----END RSA PRIVATE KEY-----" - } + "valid": { + "cert": "-----BEGIN CERTIFICATE-----\nMIIENzCCAx+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCQ04x\nEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRQwEgYDVQQK\nDAtGaXNoZHJvd25lZDEcMBoGA1UEAwwTRmlzaGRyb3duZWQgUk9PVCBDQTAeFw0y\nMDExMDYwOTQ3NDhaFw0yMjExMDYwOTQ3NDhaMH8xCzAJBgNVBAYTAkNOMRIwEAYD\nVQQIDAlHdWFuZ2RvbmcxEjAQBgNVBAcMCUd1YW5nemhvdTEUMBIGA1UECgwLRmlz\naGRyb3duZWQxFzAVBgNVBAsMDnd3dy50ZXN0aGouY29tMRkwFwYDVQQDDBAqLnd3\ndy50ZXN0aGouY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCg [...] + "key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzt2VU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0oh\nWMKzjmzauaMYXUDPfQ8yc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaW\nSNuPm73C26R6en/Jgu8I09c+gsBkhNykcnLevR5YPw2mOOKgLllmpCJsjqMkUUF1\nSLI503ZK2hVH6FdSntBSYDbQVJVQ8j3M71eKr/D8Z5wN4Px41Y2bTke+xXm/2x5Y\nRkZdtLCx/rbXPnYLruhG/C7aLqlA/ykQV0AWQgu1tc5gnAcT3mb/3y7GlybC8poM\nNPcEWic05hBJhpxlDNllwmUpcLEI3orAfbZnBwIDAQABAoIBAQCGvLCMP3iB0oOW\nLC4pAwelpuV+8d/MhOjajurCmEoKqMSs+K2roHVPKPt1uhMeeh4 [...] + "sni": "*.www.testhj.com" + }, + "invalid": { + "cert": "-----BEGIN CERTIFICATE-----\nMIIENzCCAx+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCQ04x\nEjAQBgNVBAgMCUd1YW5nZG9uZzESMBAGA1UEBwwJR3Vhbmd6aG91MRQwEgYDVQQK\n-----END CERTIFICATE-----", + "key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAzt2VU3JAtNkiUhC/FKA0D3z9gRHaNR2+JYqnMHbetXJXF0oh\nWMKzjmzauaMYXUDPfQ8yc7leR6Gj9Ow5A0sUwlSdH1P0viM1gnQj0kLxeb59vQaW\n-----END RSA PRIVATE KEY-----" + } } diff --git a/web/cypress/integration/consumer/create_and_delete_consumer.spec.js b/web/cypress/integration/consumer/create_and_delete_consumer.spec.js index bae929d..e434df7 100644 --- a/web/cypress/integration/consumer/create_and_delete_consumer.spec.js +++ b/web/cypress/integration/consumer/create_and_delete_consumer.spec.js @@ -21,13 +21,13 @@ context('Create and Delete Consumer', () => { const sleepTime = 100; const domSelectors = { notification: '.ant-notification-notice-message', - pluginsCard: '.ant-card' + pluginsCard: '.ant-card', }; beforeEach(() => { - // init login + // init login cy.login(); - }) + }); it('creates consumer with key-auth', () => { // go to consumer create page @@ -45,14 +45,16 @@ context('Create and Delete Consumer', () => { // plugin config cy.contains(domSelectors.pluginsCard, 'key-auth').within(() => { cy.get('button').first().click(); - }) + }); // edit codemirror cy.get('.CodeMirror') .first() .then((editor) => { - editor[0].CodeMirror.setValue(JSON.stringify({ - "key": "test" - })); + editor[0].CodeMirror.setValue( + JSON.stringify({ + key: 'test', + }), + ); cy.contains('button', 'Submit').click(); }); cy.contains('button', 'Next').click(); @@ -64,7 +66,7 @@ context('Create and Delete Consumer', () => { it('delete the consumer', () => { cy.visit('/'); cy.contains('Consumer').click(); - cy.wait(sleepTime * 5) + cy.wait(sleepTime * 5); cy.contains(name).siblings().contains('Delete').click(); cy.contains('button', 'Confirm').click(); cy.get(domSelectors.notification).should('contain', 'Delete Consumer Successfully'); @@ -86,16 +88,18 @@ context('Create and Delete Consumer', () => { // plugin config cy.contains(domSelectors.pluginsCard, 'key-auth').within(() => { cy.get('button').first().click(); - }) + }); // edit codeMirror cy.get('.CodeMirror') .first() .then((editor) => { - editor[0].CodeMirror.setValue(JSON.stringify({ - "key_not_exst": "test" - })); + editor[0].CodeMirror.setValue( + JSON.stringify({ + key_not_exst: 'test', + }), + ); cy.contains('button', 'Submit').click(); }); cy.get(domSelectors.notification).should('contain', 'Invalid plugin data'); }); -}) +}); diff --git a/web/cypress/integration/metrics/metrics-smoketest.spec.js b/web/cypress/integration/metrics/metrics-smoketest.spec.js index 21ed446..cd10c4a 100644 --- a/web/cypress/integration/metrics/metrics-smoketest.spec.js +++ b/web/cypress/integration/metrics/metrics-smoketest.spec.js @@ -18,13 +18,13 @@ context('metrics page smoke test', () => { const domSelectors = { - pageContent: '.ant-pro-page-container' + pageContent: '.ant-pro-page-container', }; beforeEach(() => { - // init login + // init login cy.login(); - }) + }); it('visit metrics page', () => { // go to metrics page @@ -36,6 +36,6 @@ context('metrics page smoke test', () => { .children() .should('contain', 'Metrics') .and('contain', 'You have not configured Grafana') - .and('contain', 'Configure Now') + .and('contain', 'Configure Now'); }); -}) +}); diff --git a/web/cypress/integration/route/create-and-delete-route.spec.js b/web/cypress/integration/route/create-and-delete-route.spec.js index c8bd6d9..f7fa054 100644 --- a/web/cypress/integration/route/create-and-delete-route.spec.js +++ b/web/cypress/integration/route/create-and-delete-route.spec.js @@ -20,9 +20,9 @@ context('Create and Delete Route', () => { const name = `routeName${new Date().valueOf()}`; beforeEach(() => { - // init login + // init login cy.login(); - }) + }); it('create route', () => { // go to route create page @@ -41,9 +41,13 @@ context('Create and Delete Route', () => { cy.get('#remote_addrs_0').type('12.12.12.12'); cy.get('[data-cy=addRemoteAddr]').click(); cy.get('#remote_addrs_1').type('10.10.10.10'); - cy.contains('Advanced Routing Matching Conditions').parent().siblings().contains('Create').click(); + cy.contains('Advanced Routing Matching Conditions') + .parent() + .siblings() + .contains('Create') + .click(); - // create Advanced Routing Matching Conditions + // create Advanced Routing Matching Conditions cy.get('#position').click(); cy.contains('Cookie').click(); cy.get('.ant-modal').within(() => { @@ -56,7 +60,7 @@ context('Create and Delete Route', () => { // go to step2 cy.contains('Next').click(); - cy.get('#nodes_0_host').type('12.12.12.12') + cy.get('#nodes_0_host').type('12.12.12.12'); // go to step3 cy.contains('Next').click(); @@ -80,9 +84,9 @@ context('Create and Delete Route', () => { it('delete the route', () => { cy.visit('/routes/list'); cy.get('[title=Name]').type(name); - cy.contains('查 询').click(); + cy.contains('Search').click(); cy.contains(name).siblings().contains('Delete').click(); cy.contains('button', 'Confirm').click(); cy.get('.ant-notification-notice-message').should('contain', 'Delete Route Successfully'); - }) -}) + }); +}); diff --git a/web/cypress/integration/settings/settings-smoketest.spec.js b/web/cypress/integration/settings/settings-smoketest.spec.js index 77b3676..a6b1e0c 100644 --- a/web/cypress/integration/settings/settings-smoketest.spec.js +++ b/web/cypress/integration/settings/settings-smoketest.spec.js @@ -19,13 +19,13 @@ context('settings page smoke test', () => { const domSelectors = { pageContent: '.ant-pro-page-container', - notificationMsg: '.ant-notification-notice-message' + notificationMsg: '.ant-notification-notice-message', }; beforeEach(() => { - // init login + // init login cy.login(); - }) + }); it('should visit settings page', () => { // go to settings page @@ -37,7 +37,7 @@ context('settings page smoke test', () => { .children() .should('contain', 'Setting') .and('contain', 'Grafana Address') - .and('contain', 'Grafana address should begin with HTTP or HTTPS') + .and('contain', 'Grafana address should begin with HTTP or HTTPS'); }); it('should set a invaild url', () => { @@ -58,8 +58,6 @@ context('settings page smoke test', () => { cy.contains('Submit').click(); cy.get(domSelectors.notificationMsg).should('contain', 'Update Configuration Successfully'); cy.wait(1000); - cy.get(domSelectors.pageContent) - .children() - .should('contain', 'Metrics') + cy.get(domSelectors.pageContent).children().should('contain', 'Metrics'); }); -}) +}); diff --git a/web/cypress/integration/ssl/ssl-smoketest.spec.js b/web/cypress/integration/ssl/ssl-smoketest.spec.js index 307bb3b..f0bc964 100644 --- a/web/cypress/integration/ssl/ssl-smoketest.spec.js +++ b/web/cypress/integration/ssl/ssl-smoketest.spec.js @@ -19,16 +19,17 @@ context('ssl smoke test', () => { const domSelectors = { notificationDesc: '.ant-notification-notice-description', - notificationMsg: '.ant-notification-notice-message' + notificationMsg: '.ant-notification-notice-message', }; beforeEach(() => { - // init login + // init login cy.login(); cy.fixture('certificate.json').as('certificate'); - }) + }); - it('should set match certificate and key by input', function () { // use `function () if used `fixture` above` + it('should set match certificate and key by input', function () { + // use `function () if used `fixture` above` // go to ssl create page cy.visit('/'); cy.contains('SSL').click(); @@ -72,4 +73,4 @@ context('ssl smoke test', () => { cy.wait(100); cy.get(domSelectors.notificationDesc).should('contain', "key and cert don't match"); }); -}) +}); diff --git a/web/cypress/integration/upstream/create_and_delete_upstream.spec.js b/web/cypress/integration/upstream/create_and_delete_upstream.spec.js index f6e73ea..1822a38 100644 --- a/web/cypress/integration/upstream/create_and_delete_upstream.spec.js +++ b/web/cypress/integration/upstream/create_and_delete_upstream.spec.js @@ -20,13 +20,13 @@ context('Create and Delete Upstream', () => { const name = `upstreamName${new Date().valueOf()}`; const sleepTime = 100; // the unit is milliseconds const domSelectors = { - notification: '.ant-notification-notice-message' + notification: '.ant-notification-notice-message', }; beforeEach(() => { - // init login + // init login cy.login(); - }) + }); it('should create upstream with default type (roundrobin)', () => { // go to upstream create page @@ -53,7 +53,7 @@ context('Create and Delete Upstream', () => { it('should delete the upstream', () => { cy.visit('/'); cy.contains('Upstream').click(); - cy.wait(sleepTime * 5) + cy.wait(sleepTime * 5); cy.contains(name).siblings().contains('Delete').click(); cy.contains('button', 'Confirm').click(); cy.get(domSelectors.notification).should('contain', 'Delete successfully'); @@ -79,7 +79,9 @@ context('Create and Delete Upstream', () => { cy.get('.ant-select-item-option-active:nth-child(1) > .ant-select-item-option-content').click(); cy.get('#key').click(); cy.wait(sleepTime); - cy.get('div:nth-child(8) .ant-select-item:nth-child(1) > .ant-select-item-option-content:nth-child(1)').click(); + cy.get( + 'div:nth-child(8) .ant-select-item:nth-child(1) > .ant-select-item-option-content:nth-child(1)', + ).click(); // add first upstream node cy.get('#nodes_0_host').type('127.0.0.1'); @@ -107,4 +109,4 @@ context('Create and Delete Upstream', () => { cy.contains('button', 'Confirm').click(); cy.get(domSelectors.notification).should('contain', 'Delete successfully'); }); -}) +}); diff --git a/web/cypress/integration/user/login.spec.js b/web/cypress/integration/user/login.spec.js index 65e67c2..60adad7 100644 --- a/web/cypress/integration/user/login.spec.js +++ b/web/cypress/integration/user/login.spec.js @@ -19,7 +19,7 @@ context('Login Test', () => { beforeEach(() => { // set default language - localStorage.setItem('umi_locale', "en-US"); + localStorage.setItem('umi_locale', 'en-US'); }); it('login failed with empty username and password', () => { @@ -44,4 +44,4 @@ context('Login Test', () => { cy.contains('Login').click(); cy.get('.ant-notification-notice-message').should('contain', 'Successfully'); }); -}) +}); diff --git a/web/cypress/integration/user/logout.spec.js b/web/cypress/integration/user/logout.spec.js index 853f334..ec3f368 100644 --- a/web/cypress/integration/user/logout.spec.js +++ b/web/cypress/integration/user/logout.spec.js @@ -24,11 +24,11 @@ context('Logout Test', () => { it('logout', () => { cy.visit('/'); cy.contains('.anticon', 'APISIX User', { - matchCase: false + matchCase: false, }).click({ - force: true + force: true, }); cy.get('[aria-label=logout]').click(); cy.url().should('contains', '/user/login'); }); -}) +}); diff --git a/web/cypress/plugins/index.js b/web/cypress/plugins/index.js index ed129f2..1e51e89 100644 --- a/web/cypress/plugins/index.js +++ b/web/cypress/plugins/index.js @@ -21,4 +21,4 @@ module.exports = (on, config) => { // `on` is used to hook into various events Cypress emits // `config` is the resolved Cypress config -} +}; diff --git a/web/cypress/support/commands.js b/web/cypress/support/commands.js index bfb1955..5ff9062 100644 --- a/web/cypress/support/commands.js +++ b/web/cypress/support/commands.js @@ -22,20 +22,15 @@ Cypress.Commands.add('login', () => { test: 'http://localhost:9000', }; - const { - SERVE_ENV = 'dev' - } = Cypress.env(); + const { SERVE_ENV = 'dev' } = Cypress.env(); cy.request('POST', `${serveUrlMap[SERVE_ENV]}/apisix/admin/user/login`, { - "username": "user", - "password": "user" - }) - .then(res => { - expect(res.body.code).to.equal(0); - localStorage.setItem( - 'token', res.body.data.token - ); - // set default language - localStorage.setItem('umi_locale', "en-US"); - }) -}) + username: 'user', + password: 'user', + }).then((res) => { + expect(res.body.code).to.equal(0); + localStorage.setItem('token', res.body.data.token); + // set default language + localStorage.setItem('umi_locale', 'en-US'); + }); +}); diff --git a/web/cypress/support/index.js b/web/cypress/support/index.js index 113a8ce..a7c4744 100644 --- a/web/cypress/support/index.js +++ b/web/cypress/support/index.js @@ -15,10 +15,10 @@ * limitations under the License. */ /* eslint-disable no-undef */ -import './commands' +import './commands'; Cypress.on('uncaught:exception', () => { // returning false here prevents Cypress from // failing the test - return false -}) + return false; +}); diff --git a/web/src/components/Plugin/PluginPage.tsx b/web/src/components/Plugin/PluginPage.tsx index e9b10af..e88f417 100644 --- a/web/src/components/Plugin/PluginPage.tsx +++ b/web/src/components/Plugin/PluginPage.tsx @@ -49,7 +49,7 @@ const PluginPage: React.FC<Props> = ({ readonly = false, initialData = {}, schemaType = '', - onChange = () => { }, + onChange = () => {}, }) => { const [pluginList, setPlugin] = useState<PluginComponent.Meta[][]>([]); const [name, setName] = useState<string>(NEVER_EXIST_PLUGIN_FLAG); @@ -95,9 +95,7 @@ const PluginPage: React.FC<Props> = ({ let description = ''; switch (err.keyword) { case 'enum': - description = `${err.dataPath} ${err.message}: ${err.params.allowedValues.join( - ', ', - )}`; + description = `${err.dataPath} ${err.message}: ${err.params.allowedValues.join(', ')}`; break; case 'minItems': case 'type': diff --git a/web/src/components/RightContent/AvatarDropdown.tsx b/web/src/components/RightContent/AvatarDropdown.tsx index 88c8c39..a87f831 100644 --- a/web/src/components/RightContent/AvatarDropdown.tsx +++ b/web/src/components/RightContent/AvatarDropdown.tsx @@ -24,7 +24,7 @@ import React, { useCallback } from 'react'; import { SettingOutlined, UserOutlined, SettingFilled, LogoutOutlined } from '@ant-design/icons'; import { Avatar, Menu, Spin } from 'antd'; -import { history, useModel } from 'umi'; +import { history, useModel, useIntl } from 'umi'; import { stringify } from 'querystring'; import HeaderDropdown from '../HeaderDropdown'; @@ -47,6 +47,7 @@ const settings = async () => { }; const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => { + const { formatMessage } = useIntl(); const { initialState, setInitialState } = useModel('@@initialState'); const onMenuClick = useCallback((event) => { @@ -97,25 +98,25 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => { {menu && ( <Menu.Item key="center"> <UserOutlined /> - 个人中心 + {formatMessage({ id: 'menu.account.center' })} </Menu.Item> )} {menu && ( <Menu.Item key="settings"> <SettingOutlined /> - 个人设置 + {formatMessage({ id: 'menu.setting' })} </Menu.Item> )} {menu && <Menu.Divider />} <Menu.Item key="settings"> <SettingFilled /> - 修改设置 + {formatMessage({ id: 'menu.setting' })} </Menu.Item> <Menu.Divider /> <Menu.Item key="logout"> <LogoutOutlined /> - 退出 + {formatMessage({ id: 'menu.account.logout' })} </Menu.Item> </Menu> ); diff --git a/web/src/components/Upstream/UpstreamForm.tsx b/web/src/components/Upstream/UpstreamForm.tsx index cf88245..3e7cff7 100644 --- a/web/src/components/Upstream/UpstreamForm.tsx +++ b/web/src/components/Upstream/UpstreamForm.tsx @@ -63,21 +63,6 @@ type Props = { ref?: any; }; -const timeoutFields = [ - { - label: '连接超时', - name: ['timeout', 'connect'], - }, - { - label: '发送超时', - name: ['timeout', 'send'], - }, - { - label: '接收超时', - name: ['timeout', 'read'], - }, -]; - const removeBtnStyle = { marginLeft: -10, display: 'flex', @@ -91,6 +76,21 @@ const UpstreamForm: React.FC<Props> = forwardRef( Boolean(form.getFieldValue('upstream_id')) || disabled, ); + const timeoutFields = [ + { + label: formatMessage({ id: 'page.upstream.step.connect.timeout' }), + name: ['timeout', 'connect'], + }, + { + label: formatMessage({ id: 'page.upstream.step.send.timeout' }), + name: ['timeout', 'send'], + }, + { + label: formatMessage({ id: 'page.upstream.step.read.timeout' }), + name: ['timeout', 'read'], + }, + ]; + useImperativeHandle(ref, () => ({ getData: () => transformRequest(form.getFieldsValue()), })); @@ -101,7 +101,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( setReadonly(true); requestAnimationFrame(() => { form.setFieldsValue(list.find((item) => item.id === id)); - }) + }); } }, [list]); @@ -137,9 +137,13 @@ const UpstreamForm: React.FC<Props> = forwardRef( <Form.Item required key={field.key} - label={index === 0 && '节点域名/IP'} + label={ + index === 0 && + formatMessage({ id: 'page.upstream.form.item-label.node.domain.or.ip' }) + } extra={ - index === 0 && '使用域名时,默认解析本地 /etc/resolv.conf;权重为0则熔断该节点' + index === 0 && + formatMessage({ id: 'page.upstream.form.item.extra-message.node.domain.or.ip' }) } labelCol={{ span: index === 0 ? 3 : 0 }} wrapperCol={{ offset: index === 0 ? 0 : 3 }} @@ -152,7 +156,9 @@ const UpstreamForm: React.FC<Props> = forwardRef( rules={[ { required: true, - message: formatMessage({ id: 'upstream.step.input.domain.name.or.ip' }), + message: formatMessage({ + id: 'page.upstream.step.input.domain.name.or.ip', + }), }, { pattern: new RegExp( @@ -162,7 +168,10 @@ const UpstreamForm: React.FC<Props> = forwardRef( }, ]} > - <Input placeholder="域名/IP" disabled={readonly} /> + <Input + placeholder={formatMessage({ id: 'page.upstream.step.domain.name.or.ip' })} + disabled={readonly} + /> </Form.Item> </Col> <Col span={2}> @@ -172,11 +181,16 @@ const UpstreamForm: React.FC<Props> = forwardRef( rules={[ { required: true, - message: formatMessage({ id: 'upstream.step.input.port' }), + message: formatMessage({ id: 'page.upstream.step.input.port' }), }, ]} > - <InputNumber placeholder="端口号" disabled={readonly} min={1} max={65535} /> + <InputNumber + placeholder={formatMessage({ id: 'page.upstream.step.port' })} + disabled={readonly} + min={1} + max={65535} + /> </Form.Item> </Col> <Col span={2}> @@ -186,11 +200,16 @@ const UpstreamForm: React.FC<Props> = forwardRef( rules={[ { required: true, - message: formatMessage({ id: 'upstream.step.input.weight' }), + message: formatMessage({ id: 'page.upstream.step.input.weight' }), }, ]} > - <InputNumber placeholder="权重" disabled={readonly} min={0} max={1000} /> + <InputNumber + placeholder={formatMessage({ id: 'page.upstream.step.weight' })} + disabled={readonly} + min={0} + max={1000} + /> </Form.Item> </Col> <Col style={removeBtnStyle}> @@ -205,7 +224,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( <Form.Item wrapperCol={{ offset: 3 }}> <Button type="dashed" onClick={add}> <PlusOutlined /> - 创建节点 + {formatMessage({ id: 'page.upstream.step.create.node' })} </Button> </Form.Item> )} @@ -216,14 +235,14 @@ const UpstreamForm: React.FC<Props> = forwardRef( const ActiveHealthCheck = () => ( <> - <Form.Item label="超时时间"> + <Form.Item label={formatMessage({ id: 'page.upstream.step.healthyCheck.active.timeout' })}> <Form.Item name={['checks', 'active', 'timeout']} noStyle> <InputNumber disabled={readonly} /> </Form.Item> <span style={{ margin: '0 8px' }}>s</span> </Form.Item> <Form.Item - label={formatMessage({ id: 'upstream.step.healthy.checks.active.host' })} + label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeHost' })} required > <Form.Item @@ -232,35 +251,39 @@ const UpstreamForm: React.FC<Props> = forwardRef( rules={[ { required: true, - message: formatMessage({ id: 'upstream.step.input.healthy.checks.active.host' }), + message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.activeHost' }), }, { pattern: new RegExp( /(^([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])(\.(25[0-5]|1\d{2}|2[0-4]\d|[1-9]?\d)){3}$|^(?![0-9.]+$)([a-zA-Z0-9_-]+)(\.[a-zA-Z0-9_-]+){0,}$)/, 'g', ), - message: formatMessage({ id: 'upstream.step.domain.name.or.ip.rule' }), + message: formatMessage({ id: 'page.upstream.step.domain.name.or.ip.rule' }), }, ]} > <Input - placeholder={formatMessage({ id: 'upstream.step.input.healthy.checks.active.host' })} + placeholder={formatMessage({ + id: 'page.upstream.step.input.healthyCheck.activeHost', + })} disabled={readonly} /> </Form.Item> </Form.Item> - <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.active.port' })}> + <Form.Item label={formatMessage({ id: 'page.upstream.step.healthyCheck.activePort' })}> <Form.Item name={['checks', 'active', 'port']} noStyle> <InputNumber - placeholder={formatMessage({ id: 'upstream.step.input.healthy.checks.active.port' })} + placeholder={formatMessage({ + id: 'page.upstream.step.input.healthyCheck.activePort', + })} disabled={readonly} /> </Form.Item> </Form.Item> <Form.Item - label={formatMessage({ id: 'upstream.step.healthy.checks.active.http_path' })} + label={formatMessage({ id: 'page.upstream.step.healthyCheck.active.http_path' })} required > <Form.Item @@ -270,7 +293,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( { required: true, message: formatMessage({ - id: 'upstream.step.input.healthy.checks.active.http_path', + id: 'page.upstream.step.input.healthyCheck.active.http_path', }), }, ]} @@ -278,17 +301,17 @@ const UpstreamForm: React.FC<Props> = forwardRef( <Input disabled={readonly} placeholder={formatMessage({ - id: 'upstream.step.input.healthy.checks.active.http_path', + id: 'page.upstream.step.input.healthyCheck.active.http_path', })} /> </Form.Item> </Form.Item> <Divider orientation="left" plain> - 健康状态 + {formatMessage({ id: 'page.upstream.step.healthyCheck.healthy.status' })} </Divider> <Form.Item - label={formatMessage({ id: 'upstream.step.healthy.checks.active.interval' })} + label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeInterval' })} required > <Form.Item @@ -298,7 +321,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( { required: true, message: formatMessage({ - id: 'upstream.step.input.healthy.checks.active.interval', + id: 'page.upstream.step.input.healthyCheck.activeInterval', }), }, ]} @@ -306,14 +329,17 @@ const UpstreamForm: React.FC<Props> = forwardRef( <InputNumber disabled={readonly} min={1} /> </Form.Item> </Form.Item> - <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.successes' })} required> + <Form.Item + label={formatMessage({ id: 'page.upstream.step.healthyCheck.successes' })} + required + > <Form.Item name={['checks', 'active', 'healthy', 'successes']} noStyle rules={[ { required: true, - message: formatMessage({ id: 'upstream.step.input.healthy.checks.successes' }), + message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.successes' }), }, ]} > @@ -322,10 +348,10 @@ const UpstreamForm: React.FC<Props> = forwardRef( </Form.Item> <Divider orientation="left" plain> - 不健康状态 + {formatMessage({ id: 'page.upstream.step.healthyCheck.unhealthyStatus' })} </Divider> <Form.Item - label={formatMessage({ id: 'upstream.step.healthy.checks.active.interval' })} + label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeInterval' })} required > <Form.Item @@ -335,7 +361,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( { required: true, message: formatMessage({ - id: 'upstream.step.input.healthy.checks.active.interval', + id: 'page.upstream.step.input.healthyCheck.activeInterval', }), }, ]} @@ -344,7 +370,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( </Form.Item> </Form.Item> <Form.Item - label={formatMessage({ id: 'upstream.step.healthy.checks.http_failures' })} + label={formatMessage({ id: 'page.upstream.step.healthyCheck.http_failures' })} required > <Form.Item @@ -353,7 +379,9 @@ const UpstreamForm: React.FC<Props> = forwardRef( rules={[ { required: true, - message: formatMessage({ id: 'upstream.step.input.healthy.checks.http_failures' }), + message: formatMessage({ + id: 'page.upstream.step.input.healthyCheck.http_failures', + }), }, ]} > @@ -368,7 +396,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( key={field.key} label={ index === 0 && - formatMessage({ id: 'upstream.step.healthy.checks.active.req_headers' }) + formatMessage({ id: 'page.upstream.step.healthyCheck.active.req_headers' }) } wrapperCol={{ offset: index === 0 ? 0 : 3 }} > @@ -377,7 +405,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( <Form.Item style={{ marginBottom: 0 }} name={[field.name]}> <Input placeholder={formatMessage({ - id: 'upstream.step.input.healthy.checks.active.req_headers', + id: 'page.upstream.step.input.healthyCheck.active.req_headers', })} disabled={readonly} /> @@ -400,7 +428,9 @@ const UpstreamForm: React.FC<Props> = forwardRef( <Form.Item wrapperCol={{ offset: 3 }}> <Button type="dashed" onClick={() => add()}> <PlusOutlined /> - 创建请求头 + {formatMessage({ + id: 'page.upstream.step.healthyCheck.active.create.req_headers', + })} </Button> </Form.Item> )} @@ -412,7 +442,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( const InActiveHealthCheck = () => ( <> <Divider orientation="left" plain> - 健康状态 + {formatMessage({ id: 'page.upstream.step.healthyCheck.healthy.status' })} </Divider> <Form.List name={['checks', 'passive', 'healthy', 'http_statuses']}> {(fields, { add, remove }) => ( @@ -423,7 +453,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( key={field.key} label={ index === 0 && - formatMessage({ id: 'upstream.step.healthy.checks.passive.http_statuses' }) + formatMessage({ id: 'page.upstream.step.healthyCheck.passive.http_statuses' }) } labelCol={{ span: index === 0 ? 3 : 0 }} wrapperCol={{ offset: index === 0 ? 0 : 3 }} @@ -450,21 +480,26 @@ const UpstreamForm: React.FC<Props> = forwardRef( <Form.Item wrapperCol={{ offset: 3 }}> <Button type="dashed" onClick={() => add()}> <PlusOutlined /> - 创建状态码 + {formatMessage({ + id: 'page.upstream.step.healthyCheck.passive.create.http_statuses', + })} </Button> </Form.Item> )} </> )} </Form.List> - <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.successes' })} required> + <Form.Item + label={formatMessage({ id: 'page.upstream.step.healthyCheck.successes' })} + required + > <Form.Item name={['checks', 'passive', 'healthy', 'successes']} noStyle rules={[ { required: true, - message: formatMessage({ id: 'upstream.step.input.healthy.checks.successes' }), + message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.successes' }), }, ]} > @@ -473,7 +508,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( </Form.Item> <Divider orientation="left" plain> - 不健康状态 + {formatMessage({ id: 'page.upstream.step.healthyCheck.unhealthyStatus' })} </Divider> <Form.List name={['checks', 'passive', 'unhealthy', 'http_statuses']}> {(fields, { add, remove }) => ( @@ -484,7 +519,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( key={field.key} label={ index === 0 && - formatMessage({ id: 'upstream.step.healthy.checks.passive.http_statuses' }) + formatMessage({ id: 'page.upstream.step.healthyCheck.passive.http_statuses' }) } labelCol={{ span: index === 0 ? 3 : 0 }} wrapperCol={{ offset: index === 0 ? 0 : 3 }} @@ -511,7 +546,9 @@ const UpstreamForm: React.FC<Props> = forwardRef( <Form.Item wrapperCol={{ offset: 3 }}> <Button type="dashed" onClick={() => add()}> <PlusOutlined /> - 创建状态码 + {formatMessage({ + id: 'page.upstream.step.healthyCheck.passive.create.http_statuses', + })} </Button> </Form.Item> )} @@ -519,7 +556,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( )} </Form.List> <Form.Item - label={formatMessage({ id: 'upstream.step.healthy.checks.http_failures' })} + label={formatMessage({ id: 'page.upstream.step.healthyCheck.http_failures' })} required > <Form.Item @@ -528,7 +565,9 @@ const UpstreamForm: React.FC<Props> = forwardRef( rules={[ { required: true, - message: formatMessage({ id: 'upstream.step.input.healthy.checks.http_failures' }), + message: formatMessage({ + id: 'page.upstream.step.input.healthyCheck.http_failures', + }), }, ]} > @@ -536,7 +575,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( </Form.Item> </Form.Item> <Form.Item - label={formatMessage({ id: 'upstream.step.healthy.checks.passive.tcp_failures' })} + label={formatMessage({ id: 'page.upstream.step.healthyCheck.passive.tcp_failures' })} required > <Form.Item @@ -546,7 +585,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( { required: true, message: formatMessage({ - id: 'upstream.step.input.healthy.checks.passive.tcp_failures', + id: 'page.upstream.step.input.healthyCheck.passive.tcp_failures', }), }, ]} @@ -566,26 +605,36 @@ const UpstreamForm: React.FC<Props> = forwardRef( }} > {showSelector && ( - <Form.Item label="选择上游" name="upstream_id" shouldUpdate={(prev, next) => { - setReadonly(Boolean(next.upstream_id)); - if (prev.upstream_id !== next.upstream_id) { - const id = next.upstream_id; - if (id) { - form.setFieldsValue(list.find((item) => item.id === id)); - form.setFieldsValue({ - upstream_id: id, - }); + <Form.Item + label={formatMessage({ id: 'page.upstream.step.select.upstream' })} + name="upstream_id" + shouldUpdate={(prev, next) => { + setReadonly(Boolean(next.upstream_id)); + if (prev.upstream_id !== next.upstream_id) { + const id = next.upstream_id; + if (id) { + form.setFieldsValue(list.find((item) => item.id === id)); + form.setFieldsValue({ + upstream_id: id, + }); + } } - } - return prev.upstream_id !== next.upstream_id; - }}> + return prev.upstream_id !== next.upstream_id; + }} + > <Select disabled={disabled} onChange={(id) => { form.setFieldsValue(list.find((item) => item.id === id)); }} > - {[{ name: '手动填写', id: '' }, ...list].map((item) => ( + {[ + { + name: formatMessage({ id: 'page.upstream.step.select.upstream.select.option' }), + id: '', + }, + ...list, + ].map((item) => ( <Select.Option value={item.id!} key={item.id}> {item.name} </Select.Option> @@ -594,7 +643,11 @@ const UpstreamForm: React.FC<Props> = forwardRef( </Form.Item> )} - <Form.Item label="类型" name="type" rules={[{ required: true }]}> + <Form.Item + label={formatMessage({ id: 'page.upstream.step.type' })} + name="type" + rules={[{ required: true }]} + > <Select disabled={readonly}> {Object.entries(Type).map(([label, value]) => { return ( @@ -615,19 +668,19 @@ const UpstreamForm: React.FC<Props> = forwardRef( </Form.Item> {NodeList()} <Form.Item - label={formatMessage({ id: 'upstream.step.pass-host' })} + label={formatMessage({ id: 'page.upstream.step.pass-host' })} name="pass_host" - extra={formatMessage({ id: 'upstream.step.pass-host.tips' })} + extra={formatMessage({ id: 'page.upstream.step.pass-host.tips' })} > <Select disabled={readonly}> <Select.Option value="pass"> - {formatMessage({ id: 'upstream.step.pass-host.pass' })} + {formatMessage({ id: 'page.upstream.step.pass-host.pass' })} </Select.Option> <Select.Option value="node"> - {formatMessage({ id: 'upstream.step.pass-host.node' })} + {formatMessage({ id: 'page.upstream.step.pass-host.node' })} </Select.Option> <Select.Option value="rewrite"> - {formatMessage({ id: 'upstream.step.pass-host.rewrite' })} + {formatMessage({ id: 'page.upstream.step.pass-host.rewrite' })} </Select.Option> </Select> </Form.Item> @@ -641,7 +694,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( if (form.getFieldValue('pass_host') === 'rewrite') { return ( <Form.Item - label={formatMessage({ id: 'upstream.step.pass-host.upstream_host' })} + label={formatMessage({ id: 'page.upstream.step.pass-host.upstream_host' })} name="upstream_host" > <Input disabled={readonly} /> @@ -660,7 +713,7 @@ const UpstreamForm: React.FC<Props> = forwardRef( rules={[ { required: true, - message: formatMessage({ id: `upstream.step.input.${name[1]}.timeout` }), + message: formatMessage({ id: `page.upstream.step.input.${name[1]}.timeout` }), }, ]} > @@ -670,15 +723,17 @@ const UpstreamForm: React.FC<Props> = forwardRef( </Form.Item> ))} - <PanelSection title="健康检查"> + <PanelSection + title={formatMessage({ id: 'page.upstream.step.healthyCheck.healthy.check' })} + > {[ { - label: '探活健康检查', + label: formatMessage({ id: 'page.upstream.step.healthyCheck.active' }), name: ['checks', 'active'], component: <ActiveHealthCheck />, }, { - label: '被动健康检查', + label: formatMessage({ id: 'page.upstream.step.healthyCheck.passive' }), name: ['checks', 'passive'], component: <InActiveHealthCheck />, }, diff --git a/web/src/helpers.tsx b/web/src/helpers.tsx index ac40f42..2942aee 100644 --- a/web/src/helpers.tsx +++ b/web/src/helpers.tsx @@ -32,16 +32,16 @@ export const getMenuData = (): MenuDataItem[] => { icon: <IconFont name="icondashboard" />, }, { + name: 'service', + path: '/service/list', + icon: <IconFont name="iconconsumer" />, + }, + { name: 'routes', path: '/routes/list', icon: <IconFont name="iconroute" />, }, { - name: 'ssl', - path: '/ssl/list', - icon: <IconFont name="iconssl" />, - }, - { name: 'upstream', path: '/upstream/list', icon: <IconFont name="iconserver" />, @@ -52,9 +52,9 @@ export const getMenuData = (): MenuDataItem[] => { icon: <IconFont name="iconconsumer" />, }, { - name: 'service', - path: '/service/list', - icon: <IconFont name="iconconsumer" />, + name: 'ssl', + path: '/ssl/list', + icon: <IconFont name="iconssl" />, }, { name: 'setting', diff --git a/web/src/locales/en-US/component.ts b/web/src/locales/en-US/component.ts index a712701..946a735 100644 --- a/web/src/locales/en-US/component.ts +++ b/web/src/locales/en-US/component.ts @@ -18,6 +18,8 @@ export default { 'component.tagSelect.expand': 'Expand', 'component.tagSelect.collapse': 'Collapse', 'component.tagSelect.all': 'All', + 'component.global.search': 'Search', + 'component.global.reset': 'Reset', 'component.global.confirm': 'Confirm', 'component.global.delete': 'Delete', 'component.global.cancel': 'Cancel', diff --git a/web/src/locales/en-US/menu.ts b/web/src/locales/en-US/menu.ts index 325d1cd..ae4018a 100644 --- a/web/src/locales/en-US/menu.ts +++ b/web/src/locales/en-US/menu.ts @@ -57,7 +57,6 @@ export default { 'menu.exception.trigger': 'Trigger', 'menu.account': 'Account', 'menu.account.center': 'Account Center', - 'menu.account.settings': 'Account Settings', 'menu.account.trigger': 'Trigger Error', 'menu.account.logout': 'Logout', 'menu.editor': 'Graphic Editor', diff --git a/web/src/locales/zh-CN/component.ts b/web/src/locales/zh-CN/component.ts index b62ba40..d0829c6 100644 --- a/web/src/locales/zh-CN/component.ts +++ b/web/src/locales/zh-CN/component.ts @@ -18,6 +18,8 @@ export default { 'component.tagSelect.expand': '展开', 'component.tagSelect.collapse': '收起', 'component.tagSelect.all': '全部', + 'component.global.search': '查询', + 'component.global.reset': '重置', 'component.global.confirm': '确认', 'component.global.delete': '删除', 'component.global.cancel': '取消', diff --git a/web/src/locales/zh-CN/menu.ts b/web/src/locales/zh-CN/menu.ts index aef67b3..6524131 100644 --- a/web/src/locales/zh-CN/menu.ts +++ b/web/src/locales/zh-CN/menu.ts @@ -57,7 +57,6 @@ export default { 'menu.exception.trigger': '触发错误', 'menu.account': '个人页', 'menu.account.center': '个人中心', - 'menu.account.settings': '个人设置', 'menu.account.trigger': '触发报错', 'menu.account.logout': '退出登录', 'menu.editor': '图形编辑器', diff --git a/web/src/pages/Consumer/List.tsx b/web/src/pages/Consumer/List.tsx index 78d1587..08f3dd6 100644 --- a/web/src/pages/Consumer/List.tsx +++ b/web/src/pages/Consumer/List.tsx @@ -93,6 +93,10 @@ const Page: React.FC = () => { columns={columns} rowKey="id" request={fetchList} + search={{ + searchText: formatMessage({ id: 'component.global.search' }), + resetText: formatMessage({ id: 'component.global.reset' }), + }} toolBarRender={() => [ <Button type="primary" onClick={() => history.push(`/consumer/create`)}> <PlusOutlined /> diff --git a/web/src/pages/Route/Create.tsx b/web/src/pages/Route/Create.tsx index 4fcc921..41cadae 100644 --- a/web/src/pages/Route/Create.tsx +++ b/web/src/pages/Route/Create.tsx @@ -113,7 +113,7 @@ const Page: React.FC<Props> = (props) => { setAdvancedMatchingRules(data); } if (action === 'labelsChange') { - form1.setFieldsValue({ ...form1.getFieldsValue(), labels: data }) + form1.setFieldsValue({ ...form1.getFieldsValue(), labels: data }); } }} isEdit={props.route.path.indexOf('edit') > 0} @@ -256,10 +256,11 @@ const Page: React.FC<Props> = (props) => { return ( <> <PageHeaderWrapper - title={`${(props as any).match.params.rid - ? formatMessage({ id: 'component.global.edit' }) - : formatMessage({ id: 'component.global.create' }) - } ${formatMessage({ id: 'menu.routes' })}`} + title={`${ + (props as any).match.params.rid + ? formatMessage({ id: 'component.global.edit' }) + : formatMessage({ id: 'component.global.create' }) + } ${formatMessage({ id: 'menu.routes' })}`} > <Card bordered={false}> <Steps current={step - 1} className={styles.steps}> diff --git a/web/src/pages/Route/List.tsx b/web/src/pages/Route/List.tsx index c131899..304ad3b 100644 --- a/web/src/pages/Route/List.tsx +++ b/web/src/pages/Route/List.tsx @@ -25,7 +25,6 @@ import { timestampToLocaleString } from '@/helpers'; import { fetchList, remove, fetchLabelList, updateRouteStatus } from './service'; import { DebugDrawView } from './components/DebugViews'; - const { OptGroup, Option } = Select; const Page: React.FC = () => { @@ -52,14 +51,16 @@ const Page: React.FC = () => { const handlePublishOffline = (rid: string, status: RouteModule.RouteStatus) => { updateRouteStatus(rid, status).then(() => { - const actionName = status ? formatMessage({ id: 'page.route.publish' }) : formatMessage({ id: 'page.route.offline' }) + const actionName = status + ? formatMessage({ id: 'page.route.publish' }) + : formatMessage({ id: 'page.route.offline' }); handleTableActionSuccessResponse( `${actionName} ${formatMessage({ id: 'menu.routes', })} ${formatMessage({ id: 'component.status.success' })}`, ); }); - } + }; const [debugDrawVisible, setDebugDrawVisible] = useState(false); @@ -130,14 +131,17 @@ const Page: React.FC = () => { return ( <OptGroup label={key} key={Math.random().toString(36).slice(2)}> {(labelList[key] || []).map((value: string) => ( - <Option key={Math.random().toString(36).slice(2)} value={`${key}:${value}`}> {value} </Option> + <Option key={Math.random().toString(36).slice(2)} value={`${key}:${value}`}> + {' '} + {value}{' '} + </Option> ))} </OptGroup> ); })} </Select> ); - } + }, }, { title: formatMessage({ id: 'page.route.status' }), @@ -147,8 +151,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> + )} </> ), }, @@ -175,7 +179,7 @@ const Page: React.FC = () => { <Button type="primary" onClick={() => { - handlePublishOffline(record.id, RouteStatus.Publish) + handlePublishOffline(record.id, RouteStatus.Publish); }} style={{ marginRight: 10 }} disabled={Boolean(record.status)} @@ -185,7 +189,7 @@ const Page: React.FC = () => { <Popconfirm title={formatMessage({ id: 'page.route.popconfirm.title.offline' })} onConfirm={() => { - handlePublishOffline(record.id, RouteStatus.Offline) + handlePublishOffline(record.id, RouteStatus.Offline); }} okText={formatMessage({ id: 'component.global.confirm' })} cancelText={formatMessage({ id: 'component.global.cancel' })} @@ -230,6 +234,10 @@ const Page: React.FC = () => { rowKey="id" columns={columns} request={fetchList} + search={{ + searchText: formatMessage({ id: 'component.global.search' }), + resetText: formatMessage({ id: 'component.global.reset' }), + }} toolBarRender={() => [ <Button type="primary" onClick={() => history.push(`/routes/create`)}> <PlusOutlined /> diff --git a/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx b/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx index 16c15db..c73af82 100644 --- a/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx +++ b/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx @@ -39,7 +39,7 @@ const { TabPane } = Tabs; const DebugDrawView: React.FC<RouteModule.DebugDrawProps> = (props) => { const { formatMessage } = useIntl(); const [httpMethod, setHttpMethod] = useState(HTTP_METHOD_OPTION_LIST[0]); - const [requestProtocol, setRequestProtocol] = useState(PROTOCOL_SUPPORTED[0]) + const [requestProtocol, setRequestProtocol] = useState(PROTOCOL_SUPPORTED[0]); const [showBodyTab, setShowBodyTab] = useState(false); const [queryForm] = Form.useForm(); const [bodyForm] = Form.useForm(); diff --git a/web/src/pages/Route/components/Step1/LabelsDrawer.tsx b/web/src/pages/Route/components/Step1/LabelsDrawer.tsx index 6fb0a70..ba5b221 100644 --- a/web/src/pages/Route/components/Step1/LabelsDrawer.tsx +++ b/web/src/pages/Route/components/Step1/LabelsDrawer.tsx @@ -111,7 +111,7 @@ const LabelsDrawer: React.FC<Props> = ({ disabled, labelsDataSource, onClose, - onChange = () => { }, + onChange = () => {}, }) => { const transformLabel = transformLableValueToKeyValue(labelsDataSource); @@ -141,7 +141,7 @@ const LabelsDrawer: React.FC<Props> = ({ onClick={(e) => { e.persist(); form.validateFields().then(({ labels }) => { - const data = labels.map((item: any) => `${item.labelKey}:${item.labelValue}`) + const data = labels.map((item: any) => `${item.labelKey}:${item.labelValue}`); // check for duplicates if (new Set(data).size !== data.length) { notification.warning({ @@ -161,13 +161,13 @@ const LabelsDrawer: React.FC<Props> = ({ > {formatMessage({ id: 'component.global.confirm' })} </Button> - </div > + </div> } > <Form form={form} layout="horizontal"> {LabelList(disabled, labelList || {})} </Form> - </Drawer > + </Drawer> ); }; diff --git a/web/src/pages/Route/components/Step1/MetaView.tsx b/web/src/pages/Route/components/Step1/MetaView.tsx index 8234be9..25e1f31 100644 --- a/web/src/pages/Route/components/Step1/MetaView.tsx +++ b/web/src/pages/Route/components/Step1/MetaView.tsx @@ -23,7 +23,7 @@ import { PanelSection } from '@api7-dashboard/ui'; import { FORM_ITEM_WITHOUT_LABEL } from '@/pages/Route/constants'; import LabelsDrawer from './LabelsDrawer'; -const MetaView: React.FC<RouteModule.Step1PassProps> = ({ disabled, form, isEdit, onChange, }) => { +const MetaView: React.FC<RouteModule.Step1PassProps> = ({ disabled, form, isEdit, onChange }) => { const { formatMessage } = useIntl(); const [visible, setVisible] = useState(false); diff --git a/web/src/pages/Route/components/Step1/RequestConfigView.tsx b/web/src/pages/Route/components/Step1/RequestConfigView.tsx index 957d260..7ad1631 100644 --- a/web/src/pages/Route/components/Step1/RequestConfigView.tsx +++ b/web/src/pages/Route/components/Step1/RequestConfigView.tsx @@ -31,7 +31,7 @@ import { fetchServiceList } from '../../service'; const RequestConfigView: React.FC<RouteModule.Step1PassProps> = ({ form, disabled, - onChange = () => { }, + onChange = () => {}, }) => { const { formatMessage } = useIntl(); const [serviceList, setServiceList] = useState<ServiceModule.ResponseBody[]>([]); @@ -383,17 +383,18 @@ const RequestConfigView: React.FC<RouteModule.Step1PassProps> = ({ return null; }} </Form.Item> - <Form.Item - label={formatMessage({ id: 'page.route.service' })} - name='service_id' - > + <Form.Item label={formatMessage({ id: 'page.route.service' })} name="service_id"> <Select disabled={disabled}> {/* TODO: value === '' means no service_id select, need to find a better way */} - <Select.Option value='' key={Math.random().toString(36).substring(7)}>None</Select.Option> - {serviceList.map(item => { - return <Select.Option value={item.id} key={item.id}> - {item.name} - </Select.Option> + <Select.Option value="" key={Math.random().toString(36).substring(7)}> + None + </Select.Option> + {serviceList.map((item) => { + return ( + <Select.Option value={item.id} key={item.id}> + {item.name} + </Select.Option> + ); })} </Select> </Form.Item> diff --git a/web/src/pages/Route/constants.ts b/web/src/pages/Route/constants.ts index ab6c30c..1a8dc46 100644 --- a/web/src/pages/Route/constants.ts +++ b/web/src/pages/Route/constants.ts @@ -43,7 +43,7 @@ export const FORM_ITEM_WITHOUT_LABEL = { export const DEFAULT_STEP_1_DATA: RouteModule.Form1Data = { name: '', desc: '', - labels:[], + labels: [], status: 1, priority: 0, websocket: false, @@ -54,6 +54,7 @@ export const DEFAULT_STEP_1_DATA: RouteModule.Form1Data = { redirectURI: '', ret_code: 302, methods: HTTP_METHOD_OPTION_LIST, + service_id: '', }; export const DEFAULT_STEP_3_DATA: RouteModule.Step3Data = { @@ -87,7 +88,7 @@ export const HASH_ON_LIST = ['vars', 'header', 'cookie', 'consumer']; export const AUTH_LIST = ['basic-auth', 'jwt-auth', 'key-auth']; -export const PROTOCOL_SUPPORTED = ['http', 'https']; +export const PROTOCOL_SUPPORTED: RouteModule.debugRequest['request_protocol'][] = ['http', 'https']; export const DEFAULT_DEBUG_PARAM_FORM_DATA = { params: [ diff --git a/web/src/pages/Route/service.ts b/web/src/pages/Route/service.ts index 099428b..bc1a469 100644 --- a/web/src/pages/Route/service.ts +++ b/web/src/pages/Route/service.ts @@ -21,7 +21,7 @@ import { transformStepData, transformRouteData, transformUpstreamNodes, - transformLabelList + transformLabelList, } from './transform'; export const create = (data: RouteModule.RequestData) => @@ -37,7 +37,7 @@ export const update = (rid: number, data: RouteModule.RequestData) => }); export const fetchItem = (rid: number) => - request(`/routes/${rid}`).then((data) => (transformRouteData(data.data))); + request(`/routes/${rid}`).then((data) => transformRouteData(data.data)); export const fetchList = ({ current = 1, pageSize = 10, ...res }) => { const { labels } = res; @@ -94,12 +94,14 @@ export const checkHostWithSSL = (hosts: string[]) => }); export const fetchLabelList = () => - request('/labels/route').then(({ data }) => ((transformLabelList(data.rows)) as RouteModule.LabelList)); + request('/labels/route').then( + ({ data }) => transformLabelList(data.rows) as RouteModule.LabelList, + ); export const updateRouteStatus = (rid: string, status: RouteModule.RouteStatus) => request(`/routes/${rid}`, { method: 'PATCH', - data: { status } + data: { status }, }); export const debugRoute = (data: RouteModule.debugRequest) => { diff --git a/web/src/pages/Route/transform.ts b/web/src/pages/Route/transform.ts index c7b442d..401b15d 100644 --- a/web/src/pages/Route/transform.ts +++ b/web/src/pages/Route/transform.ts @@ -45,9 +45,9 @@ export const transformStepData = ({ } const labels = {}; - transformLableValueToKeyValue(form1Data.labels).forEach(item => { + transformLableValueToKeyValue(form1Data.labels).forEach((item) => { labels[item.labelKey] = item.labelValue; - }) + }); const { service_id = '' } = form1Data; const data: Partial<RouteModule.Body> = { @@ -70,7 +70,7 @@ export const transformStepData = ({ return [key, operator, value]; }), // @ts-ignore - methods: form1Data.methods.includes("ALL") ? [] : form1Data.methods + methods: form1Data.methods.includes('ALL') ? [] : form1Data.methods, }; if (Object.keys(redirect).length === 0 || redirect.http_to_https) { @@ -171,7 +171,7 @@ export const transformRouteData = (data: RouteModule.Body) => { upstream_id, service_id = '', priority = 0, - enable_websocket + enable_websocket, } = data; const form1Data: Partial<RouteModule.Form1Data> = { name, @@ -182,10 +182,10 @@ export const transformRouteData = (data: RouteModule.Body) => { remote_addrs: remote_addrs || [''], labels: Object.keys(labels || []).map((item) => `${item}:${labels[item]}`), // @ts-ignore - methods: methods.length ? methods : ["ALL"], + methods: methods.length ? methods : ['ALL'], priority, enable_websocket, - service_id + service_id, }; const redirect = data.plugins?.redirect || {}; diff --git a/web/src/pages/Route/typing.d.ts b/web/src/pages/Route/typing.d.ts index f104b19..6b87a0b 100644 --- a/web/src/pages/Route/typing.d.ts +++ b/web/src/pages/Route/typing.d.ts @@ -124,10 +124,10 @@ declare namespace RouteModule { type LabelList = Record<string, string[]>; type LabelTableProps = { - labelKey: string, - labelValue: string, - key: string - } + labelKey: string; + labelValue: string; + key: string; + }; type Step1PassProps = { form: FormInstance; @@ -253,7 +253,7 @@ declare namespace RouteModule { // TODO: grpc and websocket type debugRequest = { url: string; - request_protocol: 'http' | 'grpc' | 'websocket'; + request_protocol: 'http' | 'https' | 'grpc' | 'websocket'; method: string; body_params?: any; header_params?: any; diff --git a/web/src/pages/SSL/List.tsx b/web/src/pages/SSL/List.tsx index bf607ea..c9a7dd5 100644 --- a/web/src/pages/SSL/List.tsx +++ b/web/src/pages/SSL/List.tsx @@ -106,6 +106,10 @@ const Page: React.FC = () => { columns={columns} actionRef={tableRef} request={fetchList} + search={{ + searchText: formatMessage({ id: 'component.global.search' }), + resetText: formatMessage({ id: 'component.global.reset' }), + }} toolBarRender={() => [ <Button type="primary" onClick={() => history.push(`/ssl/create`)}> <PlusOutlined /> diff --git a/web/src/pages/ServerInfo/List.tsx b/web/src/pages/ServerInfo/List.tsx index 2f59050..c4ae9ad 100644 --- a/web/src/pages/ServerInfo/List.tsx +++ b/web/src/pages/ServerInfo/List.tsx @@ -54,7 +54,7 @@ const ServerInfo: React.FC = () => { setData( nodeList.find((item) => { return item.id === value; - }) + }), ); }} > diff --git a/web/src/pages/ServerInfo/service.ts b/web/src/pages/ServerInfo/service.ts index 0dc2029..60fab5b 100644 --- a/web/src/pages/ServerInfo/service.ts +++ b/web/src/pages/ServerInfo/service.ts @@ -17,7 +17,7 @@ import { request } from 'umi'; export const fetchInfoList = () => { - return request<Res<ResListData<ServerInfoModule.Node>>>( - '/server_info', - ).then(({ data }) => data.rows); + return request<Res<ResListData<ServerInfoModule.Node>>>('/server_info').then( + ({ data }) => data.rows, + ); }; diff --git a/web/src/pages/Service/Create.tsx b/web/src/pages/Service/Create.tsx index 3c8bf3a..5a644f5 100644 --- a/web/src/pages/Service/Create.tsx +++ b/web/src/pages/Service/Create.tsx @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useState, useRef, useEffect } from 'react' +import React, { useState, useRef, useEffect } from 'react'; import { useIntl, history } from 'umi'; import { Card, Steps, Form, notification } from 'antd'; import { PageHeaderWrapper } from '@ant-design/pro-layout'; @@ -24,7 +24,7 @@ import ActionBar from '@/components/ActionBar'; import PluginPage from '@/components/Plugin'; import { DEFAULT_UPSTREAM } from '@/components/Upstream'; import Preview from './components/Preview'; -import Step1 from "./components/Step1"; +import Step1 from './components/Step1'; import { create, update, fetchItem } from './service'; const { Step } = Steps; @@ -40,13 +40,12 @@ const Page: React.FC = (props) => { formatMessage({ id: 'page.service.steps.stepTitle.basicInformation' }), formatMessage({ id: 'page.service.steps.stepTitle.pluginConfig' }), formatMessage({ id: 'component.global.steps.stepTitle.preview' }), - ] + ]; const [stepHeader] = useState(STEP_HEADER); const [step, setStep] = useState(1); useEffect(() => { - // init upstream default value upstreamForm.setFieldsValue(DEFAULT_UPSTREAM); @@ -82,12 +81,13 @@ const Page: React.FC = (props) => { (serviceId ? update(serviceId, data) : create(data)) .then(() => { notification.success({ - message: `${serviceId - ? formatMessage({ id: 'component.global.edit' }) - : formatMessage({ id: 'component.global.create' }) - } ${formatMessage({ id: 'menu.service' })} ${formatMessage({ - id: 'component.status.success', - })}`, + message: `${ + serviceId + ? formatMessage({ id: 'component.global.edit' }) + : formatMessage({ id: 'component.global.create' }) + } ${formatMessage({ id: 'menu.service' })} ${formatMessage({ + id: 'component.status.success', + })}`, }); history.push('/service/list'); }) @@ -101,43 +101,44 @@ const Page: React.FC = (props) => { form.validateFields().then(() => { upstreamForm.validateFields().then(() => { setStep(nextStep); - }) - }) + }); + }); return; } if (nextStep === 4) { onSubmit(); return; - }; + } setStep(nextStep); - } + }; - return (<> - <PageHeaderWrapper - title={`${(props as any).match.params.rid - ? formatMessage({ id: 'component.global.edit' }) - : formatMessage({ id: 'component.global.create' }) + return ( + <> + <PageHeaderWrapper + title={`${ + (props as any).match.params.rid + ? formatMessage({ id: 'component.global.edit' }) + : formatMessage({ id: 'component.global.create' }) } ${formatMessage({ id: 'menu.service' })}`} - > - <Card bordered={false}> - <Steps current={step - 1} style={{ marginBottom: "25px" }}> - {stepHeader.map((item) => ( - <Step title={item} key={item} /> - ))} - </Steps> - {step === 1 && <Step1 - form={form} - upstreamForm={upstreamForm} - upstreamRef={upstreamRef} - />} - {step === 2 && ( - <PluginPage initialData={plugins} onChange={setPlugins} schemaType="route" /> - )} - {step === 3 && <Preview upstreamForm={upstreamForm} form={form} plugins={plugins} />} - </Card> - </PageHeaderWrapper> - <ActionBar step={step} lastStep={3} onChange={onStepChange} withResultView /> - </>) -} + > + <Card bordered={false}> + <Steps current={step - 1} style={{ marginBottom: '25px' }}> + {stepHeader.map((item) => ( + <Step title={item} key={item} /> + ))} + </Steps> + {step === 1 && ( + <Step1 form={form} upstreamForm={upstreamForm} upstreamRef={upstreamRef} /> + )} + {step === 2 && ( + <PluginPage initialData={plugins} onChange={setPlugins} schemaType="route" /> + )} + {step === 3 && <Preview upstreamForm={upstreamForm} form={form} plugins={plugins} />} + </Card> + </PageHeaderWrapper> + <ActionBar step={step} lastStep={3} onChange={onStepChange} withResultView /> + </> + ); +}; export default Page; diff --git a/web/src/pages/Service/List.tsx b/web/src/pages/Service/List.tsx index e3e5b99..c14d11c 100644 --- a/web/src/pages/Service/List.tsx +++ b/web/src/pages/Service/List.tsx @@ -31,7 +31,7 @@ const Page: React.FC = () => { { title: 'ID', dataIndex: 'id', - hideInSearch: true + hideInSearch: true, }, { title: formatMessage({ id: 'component.global.name' }), @@ -81,23 +81,26 @@ const Page: React.FC = () => { }, ]; - return (<PageHeaderWrapper - title={`${formatMessage({ id: 'menu.service' })} ${formatMessage({ - id: 'component.global.list', - })}`} - > - <ProTable<ServiceModule.ResponseBody> - actionRef={ref} - rowKey="id" - columns={columns} - request={fetchList} - toolBarRender={() => [ - <Button type="primary" onClick={() => history.push(`/service/create`)}> - <PlusOutlined /> - {formatMessage({ id: 'component.global.create' })} - </Button>, - ]} /> - </PageHeaderWrapper>) -} + return ( + <PageHeaderWrapper + title={`${formatMessage({ id: 'menu.service' })} ${formatMessage({ + id: 'component.global.list', + })}`} + > + <ProTable<ServiceModule.ResponseBody> + actionRef={ref} + rowKey="id" + columns={columns} + request={fetchList} + toolBarRender={() => [ + <Button type="primary" onClick={() => history.push(`/service/create`)}> + <PlusOutlined /> + {formatMessage({ id: 'component.global.create' })} + </Button>, + ]} + /> + </PageHeaderWrapper> + ); +}; export default Page; diff --git a/web/src/pages/Service/components/Step1.tsx b/web/src/pages/Service/components/Step1.tsx index d1f508d..fd805ba 100644 --- a/web/src/pages/Service/components/Step1.tsx +++ b/web/src/pages/Service/components/Step1.tsx @@ -42,30 +42,26 @@ const Step1: React.FC<ServiceModule.Step1PassProps> = ({ fetchUpstreamList().then(({ data }) => setList(data)); }, []); - return <> - <Form {...FORM_LAYOUT} form={form}> - <Form.Item - name="name" - label={formatMessage({ id: 'component.global.name' })} - > - <Input disabled={disabled} /> - </Form.Item> - <Form.Item - name="desc" - label={formatMessage({ id: 'component.global.description' })} - > - <Input.TextArea disabled={disabled} /> - </Form.Item> - </Form> - <UpstreamForm - ref={upstreamRef} - form={upstreamForm} - disabled={disabled} - list={list} - showSelector - key={1} - /> - </> -} + return ( + <> + <Form {...FORM_LAYOUT} form={form}> + <Form.Item name="name" label={formatMessage({ id: 'component.global.name' })}> + <Input disabled={disabled} /> + </Form.Item> + <Form.Item name="desc" label={formatMessage({ id: 'component.global.description' })}> + <Input.TextArea disabled={disabled} /> + </Form.Item> + </Form> + <UpstreamForm + ref={upstreamRef} + form={upstreamForm} + disabled={disabled} + list={list} + showSelector + key={1} + /> + </> + ); +}; export default Step1; diff --git a/web/src/pages/Service/locales/en-US.ts b/web/src/pages/Service/locales/en-US.ts index 2923865..cb26341 100644 --- a/web/src/pages/Service/locales/en-US.ts +++ b/web/src/pages/Service/locales/en-US.ts @@ -15,7 +15,7 @@ * limitations under the License. */ export default { - 'page.service.steps.stepTitle.basicInformation': 'Basic Information', - 'page.service.steps.stepTitle.pluginConfig': 'Plugin Config', - 'page.service.steps.stepTitle.preview': 'Preview', -} + 'page.service.steps.stepTitle.basicInformation': 'Basic Information', + 'page.service.steps.stepTitle.pluginConfig': 'Plugin Config', + 'page.service.steps.stepTitle.preview': 'Preview', +}; diff --git a/web/src/pages/Service/locales/zh-CN.ts b/web/src/pages/Service/locales/zh-CN.ts index 53fda03..4050259 100644 --- a/web/src/pages/Service/locales/zh-CN.ts +++ b/web/src/pages/Service/locales/zh-CN.ts @@ -15,7 +15,7 @@ * limitations under the License. */ export default { - 'page.service.steps.stepTitle.basicInformation': '基本信息', - 'page.service.steps.stepTitle.pluginConfig': '插件配置', - 'page.service.steps.stepTitle.preview': '预览', -} + 'page.service.steps.stepTitle.basicInformation': '基本信息', + 'page.service.steps.stepTitle.pluginConfig': '插件配置', + 'page.service.steps.stepTitle.preview': '预览', +}; diff --git a/web/src/pages/Service/service.ts b/web/src/pages/Service/service.ts index 1b541b2..bda706e 100644 --- a/web/src/pages/Service/service.ts +++ b/web/src/pages/Service/service.ts @@ -47,7 +47,8 @@ export const update = (serviceId: string, data: ServiceModule.Entity) => data, }); -export const remove = (serviceId: string) => request(`/services/${serviceId}`, { method: 'DELETE' }); +export const remove = (serviceId: string) => + request(`/services/${serviceId}`, { method: 'DELETE' }); export const fetchItem = (serviceId: number) => - request(`/services/${serviceId}`).then((data) => (data)); + request(`/services/${serviceId}`).then((data) => data); diff --git a/web/src/pages/Service/typing.d.ts b/web/src/pages/Service/typing.d.ts index a9e52d0..3be9c32 100644 --- a/web/src/pages/Service/typing.d.ts +++ b/web/src/pages/Service/typing.d.ts @@ -15,33 +15,32 @@ * limitations under the License. */ declare namespace ServiceModule { - - type Entity = { - name: string; - desc: string; - upstream: any; - upstream_id: string; - labels: string; - enable_websocket: boolean; - plugins: { - [name: string]: any; - }; + type Entity = { + name: string; + desc: string; + upstream: any; + upstream_id: string; + labels: string; + enable_websocket: boolean; + plugins: { + [name: string]: any; }; + }; - type ResponseBody = { - id: string, - plugins: Record<string, any>, - upstream_id: string, - upstream: Record<string, any>, - name: string, - desc: string, - enable_websocket: boolean, - } + type ResponseBody = { + id: string; + plugins: Record<string, any>; + upstream_id: string; + upstream: Record<string, any>; + name: string; + desc: string; + enable_websocket: boolean; + }; - type Step1PassProps = { - form: FormInstance; - upstreamForm: FormInstance; - disabled?: boolean; - upstreamRef: any; - }; + type Step1PassProps = { + form: FormInstance; + upstreamForm: FormInstance; + disabled?: boolean; + upstreamRef: any; + }; } diff --git a/web/src/pages/Upstream/Create.tsx b/web/src/pages/Upstream/Create.tsx index 09e14de..2840b8f 100644 --- a/web/src/pages/Upstream/Create.tsx +++ b/web/src/pages/Upstream/Create.tsx @@ -54,9 +54,9 @@ const Page: React.FC = (props) => { notification.success({ message: `${ id - ? formatMessage({ id: 'upstream.create.edit' }) - : formatMessage({ id: 'upstream.create.create' }) - } ${formatMessage({ id: 'upstream.create.upstream.successfully' })}`, + ? formatMessage({ id: 'page.upstream.create.edit' }) + : formatMessage({ id: 'page.upstream.create.create' }) + } ${formatMessage({ id: 'page.upstream.create.upstream.successfully' })}`, }); history.replace('/upstream/list'); }); @@ -77,11 +77,11 @@ const Page: React.FC = (props) => { return ( <> - <PageContainer title={formatMessage({ id: 'upstream.create.create' })}> + <PageContainer title={formatMessage({ id: 'page.upstream.create.create' })}> <Card bordered={false}> <Steps current={step - 1} style={{ marginBottom: 30 }}> - <Steps.Step title={formatMessage({ id: 'upstream.create.basic.info' })} /> - <Steps.Step title={formatMessage({ id: 'upstream.create.preview' })} /> + <Steps.Step title={formatMessage({ id: 'page.upstream.create.basic.info' })} /> + <Steps.Step title={formatMessage({ id: 'page.upstream.create.preview' })} /> </Steps> {step === 1 && <Step1 form={form1} upstreamRef={upstreamRef} />} diff --git a/web/src/pages/Upstream/List.tsx b/web/src/pages/Upstream/List.tsx index 1f3d80e..5af67af 100644 --- a/web/src/pages/Upstream/List.tsx +++ b/web/src/pages/Upstream/List.tsx @@ -31,27 +31,27 @@ const Page: React.FC = () => { const columns: ProColumns<UpstreamModule.ResponseBody>[] = [ { - title: formatMessage({ id: 'upstream.list.name' }), + title: formatMessage({ id: 'page.upstream.list.name' }), dataIndex: 'name', }, { - title: formatMessage({ id: 'upstream.list.type' }), + title: formatMessage({ id: 'page.upstream.list.type' }), dataIndex: 'type', hideInSearch: true, }, { - title: formatMessage({ id: 'upstream.list.description' }), + title: formatMessage({ id: 'page.upstream.list.description' }), dataIndex: 'desc', hideInSearch: true, }, { - title: formatMessage({ id: 'upstream.list.edit.time' }), + title: formatMessage({ id: 'page.upstream.list.edit.time' }), dataIndex: 'update_time', hideInSearch: true, render: (text) => timestampToLocaleString(text as number), }, { - title: formatMessage({ id: 'upstream.list.operation' }), + title: formatMessage({ id: 'page.upstream.list.operation' }), valueType: 'option', hideInSearch: true, render: (_, record) => ( @@ -61,16 +61,16 @@ const Page: React.FC = () => { style={{ marginRight: 10 }} onClick={() => history.push(`/upstream/${record.id}/edit`)} > - {formatMessage({ id: 'upstream.list.edit' })} + {formatMessage({ id: 'page.upstream.list.edit' })} </Button> <Popconfirm - title={formatMessage({ id: 'upstream.list.confirm.delete' })} - okText={formatMessage({ id: 'upstream.list.confirm' })} - cancelText={formatMessage({ id: 'upstream.list.cancel' })} + title={formatMessage({ id: 'page.upstream.list.confirm.delete' })} + okText={formatMessage({ id: 'page.upstream.list.confirm' })} + cancelText={formatMessage({ id: 'page.upstream.list.cancel' })} onConfirm={() => { remove(record.id!).then(() => { notification.success({ - message: formatMessage({ id: 'upstream.list.delete.successfully' }), + message: formatMessage({ id: 'page.upstream.list.delete.successfully' }), }); /* eslint-disable no-unused-expressions */ ref.current?.reload(); @@ -78,7 +78,7 @@ const Page: React.FC = () => { }} > <Button type="primary" danger> - {formatMessage({ id: 'upstream.list.delete' })} + {formatMessage({ id: 'page.upstream.list.delete' })} </Button> </Popconfirm> </> @@ -87,12 +87,16 @@ const Page: React.FC = () => { ]; return ( - <PageContainer title={formatMessage({ id: 'upstream.list' })}> + <PageContainer title={formatMessage({ id: 'page.upstream.list' })}> <ProTable<UpstreamModule.ResponseBody> actionRef={ref} columns={columns} rowKey="id" request={fetchList} + search={{ + searchText: formatMessage({ id: 'component.global.search' }), + resetText: formatMessage({ id: 'component.global.reset' }), + }} toolBarRender={() => [ <Button type="primary" onClick={() => history.push(`/upstream/create`)}> <PlusOutlined /> diff --git a/web/src/pages/Upstream/components/Step1.tsx b/web/src/pages/Upstream/components/Step1.tsx index 1e6b4f6..79b8659 100644 --- a/web/src/pages/Upstream/components/Step1.tsx +++ b/web/src/pages/Upstream/components/Step1.tsx @@ -40,19 +40,19 @@ const Step1: React.FC<Props> = ({ form, disabled, upstreamRef }) => { <> <Form labelCol={{ span: 3 }} form={form} initialValues={DEFAULT_UPSTREAM}> <Form.Item - label={formatMessage({ id: 'upstream.step.name' })} + label={formatMessage({ id: 'page.upstream.step.name' })} name="name" rules={[{ required: true }]} - extra={formatMessage({ id: 'upstream.step.name.should.unique' })} + extra={formatMessage({ id: 'page.upstream.step.name.should.unique' })} > <Input - placeholder={formatMessage({ id: 'upstream.step.input.upstream.name' })} + placeholder={formatMessage({ id: 'page.upstream.step.input.upstream.name' })} disabled={disabled} /> </Form.Item> - <Form.Item label={formatMessage({ id: 'upstream.step.description' })} name="desc"> + <Form.Item label={formatMessage({ id: 'page.upstream.step.description' })} name="desc"> <Input.TextArea - placeholder={formatMessage({ id: 'upstream.step.input.description' })} + placeholder={formatMessage({ id: 'page.upstream.step.input.description' })} disabled={disabled} /> </Form.Item> diff --git a/web/src/pages/Upstream/locales/en-US.ts b/web/src/pages/Upstream/locales/en-US.ts index a339961..e94583f 100644 --- a/web/src/pages/Upstream/locales/en-US.ts +++ b/web/src/pages/Upstream/locales/en-US.ts @@ -15,80 +15,89 @@ * limitations under the License. */ export default { - 'upstream.step.backend.server.domain.or.ip': 'Backend Server Domain Name/IP', - 'upstream.step.domain.name.default.analysis': + 'page.upstream.step.select.upstream': 'Select Upstream', + 'page.upstream.step.select.upstream.select.option': 'Manual fill', + 'page.upstream.form.item-label.node.domain.or.ip': 'Node Domain/IP', + 'page.upstream.step.backend.server.domain.or.ip': 'Backend Server Domain Name/IP', + 'page.upstream.form.item.extra-message.node.domain.or.ip': 'When using domain name, it will analysis local: /etc/resolv.conf by default, if weight is 0, then fusing this node', - 'upstream.step.input.domain.name.or.ip': 'Please input domain name/IP', - 'upstream.step.domain.name.or.ip.rule': 'Only letters, numbers and . are supported', - 'upstream.step.domain.name.or.ip': 'Domain Name/IP', - 'upstream.step.input.port': 'Please input port number', - 'upstream.step.port': 'Port Number', - 'upstream.step.input.weight': 'Please input weight', - 'upstream.step.weight': 'Weight', - 'upstream.step.create': 'Create', - 'upstream.step.name': 'Name', - 'upstream.step.name.should.unique': 'Name should be unique', - 'upstream.step.input.upstream.name': 'Please input upstream name', - 'upstream.step.description': 'Description', - 'upstream.step.input.description': 'Please input description', - 'upstream.step.type': 'Type', - 'upstream.step.pass-host': 'Pass Host', - 'upstream.step.pass-host.tips': 'When selecting node, there can only be ONE node in node list.', - 'upstream.step.pass-host.pass': 'pass', - 'upstream.step.pass-host.node': 'node', - 'upstream.step.pass-host.rewrite': 'rewrite', - 'upstream.step.pass-host.upstream_host': 'Upstream Host', - 'upstream.step.connect.timeout': 'Connect Timeout', - 'upstream.step.input.connect.timeout': 'Please input connect timeout', - 'upstream.step.send.timeout': 'Send Timeout', - 'upstream.step.input.send.timeout': 'Please input send timeout', - 'upstream.step.read.timeout': 'Read Timeout', - 'upstream.step.input.read.timeout': 'Please input read timeout', - 'upstream.step.healthy.check': 'Upstream Healthy Check', - 'upstream.step.healthy.checks.healthy': 'Healthy', - 'upstream.step.healthy.checks.unhealthy': 'Unhealthy', - 'upstream.step.healthy.checks.active': 'Upstream Healthy Check Active', - 'upstream.step.healthy.checks.active.timeout': 'Timeout', - 'upstream.step.input.healthy.checks.active.timeout': 'Please input timeout', - 'upstream.step.healthy.checks.active.http_path': 'HttpPath', - 'upstream.step.input.healthy.checks.active.http_path': 'HttpPath', - 'upstream.step.healthy.checks.active.port': "Port", - 'upstream.step.input.healthy.checks.active.port': 'Please input port', - 'upstream.step.healthy.checks.active.host': 'Host', - 'upstream.step.input.healthy.checks.active.host': 'Please input Host', - 'upstream.step.healthy.checks.active.interval': 'Interval', - 'upstream.step.input.healthy.checks.active.interval': 'Please input Interval', - 'upstream.step.healthy.checks.successes': 'Successes', - 'upstream.step.input.healthy.checks.successes': 'Please input successes', - 'upstream.step.healthy.checks.http_failures': 'HttpFailures', - 'upstream.step.input.healthy.checks.http_failures': 'Please input httpFailures', - 'upstream.step.healthy.checks.active.req_headers': 'req_headers', - 'upstream.step.input.healthy.checks.active.req_headers': 'Please input req_headers', - 'upstream.step.healthy.checks.passive': 'Passive', - 'upstream.step.healthy.checks.passive.http_statuses': 'http_statuses', - 'upstream.step.input.healthy.checks.passive.http_statuses': 'Please input http_statuses', - 'upstream.step.healthy.checks.passive.tcp_failures': 'tcp_failures', - 'upstream.step.input.healthy.checks.passive.tcp_failures': 'Please input tcp_failures', - 'upstream.notificationMessage.enableHealthCheckFirst': 'Please enable health check first.', + 'page.upstream.step.input.domain.name.or.ip': 'Please input domain name/IP', + 'page.upstream.step.domain.name.or.ip.rule': 'Only letters, numbers and . are supported', + 'page.upstream.step.domain.name.or.ip': 'Domain Name/IP', + 'page.upstream.step.input.port': 'Please input port number', + 'page.upstream.step.port': 'Port Number', + 'page.upstream.step.input.weight': 'Please input weight', + 'page.upstream.step.weight': 'Weight', + 'page.upstream.step.create': 'Create', + 'page.upstream.step.name': 'Name', + 'page.upstream.step.name.should.unique': 'Name should be unique', + 'page.upstream.step.input.upstream.name': 'Please input upstream name', + 'page.upstream.step.description': 'Description', + 'page.upstream.step.input.description': 'Please input description', + 'page.upstream.step.type': 'Type', + 'page.upstream.step.create.node': 'Create Node', + 'page.upstream.step.pass-host': 'Pass Host', + 'page.upstream.step.pass-host.tips': + 'When selecting node, there can only be ONE node in node list.', + 'page.upstream.step.pass-host.pass': 'pass', + 'page.upstream.step.pass-host.node': 'node', + 'page.upstream.step.pass-host.rewrite': 'rewrite', + 'page.upstream.step.pass-host.upstream_host': 'Upstream Host', + 'page.upstream.step.connect.timeout': 'Connect Timeout', + 'page.upstream.step.input.connect.timeout': 'Please input connect timeout', + 'page.upstream.step.send.timeout': 'Send Timeout', + 'page.upstream.step.input.send.timeout': 'Please input send timeout', + 'page.upstream.step.read.timeout': 'Read Timeout', + 'page.upstream.step.input.read.timeout': 'Please input read timeout', + 'page.upstream.step.healthyCheck.healthy.check': 'Health Check', + 'page.upstream.step.healthyCheck.healthy': 'Healthy', + 'page.upstream.step.healthyCheck.unhealthy': 'Unhealthy', + 'page.upstream.step.healthyCheck.healthy.status': 'Healthy Status', + 'page.upstream.step.healthyCheck.unhealthyStatus': 'Unhealthy Status', + 'page.upstream.step.healthyCheck.active': 'Active', + 'page.upstream.step.healthyCheck.active.timeout': 'Timeout', + 'page.upstream.step.input.healthyCheck.active.timeout': 'Please input timeout', + 'page.upstream.step.healthyCheck.active.http_path': 'HTTP Path', + 'page.upstream.step.input.healthyCheck.active.http_path': 'Please input HTTP path', + 'page.upstream.step.healthyCheck.activePort': 'Port', + 'page.upstream.step.input.healthyCheck.activePort': 'Port', + 'page.upstream.step.healthyCheck.activeHost': 'Host', + 'page.upstream.step.input.healthyCheck.activeHost': 'Please input active host', + 'page.upstream.step.healthyCheck.activeInterval': 'Interval', + 'page.upstream.step.input.healthyCheck.activeInterval': 'Please input interval', + 'page.upstream.step.healthyCheck.successes': 'Successes', + 'page.upstream.step.input.healthyCheck.successes': 'Please input successes', + 'page.upstream.step.healthyCheck.http_failures': 'HTTP Failures', + 'page.upstream.step.healthyCheck.active.create.req_headers': 'Create Request Headers', + 'page.upstream.step.input.healthyCheck.http_failures': 'Please input http failures', + 'page.upstream.step.healthyCheck.active.req_headers': 'Request Headers', + 'page.upstream.step.input.healthyCheck.active.req_headers': 'Please input request headers', + 'page.upstream.step.healthyCheck.passive': 'Passive', + 'page.upstream.step.healthyCheck.passive.create.http_statuses': 'Create HTTP Status', + 'page.upstream.step.healthyCheck.passive.http_statuses': 'HTTP Status', + 'page.upstream.step.input.healthyCheck.passive.http_statuses': 'Please input http status', + 'page.upstream.step.healthyCheck.passive.tcp_failures': 'TCP Failures', + 'page.upstream.step.input.healthyCheck.passive.tcp_failures': 'Please input TCP failures', + 'page.upstream.notificationMessage.enableHealthCheckFirst': 'Please enable health check first.', - 'upstream.create.edit': 'Edit', - 'upstream.create.create': 'Create', - 'upstream.create.upstream.successfully': 'upstream successfully', - 'upstream.create.basic.info': 'Basic Information', - 'upstream.create.preview': 'Preview', + 'page.upstream.create.edit': 'Edit', + 'page.upstream.create.create': 'Create', + 'page.upstream.create.upstream.successfully': 'upstream successfully', + 'page.upstream.create.basic.info': 'Basic Information', + 'page.upstream.create.preview': 'Preview', - 'upstream.list.name': 'Name', - 'upstream.list.type': 'Type', - 'upstream.list.description': 'Description', - 'upstream.list.edit.time': 'Edit Time', - 'upstream.list.operation': 'Operation', - 'upstream.list.edit': 'Edit', - 'upstream.list.confirm.delete': 'Are you sure to delete ?', - 'upstream.list.confirm': 'Confirm', - 'upstream.list.cancel': 'Cancel', - 'upstream.list.delete.successfully': 'Delete successfully', - 'upstream.list.delete': 'Delete', - 'upstream.list': 'Upstream List', - 'upstream.list.input': 'Please input', - 'upstream.list.create': 'Create', + 'page.upstream.list.name': 'Name', + 'page.upstream.list.type': 'Type', + 'page.upstream.list.description': 'Description', + 'page.upstream.list.edit.time': 'Edit Time', + 'page.upstream.list.operation': 'Operation', + 'page.upstream.list.edit': 'Edit', + 'page.upstream.list.confirm.delete': 'Are you sure to delete ?', + 'page.upstream.list.confirm': 'Confirm', + 'page.upstream.list.cancel': 'Cancel', + 'page.upstream.list.delete.successfully': 'Delete successfully', + 'page.upstream.list.delete': 'Delete', + 'page.upstream.list': 'Upstream List', + 'page.upstream.list.input': 'Please input', + 'page.upstream.list.create': 'Create', }; diff --git a/web/src/pages/Upstream/locales/zh-CN.ts b/web/src/pages/Upstream/locales/zh-CN.ts index 44bae36..335d378 100644 --- a/web/src/pages/Upstream/locales/zh-CN.ts +++ b/web/src/pages/Upstream/locales/zh-CN.ts @@ -15,80 +15,88 @@ * limitations under the License. */ export default { - 'upstream.step.backend.server.domain.or.ip': '后端服务域名/IP', - 'upstream.step.domain.name.default.analysis': + 'page.upstream.step.select.upstream': '选择上游', + 'page.upstream.step.select.upstream.select.option': '手动填写', + 'page.upstream.form.item-label.node.domain.or.ip': '节点域名/IP', + 'page.upstream.step.backend.server.domain.or.ip': '后端服务域名/IP', + 'page.upstream.form.item.extra-message.node.domain.or.ip': '使用域名时,默认解析本地 /etc/resolv.conf;权重为0则熔断该节点', - 'upstream.step.input.domain.name.or.ip': '请输入域名/IP', - 'upstream.step.domain.name.or.ip.rule': '仅支持字母、数字和 . ', - 'upstream.step.domain.name.or.ip': '域名/IP', - 'upstream.step.input.port': '请输入端口号', - 'upstream.step.port': '端口号', - 'upstream.step.input.weight': '请输入权重', - 'upstream.step.weight': '权重', - 'upstream.step.create': '创建', - 'upstream.step.name': '名称', - 'upstream.step.name.should.unique': '名称需全局唯一', - 'upstream.step.input.upstream.name': '请输入上游名称', - 'upstream.step.description': '描述', - 'upstream.step.input.description': '请输入描述', - 'upstream.step.type': '类型', - 'upstream.step.pass-host': '传递域名', - 'upstream.step.pass-host.tips': '当选择节点时,节点域名只能有一条数据。', - 'upstream.step.pass-host.pass': '透传', - 'upstream.step.pass-host.node': '节点', - 'upstream.step.pass-host.rewrite': '重写', - 'upstream.step.pass-host.upstream_host': '上游域名', - 'upstream.step.connect.timeout': '连接超时', - 'upstream.step.input.connect.timeout': '请输入连接超时时间', - 'upstream.step.send.timeout': '发送超时', - 'upstream.step.input.send.timeout': '请输入发送超时时间', - 'upstream.step.read.timeout': '接收超时', - 'upstream.step.input.read.timeout': '请输入接收超时时间', - 'upstream.step.healthy.check': '上游健康检查', - 'upstream.step.healthy.checks.healthy': '健康', - 'upstream.step.healthy.checks.unhealthy': '不健康', - 'upstream.step.healthy.checks.active': '探活健康检查', - 'upstream.step.healthy.checks.active.timeout': '超时时间', - 'upstream.step.input.healthy.checks.active.timeout': '请输入超时时间', - 'upstream.step.healthy.checks.active.http_path': '路径', - 'upstream.step.input.healthy.checks.active.http_path': '请输入路径', - 'upstream.step.healthy.checks.active.port': "端口", - 'upstream.step.input.healthy.checks.active.port': '请输入端口', - 'upstream.step.healthy.checks.active.host': '域名', - 'upstream.step.input.healthy.checks.active.host': '请输入域名', - 'upstream.step.healthy.checks.active.interval': '间隔', - 'upstream.step.input.healthy.checks.active.interval': '请输入间隔', - 'upstream.step.healthy.checks.successes': '成功次数', - 'upstream.step.input.healthy.checks.successes': '请输入成功次数', - 'upstream.step.healthy.checks.http_failures': '失败次数', - 'upstream.step.input.healthy.checks.http_failures': '请输入失败次数', - 'upstream.step.healthy.checks.active.req_headers': '请求头', - 'upstream.step.input.healthy.checks.active.req_headers': '请输入请求头', - 'upstream.step.healthy.checks.passive': '被动健康检查', - 'upstream.step.healthy.checks.passive.http_statuses': '状态码', - 'upstream.step.input.healthy.checks.passive.http_statuses': '请输入状态码', - 'upstream.step.healthy.checks.passive.tcp_failures': 'tcp失败次数', - 'upstream.step.input.healthy.checks.passive.tcp_failures': '请输入tcp失败次数', - 'upstream.notificationMessage.enableHealthCheckFirst': '请先启用探活健康检查。', + 'page.upstream.step.input.domain.name.or.ip': '请输入域名/IP', + 'page.upstream.step.domain.name.or.ip.rule': '仅支持字母、数字和 . ', + 'page.upstream.step.domain.name.or.ip': '域名/IP', + 'page.upstream.step.input.port': '请输入端口号', + 'page.upstream.step.port': '端口号', + 'page.upstream.step.input.weight': '请输入权重', + 'page.upstream.step.weight': '权重', + 'page.upstream.step.create': '创建', + 'page.upstream.step.name': '名称', + 'page.upstream.step.name.should.unique': '名称需全局唯一', + 'page.upstream.step.input.upstream.name': '请输入上游名称', + 'page.upstream.step.description': '描述', + 'page.upstream.step.input.description': '请输入描述', + 'page.upstream.step.type': '类型', + 'page.upstream.step.create.node': '创建节点', + 'page.upstream.step.pass-host': '传递域名', + 'page.upstream.step.pass-host.tips': '当选择节点时,节点域名只能有一条数据。', + 'page.upstream.step.pass-host.pass': '透传', + 'page.upstream.step.pass-host.node': '节点', + 'page.upstream.step.pass-host.rewrite': '重写', + 'page.upstream.step.pass-host.upstream_host': '上游域名', + 'page.upstream.step.connect.timeout': '连接超时', + 'page.upstream.step.input.connect.timeout': '请输入连接超时时间', + 'page.upstream.step.send.timeout': '发送超时', + 'page.upstream.step.input.send.timeout': '请输入发送超时时间', + 'page.upstream.step.read.timeout': '接收超时', + 'page.upstream.step.input.read.timeout': '请输入接收超时时间', + 'page.upstream.step.healthyCheck.healthy.check': '健康检查', + 'page.upstream.step.healthyCheck.healthy': '健康', + 'page.upstream.step.healthyCheck.unhealthy': '不健康', + 'page.upstream.step.healthyCheck.healthy.status': '健康状态', + 'page.upstream.step.healthyCheck.unhealthyStatus': '不健康状态', + 'page.upstream.step.healthyCheck.active': '主动', + 'page.upstream.step.healthyCheck.active.timeout': '超时时间', + 'page.upstream.step.input.healthyCheck.active.timeout': '请输入超时时间', + 'page.upstream.step.healthyCheck.active.http_path': '路径', + 'page.upstream.step.input.healthyCheck.active.http_path': '请输入路径', + 'page.upstream.step.healthyCheck.activePort': '端口', + 'page.upstream.step.input.healthyCheck.activePort': '请输入端口', + 'page.upstream.step.healthyCheck.activeHost': '域名', + 'page.upstream.step.input.healthyCheck.activeHost': '请输入域名', + 'page.upstream.step.healthyCheck.activeInterval': '间隔', + 'page.upstream.step.input.healthyCheck.activeInterval': '请输入间隔', + 'page.upstream.step.healthyCheck.successes': '成功次数', + 'page.upstream.step.input.healthyCheck.successes': '请输入成功次数', + 'page.upstream.step.healthyCheck.http_failures': '失败次数', + 'page.upstream.step.healthyCheck.active.create.req_headers': '创建请求头', + 'page.upstream.step.input.healthyCheck.http_failures': '请输入失败次数', + 'page.upstream.step.healthyCheck.active.req_headers': '请求头', + 'page.upstream.step.input.healthyCheck.active.req_headers': '请输入请求头', + 'page.upstream.step.healthyCheck.passive': '被动', + 'page.upstream.step.healthyCheck.passive.create.http_statuses': '创建状态码', + 'page.upstream.step.healthyCheck.passive.http_statuses': '状态码', + 'page.upstream.step.input.healthyCheck.passive.http_statuses': '请输入状态码', + 'page.upstream.step.healthyCheck.passive.tcp_failures': 'tcp失败次数', + 'page.upstream.step.input.healthyCheck.passive.tcp_failures': '请输入tcp失败次数', + 'page.upstream.notificationMessage.enableHealthCheckFirst': '请先启用探活健康检查。', - 'upstream.create.edit': '编辑', - 'upstream.create.create': '创建', - 'upstream.create.upstream.successfully': '上游成功', - 'upstream.create.basic.info': '基础信息', - 'upstream.create.preview': '预览', + 'page.upstream.create.edit': '编辑', + 'page.upstream.create.create': '创建', + 'page.upstream.create.upstream.successfully': '上游成功', + 'page.upstream.create.basic.info': '基础信息', + 'page.upstream.create.preview': '预览', - 'upstream.list.name': '名称', - 'upstream.list.type': '类型', - 'upstream.list.description': '描述', - 'upstream.list.edit.time': '编辑时间', - 'upstream.list.operation': '操作', - 'upstream.list.edit': '编辑', - 'upstream.list.confirm.delete': '确定删除该条记录吗?', - 'upstream.list.confirm': '确定', - 'upstream.list.cancel': '取消', - 'upstream.list.delete.successfully': '删除记录成功', - 'upstream.list.delete': '删除', - 'upstream.list': '上游列表', - 'upstream.list.input': '请输入', - 'upstream.list.create': '创建', + 'page.upstream.list.name': '名称', + 'page.upstream.list.type': '类型', + 'page.upstream.list.description': '描述', + 'page.upstream.list.edit.time': '编辑时间', + 'page.upstream.list.operation': '操作', + 'page.upstream.list.edit': '编辑', + 'page.upstream.list.confirm.delete': '确定删除该条记录吗?', + 'page.upstream.list.confirm': '确定', + 'page.upstream.list.cancel': '取消', + 'page.upstream.list.delete.successfully': '删除记录成功', + 'page.upstream.list.delete': '删除', + 'page.upstream.list': '上游列表', + 'page.upstream.list.input': '请输入', + 'page.upstream.list.create': '创建', };