You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2020/06/01 14:27:28 UTC

[incubator-apisix-dashboard] branch next updated: feat: added disabled for Step2

This is an automated email from the ASF dual-hosted git repository.

juzhiyuan pushed a commit to branch next
in repository https://gitbox.apache.org/repos/asf/incubator-apisix-dashboard.git


The following commit(s) were added to refs/heads/next by this push:
     new d85fb48  feat: added disabled for Step2
d85fb48 is described below

commit d85fb486937cd1de606c600a98d6ffd3856d626d
Author: juzhiyuan <jj...@gmail.com>
AuthorDate: Mon Jun 1 21:13:06 2020 +0800

    feat: added disabled for Step2
---
 src/pages/Routes/Create.tsx                        |  99 ++++++++--------
 .../Routes/components/Step1/MatchingRulesView.tsx  |  17 +--
 src/pages/Routes/components/Step1/MetaView.tsx     |  32 +++--
 .../Routes/components/Step1/RequestConfigView.tsx  | 129 +++++++++++----------
 src/pages/Routes/components/Step1/index.tsx        |  25 +++-
 .../components/Step2/HttpHeaderRewriteView.tsx     |  80 ++++++-------
 .../Routes/components/Step2/RequestRewriteView.tsx |  41 ++++---
 src/pages/Routes/constants.ts                      |  31 +++++
 src/pages/Routes/typing.d.ts                       |  10 +-
 9 files changed, 257 insertions(+), 207 deletions(-)

diff --git a/src/pages/Routes/Create.tsx b/src/pages/Routes/Create.tsx
index 25ac33a..ac46cfe 100644
--- a/src/pages/Routes/Create.tsx
+++ b/src/pages/Routes/Create.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useState, useEffect } from 'react';
 import { Card, Steps } from 'antd';
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
 
@@ -8,72 +8,59 @@ import styles from './Create.less';
 import CreateStep3 from './components/CreateStep3';
 import ActionBar from './components/ActionBar';
 import CreateStep4 from './components/CreateStep4';
