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 eb33046  feat: autocomplete when people input http header (#1679)
eb33046 is described below

commit eb3304606a28586c64b4358e2bfadbc627b83e75
Author: qian0817 <[email protected]>
AuthorDate: Mon Apr 12 23:36:54 2021 +0800

    feat: autocomplete when people input http header (#1679)
---
 web/cypress/integration/route/online-debug.spec.js | 21 ++++++
 .../Route/components/DebugViews/DebugDrawView.tsx  |  2 +-
 .../components/DebugViews/DebugParamsView.tsx      | 38 +++++++++--
 web/src/pages/Route/constants.ts                   | 76 +++++++++++++++++-----
 web/src/pages/Route/typing.d.ts                    |  1 +
 5 files changed, 115 insertions(+), 23 deletions(-)

diff --git a/web/cypress/integration/route/online-debug.spec.js 
b/web/cypress/integration/route/online-debug.spec.js
index 5f80575..f5de8a4 100644
--- a/web/cypress/integration/route/online-debug.spec.js
+++ b/web/cypress/integration/route/online-debug.spec.js
@@ -124,6 +124,27 @@ context('Online debug', () => {
     });
   });
 
+  it('should autocomplete header',function () {
+    cy.visit('/');
+    cy.contains(menuLocaleUS['menu.routes']).click();
+    const currentToken = localStorage.getItem('token');
+
+    // show online debug draw
+    cy.contains(routeLocaleUS['page.route.onlineDebug']).click();
+    cy.get(domSelector.debugDraw).should('be.visible');
+    cy.get(domSelector.headerTab).should('be.visible').click();
+
+    // show autocomplete
+    cy.get(domSelector.headerDataKey0).click({ force: true });
+    cy.get('.ant-select-item-option-content').contains('Accept').click();
+    cy.get('.anticon-minus-circle').click()
+
+    // autocomplete should ingore case
+    cy.get(domSelector.headerDataKey0).type('auth').click({ force: true });
+    
cy.get('.ant-select-item-option-content').contains('Authorization').click();
+    cy.get(domSelector.headerDataValue0).type(currentToken);
+  })
+
   it('should debug POST request with file successfully', function () {
     cy.visit('/');
     cy.contains(menuLocaleUS['menu.routes']).click();
diff --git a/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx 
b/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx
index 09300b6..60dd5de 100644
--- a/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx
+++ b/web/src/pages/Route/components/DebugViews/DebugDrawView.tsx
@@ -317,7 +317,7 @@ const DebugDrawView: React.FC<RouteModule.DebugDrawProps> = 
(props) => {
               <AuthenticationView form={authForm} />
             </TabPane>
             <TabPane data-cy='header' tab={formatMessage({ id: 
'page.route.TabPane.headerParams' })} key="header">
-              <DebugParamsView form={headerForm} name='headerForm'/>
+              <DebugParamsView form={headerForm} name='headerForm' 
inputType="header"/>
             </TabPane>
             {showBodyTab && (
               <TabPane data-cy='body' tab={formatMessage({ id: 
'page.route.TabPane.bodyParams' })} key="body">
diff --git a/web/src/pages/Route/components/DebugViews/DebugParamsView.tsx 
b/web/src/pages/Route/components/DebugViews/DebugParamsView.tsx
index 64b04a6..85fc924 100644
--- a/web/src/pages/Route/components/DebugViews/DebugParamsView.tsx
+++ b/web/src/pages/Route/components/DebugViews/DebugParamsView.tsx
@@ -14,16 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React from 'react';
-import { Form, Input, Row, Col, Checkbox } from 'antd';
+import React, { useState } from 'react';
+import { Form, Input, Row, Col, Checkbox, AutoComplete } from 'antd';
 import { useIntl } from 'umi';
 import { MinusCircleOutlined } from '@ant-design/icons';
+import { HEADER_LIST } from '@/pages/Route/constants';
 
 import styles from './index.less';
 
+const { Option } = AutoComplete;
+
 const DebugParamsView: React.FC<RouteModule.DebugViewProps> = (props) => {
   const { formatMessage } = useIntl();
 
+  const allSelectOptions = props.inputType === "header" ? HEADER_LIST : []
+  const [result, setResult] = useState<string[]>(allSelectOptions);
+
+  const onSearch = (value: string) => {
+    setResult(allSelectOptions.filter((option) => 
option.toLowerCase().startsWith(value.toLowerCase())))
+  }
+
   return (
     <Form name={props.name} className={styles.routeDebugDraw} 
form={props.form}>
       <Form.List name="params">
@@ -34,7 +44,9 @@ const DebugParamsView: React.FC<RouteModule.DebugViewProps> = 
(props) => {
                 <Row gutter={16} key={field.name}>
                   <Col span={1}>
                     <Form.Item
+                      {...field}
                       name={[field.name, 'check']}
+                      fieldKey={[field.fieldKey, 'check']}
                       style={{ textAlign: 'right' }}
                       valuePropName="checked"
                     >
@@ -42,8 +54,12 @@ const DebugParamsView: React.FC<RouteModule.DebugViewProps> 
= (props) => {
                     </Form.Item>
                   </Col>
                   <Col span={8}>
-                    <Form.Item name={[field.name, 'key']}>
-                      <Input
+                    <Form.Item
+                      {...field}
+                      name={[field.name, 'key']}
+                      fieldKey={[field.fieldKey, 'key']}>
+                      <AutoComplete
+                        onSearch={onSearch}
                         placeholder={formatMessage({ id: 
'page.route.input.placeholder.paramKey' })}
                         onChange={() => {
                           // only last line key field input can trigger add 
new line event
@@ -54,12 +70,20 @@ const DebugParamsView: React.FC<RouteModule.DebugViewProps> 
= (props) => {
                             prevData.params[index].check = true;
                             props.form.setFieldsValue(prevData);
                           }
-                        }}
-                      />
+                        }}>
+                        {result.map((value) => (
+                          <Option key={value} value={value}>
+                            {value}
+                          </Option>
+                        ))}
+                      </AutoComplete>
                     </Form.Item>
                   </Col>
                   <Col span={8}>
-                    <Form.Item name={[field.name, 'value']}>
+                    <Form.Item
+                      {...field}
+                      name={[field.name, 'value']}
+                      fieldKey={[field.fieldKey, 'value']}>
                       <Input
                         placeholder={formatMessage({
                           id: 'page.route.input.placeholder.paramValue',
diff --git a/web/src/pages/Route/constants.ts b/web/src/pages/Route/constants.ts
index a343067..ecad67e 100644
--- a/web/src/pages/Route/constants.ts
+++ b/web/src/pages/Route/constants.ts
@@ -90,23 +90,69 @@ export const INIT_CHART = {
   hovered: {},
 };
 
-export const HASH_KEY_LIST = [
-  'remote_addr',
-  'host',
-  'uri',
-  'server_name',
-  'server_addr',
-  'request_uri',
-  'query_string',
-  'remote_port',
-  'hostname',
-  'arg_id',
-];
-
-export const HASH_ON_LIST = ['vars', 'header', 'cookie', 'consumer'];
-
 export const AUTH_LIST = ['basic-auth', 'jwt-auth', 'key-auth'];
 
+export const HEADER_LIST = [
+  "A-IM",
+  "Accept",
+  "Accept-Charset",
+  "Accept-Datetime",
+  "Accept-Encoding",
+  "Accept-Language",
+  "Access-Control-Request-Method",
+  "Access-Control-Request-Headers",
+  "Allow",
+  "Authorization",
+  "Cache-Control",
+  "Connection",
+  "Content-Encoding",
+  "Content-Length",
+  "Content-MD5",
+  "Content-Type",
+  "Cookie",
+  "DNT",
+  "Date",
+  "Expect",
+  "Forwarded",
+  "From",
+  "Front-End-Https",
+  "Host",
+  "HTTP2-Settings",
+  "If-Match",
+  "If-Modified-Since",
+  "If-None-Match",
+  "If-Range",
+  "If-Unmodified-Since",
+  "Max-Forwards",
+  "Origin",
+  "Pragma",
+  "Prefer",
+  "Proxy-Authorization",
+  "Proxy-Connection",
+  "Range",
+  "Referer",
+  "Save-Data",
+  "TE",
+  "Trailer",
+  "Transfer-Encoding",
+  "Upgrade",
+  "Upgrade-Insecure-Requests",
+  "User-Agent",
+  "Via",
+  "Warning",
+  "X-ATT-DeviceId",
+  "X-Correlation-ID",
+  "X-Csrf-Token",
+  "X-Forwarded-For",
+  "X-Forwarded-Host",
+  "X-Forwarded-Proto",
+  "X-Http-Method-Override",
+  "X-Request-ID",
+  "X-Requested-With",
+  "X-UIDH",
+  "X-Wap-Profile",
+];
+
 export const PROTOCOL_SUPPORTED: 
RouteModule.debugRequest['request_protocol'][] = ['http', 'https'];
 
 export const DEFAULT_DEBUG_PARAM_FORM_DATA = {
diff --git a/web/src/pages/Route/typing.d.ts b/web/src/pages/Route/typing.d.ts
index 5fed522..2961a7a 100644
--- a/web/src/pages/Route/typing.d.ts
+++ b/web/src/pages/Route/typing.d.ts
@@ -257,6 +257,7 @@ declare namespace RouteModule {
   type DebugViewProps = {
     form: FormInstance;
     name?: string;
+    inputType?: 'param' | 'header';
   };
   type DebugBodyType = 'none' | 'x-www-form-urlencoded' | 'raw input' | 
'form-data';
   type DebugDrawProps = {

Reply via email to