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/09/10 16:19:47 UTC
[apisix-dashboard] branch master updated: Feat: dashboard support
route group (#433)
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 e2271b3 Feat: dashboard support route group (#433)
e2271b3 is described below
commit e2271b386764cff0b903cae7ee3b16afcd8d1883
Author: liuxiran <be...@126.com>
AuthorDate: Fri Sep 11 00:19:38 2020 +0800
Feat: dashboard support route group (#433)
* feat: route group UI
* feat(route-ui): add routegroup when create route
* fix: add routegroup to route list
* fix: support add routegroup together with route
* fix: route path define error
* feat: trigger redeploy
* fix: update i18n key
Co-authored-by: 琚致远 <ju...@apache.org>
---
config/routes.ts | 12 +++
src/helpers.tsx | 5 ++
src/locales/en-US/menu.ts | 1 +
src/locales/zh-CN/menu.ts | 1 +
src/pages/Route/Create.tsx | 11 ++-
src/pages/Route/List.tsx | 4 +
src/pages/Route/components/Step1/MetaView.tsx | 53 ++++++++++++-
src/pages/Route/constants.ts | 2 +
src/pages/Route/locales/en-US.ts | 8 +-
src/pages/Route/locales/zh-CN.ts | 8 +-
src/pages/Route/service.ts | 11 +++
src/pages/Route/transform.ts | 15 +++-
src/pages/Route/typing.d.ts | 4 +
src/pages/RouteGroup/Create.tsx | 88 ++++++++++++++++++++++
src/pages/{Route => RouteGroup}/List.tsx | 69 ++++++-----------
src/pages/RouteGroup/components/Preview.tsx | 28 +++++++
.../components/Step1.tsx} | 43 ++++++-----
src/pages/RouteGroup/constants.ts | 31 ++++++++
src/pages/RouteGroup/index.ts | 18 +++++
src/pages/RouteGroup/locales/en-US.ts | 45 +++++++++++
src/pages/RouteGroup/locales/zh-CN.ts | 45 +++++++++++
src/pages/RouteGroup/service.ts | 46 +++++++++++
src/pages/RouteGroup/typing.d.ts | 23 ++++++
23 files changed, 498 insertions(+), 73 deletions(-)
diff --git a/config/routes.ts b/config/routes.ts
index 6648413..7512519 100644
--- a/config/routes.ts
+++ b/config/routes.ts
@@ -36,6 +36,18 @@ const routes = [
component: './Route/Create',
},
{
+ path: '/routegroup/list',
+ component: './RouteGroup/List',
+ },
+ {
+ path: '/routegroup/create',
+ component: './RouteGroup/Create',
+ },
+ {
+ path: '/routegroup/:gid/edit',
+ component: './RouteGroup/Create',
+ },
+ {
path: '/ssl/:id/edit',
component: './SSL/Create',
},
diff --git a/src/helpers.tsx b/src/helpers.tsx
index 39e97da..4b9151d 100644
--- a/src/helpers.tsx
+++ b/src/helpers.tsx
@@ -35,6 +35,11 @@ export const getMenuData = (): MenuDataItem[] => {
icon: <IconFont type="iconroute" />,
},
{
+ name: 'routegroup',
+ path: '/routegroup/list',
+ icon: <IconFont type="iconroute" />,
+ },
+ {
name: 'ssl',
path: '/ssl/list',
icon: <IconFont type="iconSSLshuzizhengshu" />,
diff --git a/src/locales/en-US/menu.ts b/src/locales/en-US/menu.ts
index 0528b97..8afd19b 100644
--- a/src/locales/en-US/menu.ts
+++ b/src/locales/en-US/menu.ts
@@ -66,6 +66,7 @@ export default {
'menu.editor.koni': 'Koni Editor',
'menu.metrics': 'Metrics',
'menu.routes': 'Route',
+ 'menu.routegroup': 'RouteGroup',
'menu.ssl': 'SSL',
'menu.upstream': 'Upstream',
'menu.consumer': 'Consumer',
diff --git a/src/locales/zh-CN/menu.ts b/src/locales/zh-CN/menu.ts
index df0fbca..7597a94 100644
--- a/src/locales/zh-CN/menu.ts
+++ b/src/locales/zh-CN/menu.ts
@@ -66,6 +66,7 @@ export default {
'menu.editor.koni': '拓扑编辑器',
'menu.metrics': '监控',
'menu.routes': '路由',
+ 'menu.routegroup': '路由分组',
'menu.ssl': '证书',
'menu.upstream': '上游',
'menu.consumer': '用户',
diff --git a/src/pages/Route/Create.tsx b/src/pages/Route/Create.tsx
index 274f5ba..dcc21b1 100644
--- a/src/pages/Route/Create.tsx
+++ b/src/pages/Route/Create.tsx
@@ -29,6 +29,7 @@ import {
checkUniqueName,
fetchUpstreamItem,
checkHostWithSSL,
+ fetchRouteGroupItem,
} from './service';
import Step1 from './components/Step1';
import Step2 from './components/Step2';
@@ -132,7 +133,15 @@ const Page: React.FC<Props> = (props) => {
data={routeData}
form={form1}
onChange={(params: RouteModule.Step1Data) => {
- setStep1Data({ ...step1Data, ...params });
+ if (params.route_group_id) {
+ fetchRouteGroupItem(params.route_group_id).then((data) => {
+ form1.setFieldsValue({
+ ...form1.getFieldsValue(),
+ ...data,
+ });
+ });
+ }
+ setStep1Data({ ...form1.getFieldsValue(), ...step1Data, ...params });
}}
/>
);
diff --git a/src/pages/Route/List.tsx b/src/pages/Route/List.tsx
index df2a899..e37d043 100644
--- a/src/pages/Route/List.tsx
+++ b/src/pages/Route/List.tsx
@@ -63,6 +63,10 @@ const Page: React.FC = () => {
dataIndex: 'description',
},
{
+ title: formatMessage({ id: 'route.list.group.name' }),
+ dataIndex: 'route_group_name',
+ },
+ {
title: formatMessage({ id: 'route.list.edit.time' }),
dataIndex: 'update_time',
render: (text) => `${moment.unix(Number(text)).format('YYYY-MM-DD HH:mm:ss')}`,
diff --git a/src/pages/Route/components/Step1/MetaView.tsx b/src/pages/Route/components/Step1/MetaView.tsx
index b04a5ac..afa1b90 100644
--- a/src/pages/Route/components/Step1/MetaView.tsx
+++ b/src/pages/Route/components/Step1/MetaView.tsx
@@ -14,16 +14,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
+import React, { useEffect, useState } from 'react';
import Form from 'antd/es/form';
-import { Input } from 'antd';
+import { Input, Select } from 'antd';
import { useIntl } from 'umi';
import { PanelSection } from '@api7-dashboard/ui';
+import { fetchRouteGroupList } from '@/pages/Route/service';
+
interface Props extends RouteModule.Data {}
-const MetaView: React.FC<Props> = ({ disabled }) => {
+const MetaView: React.FC<Props> = ({ data, disabled, onChange }) => {
+ const { step1Data } = data;
const { formatMessage } = useIntl();
+ const routeGroupDisabled = disabled || !!step1Data.route_group_id;
+ const [routeGroups, setRouteGroups] = useState<{ id: string; name: string }[]>();
+ useEffect(() => {
+ // eslint-disable-next-line no-shadow
+ fetchRouteGroupList().then(({ data }) => {
+ setRouteGroups([
+ { name: formatMessage({ id: 'route.meta.api.create.group.name' }), id: null },
+ ...data,
+ ]);
+ if (step1Data.route_group_id) {
+ onChange({ route_group_id: step1Data.route_group_id });
+ }
+ });
+ }, []);
return (
<PanelSection title={formatMessage({ id: 'route.meta.name.description' })}>
<Form.Item
@@ -43,6 +60,36 @@ const MetaView: React.FC<Props> = ({ disabled }) => {
disabled={disabled}
/>
</Form.Item>
+ <Form.Item label={formatMessage({ id: 'route.meta.api.group.name' })} name="route_group_id">
+ <Select
+ onChange={(value) => {
+ if (step1Data.route_group_id) {
+ onChange({ route_group_id: value });
+ }
+ }}
+ disabled={disabled}
+ >
+ {(routeGroups || []).map((item) => {
+ return (
+ <Select.Option value={item.id} key={item.id}>
+ {item.name}
+ </Select.Option>
+ );
+ })}
+ </Select>
+ </Form.Item>
+ <Form.Item
+ label={formatMessage({ id: 'route.meta.group.name' })}
+ name="route_group_name"
+ rules={[
+ { required: true, message: formatMessage({ id: 'route.meta.input.api.group.name' }) },
+ ]}
+ >
+ <Input
+ placeholder={formatMessage({ id: 'route.meta.input.api.group.name' })}
+ disabled={routeGroupDisabled}
+ />
+ </Form.Item>
<Form.Item label={formatMessage({ id: 'route.meta.description' })} name="desc">
<Input.TextArea
placeholder={formatMessage({ id: 'route.meta.description.rule' })}
diff --git a/src/pages/Route/constants.ts b/src/pages/Route/constants.ts
index 0620bbd..cc0e05b 100644
--- a/src/pages/Route/constants.ts
+++ b/src/pages/Route/constants.ts
@@ -41,6 +41,8 @@ export const FORM_ITEM_WITHOUT_LABEL = {
};
export const DEFAULT_STEP_1_DATA: RouteModule.Step1Data = {
+ route_group_id: '',
+ route_group_name: '',
name: '',
desc: '',
priority: 0,
diff --git a/src/pages/Route/locales/en-US.ts b/src/pages/Route/locales/en-US.ts
index 78baa5f..b102e2f 100644
--- a/src/pages/Route/locales/en-US.ts
+++ b/src/pages/Route/locales/en-US.ts
@@ -61,8 +61,13 @@ export default {
'Maximum length 100, only letters, Numbers, _, and - are supported, and can only begin with letters',
'rotue.meta.api.rule':
'Only letters, numbers, _ and - are supported, and can only begin with letters',
- 'route.meta.description': 'Description',
+ 'route.meta.api.group.name': 'RouteGroup',
+ 'route.meta.group.name': 'GroupName',
+ 'route.meta.input.api.group.name': 'Please enter the group name',
+ 'route.meta.api.create.group.name': 'Create route group',
+ 'route.meta.description': 'APIDescription',
'route.meta.description.rule': 'Can not more than 200 characters',
+ 'route.meta.group.description': 'GroupDescription',
'route.request.config.domain.name': 'Domain Name',
'route.request.config.domain.or.ip':
@@ -146,6 +151,7 @@ export default {
'route.list.domain.name': 'Domain Name',
'route.list.path': 'Path',
'route.list.description': 'Description',
+ 'route.list.group.name': 'RouteGroup',
'route.list.edit.time': 'Edit Time',
'route.list.operation': 'Operation',
'route.list.edit': 'Edit',
diff --git a/src/pages/Route/locales/zh-CN.ts b/src/pages/Route/locales/zh-CN.ts
index 5894354..a3385fd 100644
--- a/src/pages/Route/locales/zh-CN.ts
+++ b/src/pages/Route/locales/zh-CN.ts
@@ -58,8 +58,13 @@ export default {
'route.meta.input.api.name': '请输入 API 名称',
'route.meta.api.name.rule': '最大长度100,仅支持字母、数字、- 和 _,且只能以字母开头',
'rotue.meta.api.rule': '仅支持字母、数字、- 和 _,且只能以字母开头',
- 'route.meta.description': '描述',
+ 'route.meta.api.group.name': '路由分组',
+ 'route.meta.group.name': '分组名称',
+ 'route.meta.input.api.group.name': '请输入路由分组名称',
+ 'route.meta.api.create.group.name': '创建路由分组',
+ 'route.meta.description': '路由描述',
'route.meta.description.rule': '不超过 200 个字符',
+ 'route.meta.group.description': '分组描述',
'route.request.config.domain.name': '域名',
'route.request.config.domain.or.ip': '域名或IP,支持泛域名,如:*.test.com',
@@ -141,6 +146,7 @@ export default {
'route.list.domain.name': '域名',
'route.list.path': '路径',
'route.list.description': '描述',
+ 'route.list.group.name': '路由分组',
'route.list.edit.time': '编辑时间',
'route.list.operation': '操作',
'route.list.edit': '编辑',
diff --git a/src/pages/Route/service.ts b/src/pages/Route/service.ts
index e9434f5..171d4f5 100644
--- a/src/pages/Route/service.ts
+++ b/src/pages/Route/service.ts
@@ -62,6 +62,17 @@ export const checkUniqueName = (name = '', exclude = '') =>
),
});
+export const fetchRouteGroupList = () => request(`/names/routegroups`);
+
+export const fetchRouteGroupItem = (gid: string) => {
+ return request(`/routegroups/${gid}`).then((data) => {
+ return {
+ route_group_name: data.name,
+ route_group_id: data.id,
+ };
+ });
+};
+
export const fetchUpstreamList = () => request(`/names/upstreams`);
export const fetchUpstreamItem = (sid: string) => {
diff --git a/src/pages/Route/transform.ts b/src/pages/Route/transform.ts
index dae7d91..e3c2b4e 100644
--- a/src/pages/Route/transform.ts
+++ b/src/pages/Route/transform.ts
@@ -155,10 +155,23 @@ export const transformUpstreamNodes = (
};
export const transformRouteData = (data: RouteModule.Body) => {
- const { name, desc, methods, uris, protocols, hosts, vars, redirect } = data;
+ const {
+ name,
+ route_group_id,
+ route_group_name,
+ desc,
+ methods,
+ uris,
+ protocols,
+ hosts,
+ vars,
+ redirect,
+ } = data;
const step1Data: Partial<RouteModule.Step1Data> = {
name,
+ route_group_id,
+ route_group_name,
desc,
protocols: protocols.filter((item) => item !== 'websocket'),
websocket: protocols.includes('websocket'),
diff --git a/src/pages/Route/typing.d.ts b/src/pages/Route/typing.d.ts
index 9fc25dc..409f4cc 100644
--- a/src/pages/Route/typing.d.ts
+++ b/src/pages/Route/typing.d.ts
@@ -51,6 +51,8 @@ declare namespace RouteModule {
redirectURI?: string;
redirectCode?: number;
advancedMatchingRules: MatchingRule[];
+ route_group_id?: string;
+ route_group_name: string;
};
type Step3Data = {
@@ -113,6 +115,8 @@ declare namespace RouteModule {
// Request Body or Response Data for API
type Body = {
id?: number;
+ route_group_id?: string;
+ route_group_name: string;
name: string;
desc: string;
priority?: number;
diff --git a/src/pages/RouteGroup/Create.tsx b/src/pages/RouteGroup/Create.tsx
new file mode 100644
index 0000000..80213a2
--- /dev/null
+++ b/src/pages/RouteGroup/Create.tsx
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React, { useEffect, useState } from 'react';
+import { PageContainer } from '@ant-design/pro-layout';
+import { Card, Form, notification, Steps } from 'antd';
+
+import ActionBar from '@/components/ActionBar';
+import { history, useIntl } from 'umi';
+
+import Step1 from './components/Step1';
+import Preview from './components/Preview';
+import { create, fetchOne, update } from './service';
+
+const Page: React.FC = (props) => {
+ const [step, setStep] = useState(1);
+ const [form1] = Form.useForm();
+ const { formatMessage } = useIntl();
+
+ useEffect(() => {
+ const { gid } = (props as any).match.params;
+
+ if (gid) {
+ fetchOne(gid).then((data) => {
+ form1.setFieldsValue(data);
+ });
+ }
+ }, []);
+
+ const onSubmit = () => {
+ const data = { ...form1.getFieldsValue() } as RouteGroupModule.RouteGroupEntity;
+ const { gid } = (props as any).match.params;
+ (gid ? update(gid, data) : create(data)).then(() => {
+ notification.success({
+ message: `${
+ gid
+ ? formatMessage({ id: 'routegroup.create.edit' })
+ : formatMessage({ id: 'routegroup.create.create' })
+ } ${formatMessage({ id: 'routegroup.create.routegroup.successfully' })}`,
+ });
+ history.replace('/routegroup/list');
+ });
+ };
+
+ const onStepChange = (nextStep: number) => {
+ if (step === 1) {
+ form1.validateFields().then(() => {
+ setStep(nextStep);
+ });
+ } else if (nextStep === 3) {
+ onSubmit();
+ } else {
+ setStep(nextStep);
+ }
+ };
+
+ return (
+ <>
+ <PageContainer title={formatMessage({ id: 'routegroup.create.create' })}>
+ <Card bordered={false}>
+ <Steps current={step - 1} style={{ marginBottom: 30 }}>
+ <Steps.Step title={formatMessage({ id: 'routegroup.create.basic.info' })} />
+ <Steps.Step title={formatMessage({ id: 'routegroup.create.preview' })} />
+ </Steps>
+
+ {step === 1 && <Step1 form={form1} />}
+ {step === 2 && <Preview form1={form1} />}
+ </Card>
+ </PageContainer>
+ <ActionBar step={step} lastStep={2} onChange={onStepChange} />
+ </>
+ );
+};
+
+export default Page;
diff --git a/src/pages/Route/List.tsx b/src/pages/RouteGroup/List.tsx
similarity index 59%
copy from src/pages/Route/List.tsx
copy to src/pages/RouteGroup/List.tsx
index df2a899..b2da173 100644
--- a/src/pages/Route/List.tsx
+++ b/src/pages/RouteGroup/List.tsx
@@ -15,86 +15,63 @@
* limitations under the License.
*/
import React, { useRef, useState } from 'react';
-import { PageHeaderWrapper } from '@ant-design/pro-layout';
+import { PageContainer } from '@ant-design/pro-layout';
import ProTable, { ProColumns, ActionType } from '@ant-design/pro-table';
-import { Button, Popconfirm, notification, Tag, Input } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
-import moment from 'moment';
+import { Popconfirm, Button, notification, Input } from 'antd';
import { history, useIntl } from 'umi';
+import moment from 'moment';
import { fetchList, remove } from './service';
const Page: React.FC = () => {
const ref = useRef<ActionType>();
+
const [search, setSearch] = useState('');
const { formatMessage } = useIntl();
- const columns: ProColumns<RouteModule.BaseData>[] = [
+ const columns: ProColumns<RouteGroupModule.RouteGroupEntity>[] = [
{
- title: formatMessage({ id: 'route.list.name' }),
+ title: formatMessage({ id: 'routegroup.list.name' }),
dataIndex: 'name',
},
{
- title: formatMessage({ id: 'route.list.domain.name' }),
- dataIndex: 'hosts',
- render: (_, record) =>
- record.hosts.map((host) => (
- <Tag key={host} color="geekblue">
- {host}
- </Tag>
- )),
- },
- {
- title: formatMessage({ id: 'route.list.path' }),
- dataIndex: 'uri',
- render: (_, record) =>
- record.uris.map((uri) => (
- <Tag key={uri} color="geekblue">
- {uri}
- </Tag>
- )),
- },
- // {
- // title: '优先级',
- // dataIndex: 'priority',
- // },
- {
- title: formatMessage({ id: 'route.list.description' }),
+ title: formatMessage({ id: 'routegroup.list.description' }),
dataIndex: 'description',
},
{
- title: formatMessage({ id: 'route.list.edit.time' }),
+ title: formatMessage({ id: 'routegroup.list.edit.time' }),
dataIndex: 'update_time',
render: (text) => `${moment.unix(Number(text)).format('YYYY-MM-DD HH:mm:ss')}`,
},
{
- title: formatMessage({ id: 'route.list.operation' }),
+ title: formatMessage({ id: 'routegroup.list.operation' }),
valueType: 'option',
render: (_, record) => (
<>
<Button
type="primary"
- onClick={() => history.push(`/routes/${record.id}/edit`)}
style={{ marginRight: 10 }}
+ onClick={() => history.push(`/routegroup/${record.id}/edit`)}
>
- {formatMessage({ id: 'route.list.edit' })}
+ {formatMessage({ id: 'routegroup.list.edit' })}
</Button>
<Popconfirm
- title={formatMessage({ id: 'route.list.delete.confrim' })}
+ title={formatMessage({ id: 'routegroup.list.confirm.delete' })}
+ okText={formatMessage({ id: 'routegroup.list.confirm' })}
+ cancelText={formatMessage({ id: 'routegroup.list.cancel' })}
onConfirm={() => {
remove(record.id!).then(() => {
notification.success({
- message: formatMessage({ id: 'route.list.delete.success' }),
+ message: formatMessage({ id: 'routegroup.list.delete.successfully' }),
});
/* eslint-disable no-unused-expressions */
ref.current?.reload();
});
}}
- okText={formatMessage({ id: 'route.list.confirm' })}
- cancelText={formatMessage({ id: 'route.list.cancel' })}
>
<Button type="primary" danger>
- {formatMessage({ id: 'route.list.delete' })}
+ {formatMessage({ id: 'routegroup.list.delete' })}
</Button>
</Popconfirm>
</>
@@ -103,29 +80,29 @@ const Page: React.FC = () => {
];
return (
- <PageHeaderWrapper title={formatMessage({ id: 'route.list' })}>
- <ProTable<RouteModule.BaseData>
+ <PageContainer title={formatMessage({ id: 'routegroup.list' })}>
+ <ProTable<RouteGroupModule.RouteGroupEntity>
actionRef={ref}
- rowKey="name"
columns={columns}
+ rowKey="id"
search={false}
request={(params) => fetchList(params, search)}
toolBarRender={(action) => [
<Input.Search
- placeholder={formatMessage({ id: 'route.list.input' })}
+ placeholder={formatMessage({ id: 'routegroup.list.input' })}
onSearch={(value) => {
setSearch(value);
action.setPageInfo({ page: 1 });
action.reload();
}}
/>,
- <Button type="primary" onClick={() => history.push('/routes/create')}>
+ <Button type="primary" onClick={() => history.push('/routegroup/create')}>
<PlusOutlined />
- {formatMessage({ id: 'route.list.create' })}
+ {formatMessage({ id: 'routegroup.list.create' })}
</Button>,
]}
/>
- </PageHeaderWrapper>
+ </PageContainer>
);
};
diff --git a/src/pages/RouteGroup/components/Preview.tsx b/src/pages/RouteGroup/components/Preview.tsx
new file mode 100644
index 0000000..92d436f
--- /dev/null
+++ b/src/pages/RouteGroup/components/Preview.tsx
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react';
+import { FormInstance } from 'antd/lib/form';
+
+import Step1 from './Step1';
+
+type Props = {
+ form1: FormInstance;
+};
+
+const Page: React.FC<Props> = ({ form1 }) => <Step1 form={form1} disabled />;
+
+export default Page;
diff --git a/src/pages/Route/components/Step1/MetaView.tsx b/src/pages/RouteGroup/components/Step1.tsx
similarity index 53%
copy from src/pages/Route/components/Step1/MetaView.tsx
copy to src/pages/RouteGroup/components/Step1.tsx
index b04a5ac..59f5dc4 100644
--- a/src/pages/Route/components/Step1/MetaView.tsx
+++ b/src/pages/RouteGroup/components/Step1.tsx
@@ -15,42 +15,45 @@
* limitations under the License.
*/
import React from 'react';
-import Form from 'antd/es/form';
-import { Input } from 'antd';
+import { Form, Input } from 'antd';
+import { FormInstance } from 'antd/lib/form';
import { useIntl } from 'umi';
-import { PanelSection } from '@api7-dashboard/ui';
-interface Props extends RouteModule.Data {}
+import { FORM_ITEM_LAYOUT } from '@/pages/Upstream/constants';
-const MetaView: React.FC<Props> = ({ disabled }) => {
+type Props = {
+ form: FormInstance;
+ disabled?: boolean;
+};
+
+const initialValues = {
+ name: '',
+ description: '',
+};
+
+const Step1: React.FC<Props> = ({ form, disabled }) => {
const { formatMessage } = useIntl();
return (
- <PanelSection title={formatMessage({ id: 'route.meta.name.description' })}>
+ <Form {...FORM_ITEM_LAYOUT} form={form} initialValues={initialValues}>
<Form.Item
- label={formatMessage({ id: 'route.meta.api.name' })}
+ label={formatMessage({ id: 'routegroup.step.name' })}
name="name"
- rules={[
- { required: true, message: formatMessage({ id: 'route.meta.input.api.name' }) },
- {
- pattern: new RegExp(/^[a-zA-Z][a-zA-Z0-9_-]{0,100}$/, 'g'),
- message: formatMessage({ id: 'route.meta.api.name.rule' }),
- },
- ]}
- extra={formatMessage({ id: 'rotue.meta.api.rule' })}
+ rules={[{ required: true }]}
+ extra={formatMessage({ id: 'routegroup.step.name.should.unique' })}
>
<Input
- placeholder={formatMessage({ id: 'route.meta.input.api.name' })}
+ placeholder={formatMessage({ id: 'routegroup.step.input.routegroup.name' })}
disabled={disabled}
/>
</Form.Item>
- <Form.Item label={formatMessage({ id: 'route.meta.description' })} name="desc">
+ <Form.Item label={formatMessage({ id: 'routegroup.step.description' })} name="description">
<Input.TextArea
- placeholder={formatMessage({ id: 'route.meta.description.rule' })}
+ placeholder={formatMessage({ id: 'routegroup.step.input.description' })}
disabled={disabled}
/>
</Form.Item>
- </PanelSection>
+ </Form>
);
};
-export default MetaView;
+export default Step1;
diff --git a/src/pages/RouteGroup/constants.ts b/src/pages/RouteGroup/constants.ts
new file mode 100644
index 0000000..25bb12f
--- /dev/null
+++ b/src/pages/RouteGroup/constants.ts
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export const FORM_ITEM_LAYOUT = {
+ labelCol: {
+ span: 6,
+ },
+ wrapperCol: {
+ span: 18,
+ },
+};
+
+export const FORM_ITEM_WITHOUT_LABEL = {
+ wrapperCol: {
+ xs: { span: 24, offset: 0 },
+ sm: { span: 20, offset: 6 },
+ },
+};
diff --git a/src/pages/RouteGroup/index.ts b/src/pages/RouteGroup/index.ts
new file mode 100644
index 0000000..7120a79
--- /dev/null
+++ b/src/pages/RouteGroup/index.ts
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export { default as RouteGroupCN } from './locales/zh-CN';
+export { default as RouteGroupUS } from './locales/en-US';
diff --git a/src/pages/RouteGroup/locales/en-US.ts b/src/pages/RouteGroup/locales/en-US.ts
new file mode 100644
index 0000000..318809d
--- /dev/null
+++ b/src/pages/RouteGroup/locales/en-US.ts
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export default {
+ 'routegroup.step.create': 'Create',
+ 'routegroup.step.name': 'Name',
+ 'routegroup.step.name.should.unique': 'Name should be unique',
+ 'routegroup.step.input.routegroup.name': 'Please input routegroup name',
+ 'routegroup.step.description': 'Description',
+ 'routegroup.step.input.description': 'Please input description',
+
+ 'routegroup.create.edit': 'Edit',
+ 'routegroup.create.create': 'Create',
+ 'routegroup.create.routegroup.successfully': 'routegroup successfully',
+ 'routegroup.create.basic.info': 'Basic Information',
+ 'routegroup.create.preview': 'Preview',
+
+ 'routegroup.list.name': 'Name',
+ 'routegroup.list.type': 'Type',
+ 'routegroup.list.description': 'Description',
+ 'routegroup.list.edit.time': 'Edit Time',
+ 'routegroup.list.operation': 'Operation',
+ 'routegroup.list.edit': 'Edit',
+ 'routegroup.list.confirm.delete': 'Are you sure to delete ?',
+ 'routegroup.list.confirm': 'Confirm',
+ 'routegroup.list.cancel': 'Cancel',
+ 'routegroup.list.delete.successfully': 'Delete successfully',
+ 'routegroup.list.delete': 'Delete',
+ 'routegroup.list': 'routegroup List',
+ 'routegroup.list.input': 'Please input',
+ 'routegroup.list.create': 'Create',
+};
diff --git a/src/pages/RouteGroup/locales/zh-CN.ts b/src/pages/RouteGroup/locales/zh-CN.ts
new file mode 100644
index 0000000..9797ae4
--- /dev/null
+++ b/src/pages/RouteGroup/locales/zh-CN.ts
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export default {
+ 'routegroup.step.create': '创建',
+ 'routegroup.step.name': '名称',
+ 'routegroup.step.name.should.unique': '名称需全局唯一',
+ 'routegroup.step.input.routegroup.name': '请输入分组名称',
+ 'routegroup.step.description': '描述',
+ 'routegroup.step.input.description': '请输入描述',
+
+ 'routegroup.create.edit': '编辑',
+ 'routegroup.create.create': '创建',
+ 'routegroup.create.routegroup.successfully': '分组成功',
+ 'routegroup.create.basic.info': '基础信息',
+ 'routegroup.create.preview': '预览',
+
+ 'routegroup.list.name': '名称',
+ 'routegroup.list.type': '类型',
+ 'routegroup.list.description': '描述',
+ 'routegroup.list.edit.time': '编辑时间',
+ 'routegroup.list.operation': '操作',
+ 'routegroup.list.edit': '编辑',
+ 'routegroup.list.confirm.delete': '确定删除该条记录吗?',
+ 'routegroup.list.confirm': '确定',
+ 'routegroup.list.cancel': '取消',
+ 'routegroup.list.delete.successfully': '删除记录成功',
+ 'routegroup.list.delete': '删除',
+ 'routegroup.list': '分组列表',
+ 'routegroup.list.input': '请输入',
+ 'routegroup.list.create': '创建',
+};
diff --git a/src/pages/RouteGroup/service.ts b/src/pages/RouteGroup/service.ts
new file mode 100644
index 0000000..8504e4b
--- /dev/null
+++ b/src/pages/RouteGroup/service.ts
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { request } from 'umi';
+
+export const fetchList = ({ current = 1, pageSize = 10 }, search: string) =>
+ request('/routegroups', {
+ params: {
+ page: current,
+ size: pageSize,
+ search,
+ },
+ }).then(({ data, count }) => ({
+ data,
+ total: count,
+ }));
+
+export const fetchOne = (id: string) =>
+ request<RouteGroupModule.RouteGroupEntity>(`/routegroups/${id}`);
+
+export const create = (data: RouteGroupModule.RouteGroupEntity) =>
+ request('/routegroups', {
+ method: 'POST',
+ data,
+ });
+
+export const update = (id: string, data: RouteGroupModule.RouteGroupEntity) =>
+ request(`/routegroups/${id}`, {
+ method: 'PUT',
+ data,
+ });
+
+export const remove = (id: string) => request(`/routegroups/${id}`, { method: 'DELETE' });
diff --git a/src/pages/RouteGroup/typing.d.ts b/src/pages/RouteGroup/typing.d.ts
new file mode 100644
index 0000000..313272a
--- /dev/null
+++ b/src/pages/RouteGroup/typing.d.ts
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+declare namespace RouteGroupModule {
+ type RouteGroupEntity = {
+ id: string;
+ name: string;
+ description: string;
+ };
+}