+import { DEFAULT_STEP_1_DATA, DEFAULT_STEP_2_DATA, DEFAULT_STEP_3_DATA } from './constants';
 
 const { Step } = Steps;
 
 const Create: React.FC = () => {
-  const [step1Data, setStep1Data] = useState<RouteModule.Step1Data>({
-    name: '',
-    protocol: [],
-    hosts: [''],
-    paths: [],
-    httpMethods: [],
-    advancedMatchingRules: [],
-  });
-
-  const [step2Data, setStep2Data] = useState<RouteModule.Step2Data>({
-    backendProtocol: 'originalRequest',
-    backendAddressList: [{ host: '', port: 0, weight: 0 }],
-    upstream_header: [],
-    timeout: {
-      connect: 30000,
-      send: 30000,
-      read: 30000,
-    },
-  });
-
-  const [step3Data, setStep3Data] = useState<RouteModule.Step3Data>({
-    plugins: {
-      'limit-count': {
-        count: 2,
-        time_window: 60,
-        rejected_code: 503,
-        key: 'remote_addr',
-      },
-    },
-  });
+  const [step1Data, setStep1Data] = useState(DEFAULT_STEP_1_DATA);
+  const [step2Data, setStep2Data] = useState(DEFAULT_STEP_2_DATA);
+  const [step3Data, setStep3Data] = useState(DEFAULT_STEP_3_DATA);
 
   const [step, setStep] = useState(0);
   const [stepHeader] = useState(['定义 API 请求', '定义 API 后端服务', '插件配置', '预览']);
+
   const data = {
     step1Data,
     step2Data,
     step3Data,
   };
 
+  useEffect(() => {
+    console.log('step1Data2', step1Data);
+  }, [step1Data]);
+
   const renderStep = () => {
-    switch (step) {
-      case 0:
-        return (
-          <Step1
-            data={data}
-            onChange={(params: RouteModule.Step1Data) => setStep1Data({ ...step1Data, ...params })}
-          />
-        );
-      case 1:
-        return (
-          <Step2
-            data={data}
-            onChange={(params: RouteModule.Step2Data) => setStep2Data({ ...step2Data, ...params })}
-          />
-        );
-      case 2:
-        return <CreateStep3 data={data} onChange={setStep3Data} />;
-      case 3:
-        return <CreateStep4 data={data} onChange={() => {}} />;
-      default:
-        return null;
+    if (step === 0) {
+      return (
+        <Step1
+          data={data}
+          onChange={(_data: RouteModule.Step1Data) => {
+            console.log(_data);
+            setStep1Data(_data);
+          }}
+        />
+      );
+    }
+
+    if (step === 1) {
+      return (
+        <Step2
+          data={data}
+          onChange={(params: RouteModule.Step2Data) => setStep2Data({ ...step2Data, ...params })}
+        />
+      );
     }
+
+    if (step === 3) {
+      return <CreateStep3 data={data} onChange={setStep3Data} />;
+    }
+
+    if (step === 4) {
+      return <CreateStep4 data={data} onChange={() => {}} />;
+    }
+
+    return null;
   };
 
   return (
@@ -88,7 +75,13 @@ const Create: React.FC = () => {
           {renderStep()}
         </Card>
       </PageHeaderWrapper>
-      <ActionBar step={step} onChange={setStep} />
+      <ActionBar
+        step={step}
+        onChange={(nextStep) => {
+          setStep(nextStep);
+          window.scrollTo({ top: 0 });
+        }}
+      />
     </>
   );
 };
diff --git a/src/pages/Routes/components/Step1/MatchingRulesView.tsx b/src/pages/Routes/components/Step1/MatchingRulesView.tsx
index 8b91de2..6e95710 100644
--- a/src/pages/Routes/components/Step1/MatchingRulesView.tsx
+++ b/src/pages/Routes/components/Step1/MatchingRulesView.tsx
@@ -15,12 +15,11 @@ const MatchingRulesView: React.FC<Props> = ({ data, disabled, onChange }) => {
 
   const onOk = () => {
     modalForm.validateFields().then((value) => {
-      onChange({
-        advancedMatchingRules: advancedMatchingRules.concat({
-          ...(value as RouteModule.MatchingRule),
-          key: Math.random().toString(36).slice(2),
-        }),
-      });
+      const rule = {
+        ...(value as RouteModule.MatchingRule),
+        key: Math.random().toString(36).slice(2),
+      };
+      onChange({ ...data.step1Data, advancedMatchingRules: advancedMatchingRules.concat(rule) });
       modalForm.resetFields();
       setVisible(false);
     });
@@ -32,8 +31,10 @@ const MatchingRulesView: React.FC<Props> = ({ data, disabled, onChange }) => {
   };
 
   const handleRemove = (key: string) => {
-    const filteredAdvancedMatchingRules = advancedMatchingRules.filter((item) => item.key !== key);
-    onChange({ advancedMatchingRules: filteredAdvancedMatchingRules });
+    onChange({
+      ...data.step1Data,
+      advancedMatchingRules: advancedMatchingRules.filter((item) => item.key !== key),
+    });
   };
 
   const columns = [
diff --git a/src/pages/Routes/components/Step1/MetaView.tsx b/src/pages/Routes/components/Step1/MetaView.tsx
index 02921ba..69e64c7 100644
--- a/src/pages/Routes/components/Step1/MetaView.tsx
+++ b/src/pages/Routes/components/Step1/MetaView.tsx
@@ -1,30 +1,24 @@
 import React from 'react';
-import Form, { FormInstance } from 'antd/es/form';
+import Form from 'antd/es/form';
 import { Input } from 'antd';
 
-import { FORM_ITEM_LAYOUT } from '@/pages/Routes/constants';
 import PanelSection from '../PanelSection';
-import styles from '../../Create.less';
 
-interface Props extends RouteModule.Data {
-  form: FormInstance;
-}
+interface Props extends RouteModule.Data {}
 
-const MetaView: React.FC<Props> = ({ form, disabled }) => {
+const MetaView: React.FC<Props> = ({ disabled }) => {
   return (
     <PanelSection title="名称及其描述">
-      <Form {...FORM_ITEM_LAYOUT} form={form} layout="horizontal" className={styles.stepForm}>
-        <Form.Item
-          label="API 名称"
-          name="name"
-          rules={[{ required: true, message: '请输入 API 名称' }]}
-        >
-          <Input placeholder="请输入 API 名称" disabled={disabled} />
-        </Form.Item>
-        <Form.Item label="描述" name="desc">
-          <Input.TextArea placeholder="请输入描述" disabled={disabled} />
-        </Form.Item>
-      </Form>
+      <Form.Item
+        label="API 名称"
+        name="name"
+        rules={[{ required: true, message: '请输入 API 名称' }]}
+      >
+        <Input placeholder="请输入 API 名称" disabled={disabled} />
+      </Form.Item>
+      <Form.Item label="描述" name="desc">
+        <Input.TextArea placeholder="请输入描述" disabled={disabled} />
+      </Form.Item>
     </PanelSection>
   );
 };
diff --git a/src/pages/Routes/components/Step1/RequestConfigView.tsx b/src/pages/Routes/components/Step1/RequestConfigView.tsx
index 599d4ee..4ef72fa 100644
--- a/src/pages/Routes/components/Step1/RequestConfigView.tsx
+++ b/src/pages/Routes/components/Step1/RequestConfigView.tsx
@@ -1,25 +1,17 @@
 import React, { useState } from 'react';
-import Form, { FormInstance } from 'antd/es/form';
+import Form from 'antd/es/form';
 import { Row, Checkbox, Button, Col, Input, Space } from 'antd';
 import { CheckboxValueType } from 'antd/lib/checkbox/Group';
 import { CheckboxChangeEvent } from 'antd/lib/checkbox';
 
-import { FORM_ITEM_LAYOUT, HTTP_METHOD_OPTION_LIST } from '@/pages/Routes/constants';
+import { HTTP_METHOD_OPTION_LIST } from '@/pages/Routes/constants';
 
 import PanelSection from '../PanelSection';
-import styles from '../../Create.less';
 
-interface Props extends RouteModule.Data {
-  form: FormInstance;
-}
+interface Props extends RouteModule.Data {}
 
-const RequestConfigView: React.FC<Props> = ({ data, form, disabled, onChange }) => {
-  const { paths, hosts } = data.step1Data;
-  const [protocolValueList, setProtocolValueList] = useState<RouteModule.RequestProtocol[]>([
-    'HTTP',
-    'HTTPS',
-  ]);
-  const protocolList = ['HTTP', 'HTTPS', 'WebSocket'];
+const RequestConfigView: React.FC<Props> = ({ data, disabled, onChange }) => {
+  const { paths, hosts, protocols } = data.step1Data;
   const [httpMethodList, setHttpMethodList] = useState({
     checkedList: HTTP_METHOD_OPTION_LIST,
     indeterminate: false,
@@ -28,7 +20,7 @@ const RequestConfigView: React.FC<Props> = ({ data, form, disabled, onChange })
 
   const onProtocolChange = (e: CheckboxValueType[]) => {
     if (!e.includes('HTTP') && !e.includes('HTTPS')) return;
-    setProtocolValueList(e as RouteModule.RequestProtocol[]);
+    onChange({ ...data.step1Data, protocols: e });
   };
   const onMethodsChange = (checkedList: CheckboxValueType[]) => {
     setHttpMethodList({
@@ -58,7 +50,10 @@ const RequestConfigView: React.FC<Props> = ({ data, form, disabled, onChange })
                 type="primary"
                 danger
                 onClick={() => {
-                  onChange({ hosts: hosts.filter((_, _index) => _index !== index) });
+                  onChange({
+                    ...data.step1Data,
+                    hosts: hosts.filter((_, _index) => _index !== index),
+                  });
                 }}
               >
                 删除
@@ -82,7 +77,10 @@ const RequestConfigView: React.FC<Props> = ({ data, form, disabled, onChange })
                 type="primary"
                 danger
                 onClick={() => {
-                  onChange({ paths: paths.filter((_, _index) => _index !== index) });
+                  onChange({
+                    ...data.step1Data,
+                    paths: paths.filter((_, _index) => _index !== index),
+                  });
                 }}
               >
                 删除
@@ -95,56 +93,61 @@ const RequestConfigView: React.FC<Props> = ({ data, form, disabled, onChange })
 
   return (
     <PanelSection title="请求基础定义">
-      <Form {...FORM_ITEM_LAYOUT} form={form} layout="horizontal" className={styles.stepForm}>
-        <Form.Item label="协议" name="protocol" rules={[{ required: true, message: '请勾选协议' }]}>
-          <Row>
-            <Checkbox.Group
-              disabled={disabled}
-              options={protocolList}
-              value={protocolValueList}
-              onChange={onProtocolChange}
-            />
-          </Row>
-        </Form.Item>
-        {/* TODO: name */}
-        <Form.Item label="HOST" rules={[{ required: true, message: '请输入 HOST' }]}>
-          {renderHosts()}
-          {!disabled && (
-            <Button type="primary" onClick={() => onChange({ hosts: hosts.concat('') })}>
-              增加
-            </Button>
-          )}
-        </Form.Item>
-        {/* TODO: name */}
-        <Form.Item label="PATH">
-          {renderPaths()}
-          {!disabled && (
-            <Button onClick={() => onChange({ paths: paths.concat(['']) })} type="primary">
-              增加
-            </Button>
-          )}
-        </Form.Item>
-        <Form.Item
-          label="HTTP Methods"
-          name="httpMethods"
-          rules={[{ required: true, message: '请勾选 HTTP Methods' }]}
-        >
-          <Checkbox
-            indeterminate={httpMethodList.indeterminate}
-            onChange={onCheckAllChange}
-            checked={httpMethodList.checkAll}
-            disabled={disabled}
-          >
-            ANY
-          </Checkbox>
+      <Form.Item label="协议" name="protocol" rules={[{ required: true, message: '请勾选协议' }]}>
+        <Row>
           <Checkbox.Group
-            options={HTTP_METHOD_OPTION_LIST}
-            value={httpMethodList.checkedList}
-            onChange={onMethodsChange}
             disabled={disabled}
+            options={['HTTP', 'HTTPS', 'WebSocket']}
+            defaultValue={protocols}
+            value={protocols}
+            onChange={onProtocolChange}
           />
-        </Form.Item>
-      </Form>
+        </Row>
+      </Form.Item>
+      {/* TODO: name */}
+      <Form.Item label="HOST" rules={[{ required: true, message: '请输入 HOST' }]}>
+        {renderHosts()}
+        {!disabled && (
+          <Button
+            type="primary"
+            onClick={() => onChange({ ...data.step1Data, hosts: hosts.concat('') })}
+          >
+            增加
+          </Button>
+        )}
+      </Form.Item>
+      {/* TODO: name */}
+      <Form.Item label="PATH">
+        {renderPaths()}
+        {!disabled && (
+          <Button
+            onClick={() => onChange({ ...data.step1Data, paths: paths.concat(['']) })}
+            type="primary"
+          >
+            增加
+          </Button>
+        )}
+      </Form.Item>
+      <Form.Item
+        label="HTTP Methods"
+        name="httpMethods"
+        rules={[{ required: true, message: '请勾选 HTTP Methods' }]}
+      >
+        <Checkbox
+          indeterminate={httpMethodList.indeterminate}
+          onChange={onCheckAllChange}
+          checked={httpMethodList.checkAll}
+          disabled={disabled}
+        >
+          ANY
+        </Checkbox>
+        <Checkbox.Group
+          options={HTTP_METHOD_OPTION_LIST}
+          value={httpMethodList.checkedList}
+          onChange={onMethodsChange}
+          disabled={disabled}
+        />
+      </Form.Item>
     </PanelSection>
   );
 };
diff --git a/src/pages/Routes/components/Step1/index.tsx b/src/pages/Routes/components/Step1/index.tsx
index f872681..05d0669 100644
--- a/src/pages/Routes/components/Step1/index.tsx
+++ b/src/pages/Routes/components/Step1/index.tsx
@@ -1,16 +1,35 @@
-import React from 'react';
+import React, { useEffect } from 'react';
 import { Form } from 'antd';
 
+import { FORM_ITEM_LAYOUT } from '@/pages/Routes/constants';
+import styles from '../../Create.less';
+
 import MetaView from './MetaView';
 import RequestConfigView from './RequestConfigView';
 import MatchingRulesView from './MatchingRulesView';
 
 const Step1: React.FC<RouteModule.Data> = (props) => {
+  const { onChange, data } = props;
   const [form] = Form.useForm();
+
+  useEffect(() => {
+    return () => {
+      onChange(form.getFieldsValue());
+    };
+  }, []);
+
   return (
     <>
-      <MetaView form={form} {...props} />
-      <RequestConfigView form={form} {...props} />
+      <Form
+        {...FORM_ITEM_LAYOUT}
+        form={form}
+        layout="horizontal"
+        className={styles.stepForm}
+        initialValues={data.step1Data}
+      >
+        <MetaView {...props} />
+        <RequestConfigView {...props} />
+      </Form>
       <MatchingRulesView {...props} />
     </>
   );
diff --git a/src/pages/Routes/components/Step2/HttpHeaderRewriteView.tsx b/src/pages/Routes/components/Step2/HttpHeaderRewriteView.tsx
index fde1996..10d8bd1 100644
--- a/src/pages/Routes/components/Step2/HttpHeaderRewriteView.tsx
+++ b/src/pages/Routes/components/Step2/HttpHeaderRewriteView.tsx
@@ -1,15 +1,13 @@
 import React, { useState } from 'react';
-import Form, { FormInstance } from 'antd/es/form';
+import Form from 'antd/es/form';
 import { Button, Table, Space, Modal, Input } from 'antd';
-
 import TextArea from 'antd/lib/input/TextArea';
+
 import PanelSection from '../PanelSection';
 
-interface Props extends RouteModule.Data {
-  form: FormInstance;
-}
+interface Props extends RouteModule.Data {}
 
-const HttpHeaderRewriteView: React.FC<Props> = ({ data, onChange }) => {
+const HttpHeaderRewriteView: React.FC<Props> = ({ data, disabled, onChange }) => {
   const { upstream_header } = data.step2Data;
   const [visible, setVisible] = useState(false);
   const [modalForm] = Form.useForm();
@@ -38,28 +36,30 @@ const HttpHeaderRewriteView: React.FC<Props> = ({ data, onChange }) => {
       dataIndex: 'header_desc',
       key: 'header_desc',
     },
-    {
-      title: '操作',
-      key: 'action',
-      render: (_: any, record: RouteModule.UpstreamHeader) => (
-        <Space size="middle">
-          <a
-            onClick={() => {
-              handleEdit(record);
-            }}
-          >
-            编辑
-          </a>
-          <a
-            onClick={() => {
-              handleRemove(record.key);
-            }}
-          >
-            移除
-          </a>
-        </Space>
-      ),
-    },
+    disabled
+      ? {}
+      : {
+          title: '操作',
+          key: 'action',
+          render: (_: any, record: RouteModule.UpstreamHeader) => (
+            <Space size="middle">
+              <a
+                onClick={() => {
+                  handleEdit(record);
+                }}
+              >
+                编辑
+              </a>
+              <a
+                onClick={() => {
+                  handleRemove(record.key);
+                }}
+              >
+                移除
+              </a>
+            </Space>
+          ),
+        },
   ];
 
   const renderModal = () => {
@@ -112,17 +112,19 @@ const HttpHeaderRewriteView: React.FC<Props> = ({ data, onChange }) => {
 
   return (
     <PanelSection title="HTTP 头改写">
-      <Button
-        onClick={() => {
-          setVisible(true);
-        }}
-        type="primary"
-        style={{
-          marginBottom: 16,
-        }}
-      >
-        新增
-      </Button>
+      {!disabled && (
+        <Button
+          onClick={() => {
+            setVisible(true);
+          }}
+          type="primary"
+          style={{
+            marginBottom: 16,
+          }}
+        >
+          新增
+        </Button>
+      )}
       <Table key="table" bordered dataSource={upstream_header} columns={columns} />
       {renderModal()}
     </PanelSection>
diff --git a/src/pages/Routes/components/Step2/RequestRewriteView.tsx b/src/pages/Routes/components/Step2/RequestRewriteView.tsx
index ee1912b..fa7d2e1 100644
--- a/src/pages/Routes/components/Step2/RequestRewriteView.tsx
+++ b/src/pages/Routes/components/Step2/RequestRewriteView.tsx
@@ -11,7 +11,7 @@ interface Props extends RouteModule.Data {
   form: FormInstance;
 }
 
-const RequestRewriteView: React.FC<Props> = ({ data, form, onChange }) => {
+const RequestRewriteView: React.FC<Props> = ({ data, form, disabled, onChange }) => {
   const { step2Data } = data;
   const { backendAddressList, backendProtocol } = step2Data;
   const onProtocolChange = (e: RadioChangeEvent) => {
@@ -25,19 +25,19 @@ const RequestRewriteView: React.FC<Props> = ({ data, form, onChange }) => {
   };
   const renderBackendAddress = () =>
     backendAddressList.map((item, index) => (
-      <Row key={`${item.host + index}`} style={{ marginBottom: '10px' }} gutter={[16, 16]}>
-        <Col span={12}>
-          <Input placeholder="HOST" />
+      <Row key={`${item.host + index}`} style={{ marginBottom: '10px' }} gutter={16}>
+        <Col span={9}>
+          <Input placeholder="HOST" disabled={disabled} />
         </Col>
         <Col span={4}>
-          <InputNumber placeholder="Port" />
+          <InputNumber placeholder="Port" disabled={disabled} />
         </Col>
-        <Col span={4}>
-          <InputNumber placeholder="Weight" />
+        <Col span={4} offset={1}>
+          <InputNumber placeholder="Weight" disabled={disabled} />
         </Col>
-        <Col span={4}>
+        <Col span={4} offset={1}>
           <Space>
-            {backendAddressList.length > 1 && (
+            {backendAddressList.length > 1 && !disabled && (
               <Button
                 type="primary"
                 danger
@@ -66,7 +66,12 @@ const RequestRewriteView: React.FC<Props> = ({ data, form, onChange }) => {
       >
         <Form.Item label="协议" name="protocol" rules={[{ required: true, message: '请勾选协议' }]}>
           <Row>
-            <Radio.Group onChange={onProtocolChange} name="backendProtocol" value={backendProtocol}>
+            <Radio.Group
+              onChange={onProtocolChange}
+              name="backendProtocol"
+              value={backendProtocol}
+              disabled={disabled}
+            >
               <Radio value="HTTP">HTTP</Radio>
               <Radio value="HTTPS">HTTPS</Radio>
               <Radio value="originalRequest">原始请求</Radio>
@@ -75,23 +80,25 @@ const RequestRewriteView: React.FC<Props> = ({ data, form, onChange }) => {
         </Form.Item>
         <Form.Item label="后端地址" rules={[{ required: true, message: '请输入后端地址' }]}>
           {renderBackendAddress()}
-          <Button type="primary" onClick={addBackendAddress}>
-            增加
-          </Button>
+          {!disabled && (
+            <Button type="primary" onClick={addBackendAddress}>
+              增加
+            </Button>
+          )}
         </Form.Item>
         <Form.Item label="后端请求 Path">
           <Row>
-            <Input />
+            <Input disabled={disabled} />
           </Row>
         </Form.Item>
         <Form.Item label="连接超时">
-          <InputNumber /> ms
+          <InputNumber disabled={disabled} /> ms
         </Form.Item>
         <Form.Item label="发送超时">
-          <InputNumber /> ms
+          <InputNumber disabled={disabled} /> ms
         </Form.Item>
         <Form.Item label="接收超时">
-          <InputNumber /> ms
+          <InputNumber disabled={disabled} /> ms
         </Form.Item>
       </Form>
     </PanelSection>
diff --git a/src/pages/Routes/constants.ts b/src/pages/Routes/constants.ts
index 4155eb1..5bc45a0 100644
--- a/src/pages/Routes/constants.ts
+++ b/src/pages/Routes/constants.ts
@@ -8,3 +8,34 @@ export const FORM_ITEM_LAYOUT = {
     span: 18,
   },
 };
+
+export const DEFAULT_STEP_1_DATA: RouteModule.Step1Data = {
+  name: '',
+  protocols: ['HTTP', 'HTTPS'],
+  hosts: [],
+  paths: [],
+  httpMethods: [],
+  advancedMatchingRules: [],
+};
+
+export const DEFAULT_STEP_2_DATA: RouteModule.Step2Data = {
+  backendProtocol: 'originalRequest',
+  backendAddressList: [{ host: '', port: 0, weight: 0 }],
+  upstream_header: [],
+  timeout: {
+    connect: 30000,
+    send: 30000,
+    read: 30000,
+  },
+};
+
+export const DEFAULT_STEP_3_DATA: RouteModule.Step3Data = {
+  plugins: {
+    'limit-count': {
+      count: 2,
+      time_window: 60,
+      rejected_code: 503,
+      key: 'remote_addr',
+    },
+  },
+};
diff --git a/src/pages/Routes/typing.d.ts b/src/pages/Routes/typing.d.ts
index fda64db..b7fb371 100644
--- a/src/pages/Routes/typing.d.ts
+++ b/src/pages/Routes/typing.d.ts
@@ -7,12 +7,15 @@ declare namespace RouteModule {
     key: string;
   }
 
+  type HttpMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'PATCH';
+  type RequestProtocol = 'HTTPS' | 'HTTP' | 'WebSocket';
+
   type Step1Data = {
     name: string;
-    protocol: [];
+    protocols: RequestProtocol[];
     hosts: string[];
     paths: string[];
-    httpMethods: [];
+    httpMethods: HttpMethod[];
     advancedMatchingRules: MatchingRule[];
   };
 
@@ -32,9 +35,6 @@ declare namespace RouteModule {
     onChange(data: T): void;
   }
 
-  type HttpMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'PATCH';
-  type RequestProtocol = 'HTTPS' | 'HTTP';
-
   type backendAddressItemProps = {
     host: '';
     port: number;