diff --git a/web/src/components/integration/component/DataForm.js b/web/src/components/integration/component/DataForm.js
new file mode 100644
index 000000000..bff3596b9
--- /dev/null
+++ b/web/src/components/integration/component/DataForm.js
@@ -0,0 +1,147 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Form, Select, Input, Button } from 'antd';
+
+const FormItem = Form.Item;
+const Option = Select.Option;
+const formMap = {
+ git: [
+ {
+ label: 'URL',
+ key: 'url',
+ },
+ {
+ label: 'Token',
+ key: 'Token',
+ },
+ ],
+ imagesregistry: [
+ {
+ label: intl.get('integration.dataform.registryaddress'),
+ key: 'registryAddress',
+ },
+ {
+ label: intl.get('integration.dataform.username'),
+ key: 'username',
+ },
+ {
+ label: intl.get('integration.dataform.pwd'),
+ key: 'pwd',
+ },
+ ],
+};
+
+class DataForm extends React.Component {
+ static propTypes = {
+ form: PropTypes.object,
+ onSubmit: PropTypes.func,
+ onCancel: PropTypes.func,
+ };
+ state = {
+ inputList: [],
+ };
+
+ componentDidMount() {
+ this.resetForm();
+ }
+
+ componentWillUnmount() {
+ this.resetForm();
+ }
+
+ resetForm = () => {
+ const { resetFields } = this.props.form;
+ this.setState({ inputList: [] });
+ resetFields();
+ };
+
+ handleSubmit = e => {
+ const { onSubmit } = this.props;
+ e.preventDefault();
+ this.props.form.validateFields((err, values) => {
+ if (!err) {
+ // TODO post request
+ this.resetForm();
+ onSubmit();
+ }
+ });
+ };
+
+ handleCancle = () => {
+ const { onCancel } = this.props;
+ this.resetForm();
+ onCancel();
+ };
+
+ handleSelectChange = value => {
+ this.setState({
+ inputList: formMap[value],
+ });
+ };
+
+ renderFormInputs = () => {
+ const { inputList } = this.state;
+ const { getFieldDecorator } = this.props.form;
+ return (
+ inputList.length > 0 &&
+ inputList.map((v, i) => (
+
+ {getFieldDecorator(v.key)()}
+
+ ))
+ );
+ };
+
+ render() {
+ const { getFieldDecorator } = this.props.form;
+ const { inputList } = this.state;
+ return (
+
+
+
+
+
+ );
+ }
+}
+
+export default Form.create()(DataForm);
diff --git a/web/src/components/integration/component/List.js b/web/src/components/integration/component/List.js
new file mode 100644
index 000000000..221b62b6c
--- /dev/null
+++ b/web/src/components/integration/component/List.js
@@ -0,0 +1,78 @@
+import React from 'react';
+import { Table, Button, Modal } from 'antd';
+import { inject, observer } from 'mobx-react';
+import IntegrationForm from './DataForm';
+import PropTypes from 'prop-types';
+
+@inject('integration')
+@observer
+class List extends React.Component {
+ static propTypes = {
+ integration: PropTypes.object,
+ };
+ state = { visible: false };
+ componentDidMount() {
+ this.props.integration.getIntegrationList();
+ }
+ addDataSource = () => {
+ this.setState({
+ visible: true,
+ });
+ };
+ handleOk = e => {
+ this.setState({
+ visible: false,
+ });
+ };
+
+ handleCancel = e => {
+ this.setState({
+ visible: false,
+ });
+ };
+ render() {
+ const { integration } = this.props;
+ const columns = [
+ {
+ title: intl.get('name'),
+ dataIndex: 'name',
+ key: 'name',
+ },
+ {
+ title: intl.get('integration.type'),
+ dataIndex: 'type',
+ key: 'type',
+ },
+ {
+ title: intl.get('integration.creationTime'),
+ dataIndex: 'time',
+ key: 'time',
+ },
+ ];
+ return (
+
+
+
{intl.get('integration.datasource')}
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default List;
diff --git a/web/src/components/integration/index.js b/web/src/components/integration/index.js
new file mode 100644
index 000000000..ccbe35a92
--- /dev/null
+++ b/web/src/components/integration/index.js
@@ -0,0 +1,2 @@
+import Integration from './component/List';
+export default Integration;
diff --git a/web/src/layout/index.js b/web/src/layout/index.js
index f7095d437..4a848ce95 100644
--- a/web/src/layout/index.js
+++ b/web/src/layout/index.js
@@ -80,6 +80,12 @@ class CoreLayout extends Component {
{intl.get('sideNav.workflow')}
+
+
+
+ {intl.get('sideNav.integration')}
+
+
{/* TODO: manage and setting */}
{/* (
+
);
diff --git a/web/src/store/index.js b/web/src/store/index.js
index f91b4aca4..d47054dc6 100644
--- a/web/src/store/index.js
+++ b/web/src/store/index.js
@@ -1,6 +1,8 @@
import workflow from './workflow';
+import integration from './integration';
const stores = {
workflow,
+ integration,
};
export default stores;
diff --git a/web/src/store/integration.js b/web/src/store/integration.js
new file mode 100644
index 000000000..dfc9cfa0f
--- /dev/null
+++ b/web/src/store/integration.js
@@ -0,0 +1,20 @@
+import { observable, useStrict, action } from 'mobx';
+
+useStrict(true);
+
+class Integration {
+ @observable integrationList = [];
+ @action.bound
+ getIntegrationList(workflowId) {
+ this.integrationList = [
+ {
+ name: 'svn-2',
+ type: 'svn-1',
+ time: '2018-12-21',
+ },
+ ];
+ return;
+ }
+}
+
+export default new Integration();