diff --git a/web/config/router.config.js b/web/config/router.config.js
index ffd299d1..ea8bc503 100644
--- a/web/config/router.config.js
+++ b/web/config/router.config.js
@@ -23,8 +23,8 @@ export default [
path: '/platform',
name: 'platform',
icon: 'dashboard',
- component: './Dashboard/Analysis',
routes: [
+ // { path: '/', redirect: '/platform/gateway' },
{
path: '/platform/gateway',
name: 'gateway',
@@ -72,41 +72,54 @@ export default [
},{
path: '/data/indices',
name: 'index',
- // component: './DataManagement/Indices',
- // routes: [
- // {
- // path: '/data/indices',
- // redirect: '/data/indices/summary',
- // },
- // {
- // path: '/data/indices/summary',
- // component: './DataManagement/IndexSummary',
- // },
- // {
- // path: '/data/indices/doc',
- // component: './DataManagement/Document',
- // },
- // {
- // path: '/data/indices/template',
- // component: './DataManagement/IndexTemplate',
- // },
- // {
- // path: '/data/indices/ilm',
- // component: './DataManagement/IndexLifeCycle',
- // },
- // ]
+ component: './DataManagement/Indices',
+ routes: [
+ {
+ path: '/data/indices',
+ redirect: '/data/indices/summary',
+ },
+ {
+ path: '/data/indices/summary',
+ component: './DataManagement/IndexSummary',
+ },
+ {
+ path: '/data/indices/doc',
+ component: './DataManagement/Document',
+ },
+ {
+ path: '/data/indices/template',
+ component: './DataManagement/IndexTemplate',
+ },
+ {
+ path: '/data/indices/ilm',
+ component: './DataManagement/IndexLifeCycle',
+ },
+ ]
}, {
- path: '/list/table-list',
+ path: '/data/backup',
name: 'snapshot',
- component: './List/TableList',
+ component: './DataManagement/Backup',
+ routes: [
+ {
+ path: '/data/backup',
+ redirect: '/data/backup/bakandrestore',
+ },
+ {
+ path: '/data/backup/bakandrestore',
+ component: './DataManagement/backup/BakAndRestore',
+ },{
+ path: '/data/backup/bakcycle',
+ component: './DataManagement/backup/BakCycle',
+ }
+ ]
}, {
- path: '/list/table-list',
+ path: '/data/rebuild',
name: 'rebuild',
- component: './List/TableList',
+ component: './DataManagement/Rebuild',
}, {
- path: '/list/table-list',
+ path: '/data/import',
name: 'export',
- component: './List/TableList',
+ component: './DataManagement/Import',
},
]
},
diff --git a/web/src/pages/DataManagement/Backup.js b/web/src/pages/DataManagement/Backup.js
new file mode 100644
index 00000000..30f7a9e2
--- /dev/null
+++ b/web/src/pages/DataManagement/Backup.js
@@ -0,0 +1,47 @@
+import React, { Component } from 'react';
+import router from 'umi/router';
+import { connect } from 'dva';
+import PageHeaderWrapper from '@/components/PageHeaderWrapper';
+
+@connect()
+class Backup extends Component {
+ handleTabChange = key => {
+ const { match } = this.props;
+ switch (key) {
+ case 'bakandrestore':
+ router.push(`${match.url}/bakandrestore`);
+ break;
+ case 'bakcycle':
+ router.push(`${match.url}/bakcycle`);
+ break;
+ default:
+ break;
+ }
+ }
+ render() {
+ const tabList = [
+ {
+ key: 'bakandrestore',
+ tab: '索引备份与还原',
+ },
+ {
+ key: 'bakcycle',
+ tab: '备份周期管理',
+ }
+ ];
+
+ const { match, children, location } = this.props;
+
+ return (
+
+ {children}
+
+ );
+ }
+}
+
+export default Backup;
diff --git a/web/src/pages/DataManagement/Document.js b/web/src/pages/DataManagement/Document.js
new file mode 100644
index 00000000..2ea4a252
--- /dev/null
+++ b/web/src/pages/DataManagement/Document.js
@@ -0,0 +1,376 @@
+import React, { PureComponent, Fragment } from 'react';
+import { connect } from 'dva';
+import {
+ Row,
+ Col,
+ Card,
+ Form,
+ Input,
+ Button,
+ Modal,
+ message,
+ Divider,
+} from 'antd';
+import StandardTable from '@/components/StandardTable';
+import PageHeaderWrapper from '@/components/PageHeaderWrapper';
+
+import styles from '../List/TableList.less';
+
+const FormItem = Form.Item;
+const { TextArea } = Input;
+
+const CreateForm = Form.create()(props => {
+ const { modalVisible, form, handleAdd, handleModalVisible } = props;
+ const okHandle = () => {
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ form.resetFields();
+ handleAdd(fieldsValue);
+ });
+ };
+ return (
+ handleModalVisible()}
+ >
+
+ {form.getFieldDecorator('index', {
+ rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
+ })()}
+
+
+ {form.getFieldDecorator('settings', {
+ rules: [{ required: true }],
+ })()}
+
+
+ );
+});
+
+const UpdateForm = Form.create()(props => {
+ const { updateModalVisible, handleUpdateModalVisible, handleUpdate,values,form } = props;
+
+ const okHandle = () => {
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ form.resetFields();
+ handleUpdate(fieldsValue);
+ });
+ };
+
+ return (
+ handleUpdateModalVisible()}
+ >
+
+ {form.getFieldDecorator('index', {
+ initialValue: values.index,
+ rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
+ })()}
+
+
+ {form.getFieldDecorator('settings', {
+ initialValue: values.processors,
+ rules: [{ required: true }],
+ })()}
+
+
+ );
+});
+
+/* eslint react/no-multi-comp:0 */
+@connect(({ pipeline, loading }) => ({
+ pipeline,
+ loading: loading.models.pipeline,
+}))
+@Form.create()
+class Document extends PureComponent {
+ state = {
+ modalVisible: false,
+ updateModalVisible: false,
+ expandForm: false,
+ selectedRows: [],
+ formValues: {},
+ updateFormValues: {},
+ };
+ datasource = `[{"health":"green","status":"open","index":"blogs_fixed","uuid":"Q6zngGf9QVaWqpV0lF-0nw","pri":"1","rep":"1","docs.count":"1594","docs.deleted":"594","store.size":"17.9mb","pri.store.size":"8.9mb"},{"health":"red","status":"open","index":"elastic_qa","uuid":"_qkVlQ5LRoOKffV-nFj8Uw","pri":"1","rep":"1","docs.count":null,"docs.deleted":null,"store.size":null,"pri.store.size":null},{"health":"green","status":"open","index":".kibana-event-log-7.9.0-000001","uuid":"fgTtyl62Tc6F1ddJfPwqHA","pri":"1","rep":"1","docs.count":"20","docs.deleted":"0","store.size":"25kb","pri.store.size":"12.5kb"},{"health":"green","status":"open","index":"blogs","uuid":"Mb2n4wnNQSKqSToI_QO0Yg","pri":"1","rep":"1","docs.count":"1594","docs.deleted":"0","store.size":"11mb","pri.store.size":"5.5mb"},{"health":"green","status":"open","index":".kibana-event-log-7.9.0-000002","uuid":"8GpbwnDXR2KJUsw6srLnWw","pri":"1","rep":"1","docs.count":"9","docs.deleted":"0","store.size":"96.9kb","pri.store.size":"48.4kb"},{"health":"green","status":"open","index":".apm-agent-configuration","uuid":"vIaV9k2VS-W48oUOe2xNWA","pri":"1","rep":"1","docs.count":"0","docs.deleted":"0","store.size":"416b","pri.store.size":"208b"},{"health":"green","status":"open","index":"logs_server1","uuid":"u56jv2AyR2KOkruOfxIAnA","pri":"1","rep":"1","docs.count":"5386","docs.deleted":"0","store.size":"5.1mb","pri.store.size":"2.5mb"},{"health":"green","status":"open","index":".kibana_1","uuid":"dBCrfVblRPGVlYAIlP_Duw","pri":"1","rep":"1","docs.count":"3187","docs.deleted":"50","store.size":"24.8mb","pri.store.size":"12.4mb"},{"health":"green","status":"open","index":".tasks","uuid":"3RafayGeSNiqglO2BHof9Q","pri":"1","rep":"1","docs.count":"3","docs.deleted":"0","store.size":"39.9kb","pri.store.size":"19.9kb"},{"health":"green","status":"open","index":"filebeat-7.9.0-elastic_qa","uuid":"tktSYU14S3CrsrJb0ybpSQ","pri":"1","rep":"1","docs.count":"3009880","docs.deleted":"0","store.size":"1.6gb","pri.store.size":"850.1mb"},{"health":"green","status":"open","index":"analysis_test","uuid":"6ZHEAW1ST_qfg7mo4Bva4w","pri":"1","rep":"1","docs.count":"0","docs.deleted":"0","store.size":"416b","pri.store.size":"208b"},{"health":"green","status":"open","index":".apm-custom-link","uuid":"Y4N2TeVERrGacEGwY-NPAQ","pri":"1","rep":"1","docs.count":"0","docs.deleted":"0","store.size":"416b","pri.store.size":"208b"},{"health":"green","status":"open","index":"kibana_sample_data_ecommerce","uuid":"4FIWJKhGSr6bE72R0xEQyA","pri":"1","rep":"1","docs.count":"4675","docs.deleted":"0","store.size":"9.2mb","pri.store.size":"4.6mb"},{"health":"green","status":"open","index":".kibana_task_manager_1","uuid":"9afyndU_Q26oqOiEIoqRJw","pri":"1","rep":"1","docs.count":"6","docs.deleted":"2","store.size":"378.8kb","pri.store.size":"12.5kb"},{"health":"green","status":"open","index":".async-search","uuid":"2VbJgnN7SsqC-DWN64yXUQ","pri":"1","rep":"1","docs.count":"0","docs.deleted":"0","store.size":"3.9kb","pri.store.size":"3.7kb"}]`;
+
+ columns = [
+ {
+ title: '索引名称',
+ dataIndex: 'index',
+ },
+ {
+ title: '文档数',
+ dataIndex: 'docs.count',
+ },
+ {
+ title: '主分片数',
+ dataIndex: 'pri'
+ },
+ {
+ title: '从分片数',
+ dataIndex: 'rep'
+ },
+ {
+ title: '存储大小',
+ dataIndex: 'store.size'
+ },
+ {
+ title: '操作',
+ render: (text, record) => (
+
+ this.handleUpdateModalVisible(true, record)}>设置
+
+ {
+ this.state.selectedRows.push(record);
+ this.handleDeleteClick();
+ }}>删除
+
+ {
+ this.state.selectedRows.push(record);
+ this.handleDeleteClick();
+ }}>新增文档
+
+ ),
+ },
+ ];
+
+ componentDidMount() {
+ const { dispatch } = this.props;
+ // dispatch({
+ // type: 'pipeline/fetch',
+ // });
+ }
+
+ handleStandardTableChange = (pagination, filtersArg, sorter) => {
+ const { dispatch } = this.props;
+ const { formValues } = this.state;
+
+ const filters = Object.keys(filtersArg).reduce((obj, key) => {
+ const newObj = { ...obj };
+ newObj[key] = getValue(filtersArg[key]);
+ return newObj;
+ }, {});
+
+ const params = {
+ currentPage: pagination.current,
+ pageSize: pagination.pageSize,
+ ...formValues,
+ ...filters,
+ };
+ if (sorter.field) {
+ params.sorter = `${sorter.field}_${sorter.order}`;
+ }
+
+ dispatch({
+ type: 'pipeline/fetch',
+ payload: params,
+ });
+ };
+
+ handleFormReset = () => {
+ const { form, dispatch } = this.props;
+ form.resetFields();
+ this.setState({
+ formValues: {},
+ });
+ dispatch({
+ type: 'pipeline/fetch',
+ payload: {},
+ });
+ };
+
+ handleDeleteClick = e => {
+ const { dispatch } = this.props;
+ const { selectedRows } = this.state;
+
+ if (!selectedRows) return;
+ dispatch({
+ type: 'pipeline/delete',
+ payload: {
+ key: selectedRows.map(row => row.name),
+ },
+ callback: () => {
+ this.setState({
+ selectedRows: [],
+ });
+ },
+ });
+ };
+
+ handleSelectRows = rows => {
+ this.setState({
+ selectedRows: rows,
+ });
+ };
+
+ handleSearch = e => {
+ e.preventDefault();
+
+ const { dispatch, form } = this.props;
+
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+
+ const values = {
+ ...fieldsValue,
+ updatedAt: fieldsValue.updatedAt && fieldsValue.updatedAt.valueOf(),
+ };
+
+ this.setState({
+ formValues: values,
+ });
+
+ dispatch({
+ type: 'rule/fetch',
+ payload: values,
+ });
+ });
+ };
+
+ handleModalVisible = flag => {
+ this.setState({
+ modalVisible: !!flag,
+ });
+ };
+
+ handleUpdateModalVisible = (flag, record) => {
+ this.setState({
+ updateModalVisible: !!flag,
+ updateFormValues: record || {},
+ });
+ };
+
+ handleAdd = fields => {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'pipeline/add',
+ payload: {
+ name: fields.name,
+ desc: fields.desc,
+ processors: fields.processors,
+ },
+ });
+
+ message.success('添加成功');
+ this.handleModalVisible();
+ };
+
+ handleUpdate = fields => {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'pipeline/update',
+ payload: {
+ name: fields.name,
+ desc: fields.desc,
+ processors: fields.processors,
+ },
+ });
+
+ message.success('修改成功');
+ this.handleUpdateModalVisible();
+ };
+
+ renderSimpleForm() {
+ const {
+ form: { getFieldDecorator },
+ } = this.props;
+ return (
+
+ );
+ }
+
+ renderForm() {
+ return this.renderSimpleForm();
+ }
+
+ render() {
+ const data = {
+ list: JSON.parse(this.datasource),
+ pagination: {
+ pageSize: 5,
+ },
+ };
+ const { selectedRows, modalVisible, updateModalVisible, updateFormValues } = this.state;
+ const parentMethods = {
+ handleAdd: this.handleAdd,
+ handleModalVisible: this.handleModalVisible,
+ };
+ const updateMethods = {
+ handleUpdateModalVisible: this.handleUpdateModalVisible,
+ handleUpdate: this.handleUpdate,
+ };
+ return (
+
+
+
+
{this.renderForm()}
+
+
+ {selectedRows.length > 0 && (
+
+
+
+ )}
+
+
+
+
+
+ {updateFormValues && Object.keys(updateFormValues).length ? (
+
+ ) : null}
+
+ );
+ }
+}
+
+export default Document;
diff --git a/web/src/pages/DataManagement/Import.js b/web/src/pages/DataManagement/Import.js
new file mode 100644
index 00000000..1acc6217
--- /dev/null
+++ b/web/src/pages/DataManagement/Import.js
@@ -0,0 +1,185 @@
+import React, { Component,Fragment } from 'react';
+import { connect } from 'dva';
+import { Card,Form,Input, Select,Button,message,Upload, Icon } from 'antd';
+const { Option } = Select;
+import { formatMessage, FormattedMessage } from 'umi/locale';
+import DescriptionList from '@/components/DescriptionList';
+import styles from '../profile/AdvancedProfile.less';
+const { Description } = DescriptionList;
+import PageHeaderWrapper from '@/components/PageHeaderWrapper';
+const FormItem = Form.Item;
+const { TextArea } = Input;
+const { Dragger } = Upload;
+const operationTabList = [
+ {
+ key: 'tab1',
+ tab: 'API',
+ },
+ {
+ key: 'tab2',
+ tab: '文件上传',
+ }
+ ];
+
+@connect(({logstash,loading }) => ({
+ data: logstash.logstash,
+ loading: loading.models.logstash,
+ submitting: loading.effects['logstash/submitLogstashConfig'],
+}))
+
+@Form.create()
+class Import extends Component {
+ state = {
+ operationkey: 'tab1',
+ };
+ componentDidMount() {
+ // message.loading('数据加载中..', 'initdata');
+ // const { dispatch } = this.props;
+ // dispatch({
+ // type: 'logstash/queryInitialLogstashConfig',
+ // });
+ }
+ onOperationTabChange = key => {
+ this.setState({ operationkey: key });
+ };
+ handleSubmit = e => {
+ const { dispatch, form } = this.props;
+ e.preventDefault();
+ form.validateFieldsAndScroll((err, values) => {
+ if (!err) {
+ let pdata = {
+ jdbc:{
+ type: values.dbtype,
+ config: values.logstash.jdbcconf,
+ },
+ };
+ if(e.target.name="kafka"){
+ pdata={
+ kafka:{
+ config: values.logstash.kafkaconf,
+ },
+ }
+ }
+ dispatch({
+ type: 'logstash/submitLogstashConfig',
+ payload: pdata,
+ });
+ }
+ });
+ };
+
+ render() {
+ const { operationkey } = this.state;
+ const { submitting, data, loading } = this.props;
+ const {
+ form: { getFieldDecorator, getFieldValue },
+ } = this.props;
+ const formItemLayout = {
+ labelCol: {
+ xs: { span: 24 },
+ sm: { span: 7 },
+ md:{span:5},
+ },
+ wrapperCol: {
+ xs: { span: 24 },
+ sm: { span: 12 },
+ md: { span: 15 },
+ },
+ };
+ const submitFormLayout = {
+ wrapperCol: {
+ xs: { span: 24, offset: 0 },
+ sm: { span: 10, offset: 7 },
+ },
+ };
+ const uploadProps = {
+ name: 'file',
+ multiple: true,
+ action: '',
+ onChange(info) {
+ const { status } = info.file;
+ if (status !== 'uploading') {
+ console.log(info.file, info.fileList);
+ }
+ if (status === 'done') {
+ message.success(`${info.file.name} file uploaded successfully.`);
+ } else if (status === 'error') {
+ message.error(`${info.file.name} file upload failed.`);
+ }
+ },
+ };
+ const contentList = {
+ tab1: (
+
+
+
+ ),
+ tab2: (
+
+
+
+
+ 点击或拖拽文件至该区域上传
+
+ 支持多文件上传
+
+
+ )
+ };
+
+ return (
+
+
+ {contentList[operationkey]}
+
+
+ );
+ }
+}
+
+export default Import;
diff --git a/web/src/pages/DataManagement/IndexLifeCycle.js b/web/src/pages/DataManagement/IndexLifeCycle.js
new file mode 100644
index 00000000..ea6a2738
--- /dev/null
+++ b/web/src/pages/DataManagement/IndexLifeCycle.js
@@ -0,0 +1,373 @@
+import React, { PureComponent, Fragment } from 'react';
+import { connect } from 'dva';
+import {
+ Row,
+ Col,
+ Card,
+ Form,
+ Input,
+ Button,
+ Modal,
+ message,
+ Divider,
+} from 'antd';
+import StandardTable from '@/components/StandardTable';
+
+import styles from '../List/TableList.less';
+
+const FormItem = Form.Item;
+const { TextArea } = Input;
+
+const CreateForm = Form.create()(props => {
+ const { modalVisible, form, handleAdd, handleModalVisible } = props;
+ const okHandle = () => {
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ form.resetFields();
+ handleAdd(fieldsValue);
+ });
+ };
+ return (
+ handleModalVisible()}
+ >
+
+ {form.getFieldDecorator('name', {
+ rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
+ })()}
+
+
+ {form.getFieldDecorator('settings', {
+ rules: [{ required: true }],
+ })()}
+
+
+ );
+});
+
+const UpdateForm = Form.create()(props => {
+ const { updateModalVisible, handleUpdateModalVisible, handleUpdate,values,form } = props;
+
+ const okHandle = () => {
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ form.resetFields();
+ handleUpdate(fieldsValue);
+ });
+ };
+
+ return (
+ handleUpdateModalVisible()}
+ >
+
+ {form.getFieldDecorator('name', {
+ initialValue: values.name,
+ rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
+ })()}
+
+
+ {form.getFieldDecorator('policy', {
+ initialValue: values.policy,
+ rules: [{ required: true }],
+ })()}
+
+
+ );
+});
+
+/* eslint react/no-multi-comp:0 */
+@connect(({ pipeline, loading }) => ({
+ pipeline,
+ loading: loading.models.pipeline,
+}))
+@Form.create()
+class IndexLifeCycle extends PureComponent {
+ state = {
+ modalVisible: false,
+ updateModalVisible: false,
+ expandForm: false,
+ selectedRows: [],
+ formValues: {},
+ updateFormValues: {},
+ };
+ datasource = `{"ilm-history-ilm-policy":{"version":1,"modified_date":"2020-08-28T13:19:39.550Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}},"delete":{"min_age":"90d","actions":{"delete":{"delete_searchable_snapshot":true}}}}}},"watch-history-ilm-policy":{"version":1,"modified_date":"2020-08-28T13:19:39.460Z","policy":{"phases":{"delete":{"min_age":"7d","actions":{"delete":{"delete_searchable_snapshot":true}}}}}},"kibana-event-log-policy":{"version":1,"modified_date":"2020-08-28T13:43:28.035Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}},"delete":{"min_age":"90d","actions":{"delete":{"delete_searchable_snapshot":true}}}}}},"metrics":{"version":1,"modified_date":"2020-08-28T13:19:39.367Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}}}}},"ml-size-based-ilm-policy":{"version":1,"modified_date":"2020-08-28T13:19:39.166Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb"}}}}}},"filebeat":{"version":1,"modified_date":"2020-08-29T10:49:38.774Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}}}}},"logs":{"version":1,"modified_date":"2020-08-28T13:19:39.289Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}}}}},"slm-history-ilm-policy":{"version":1,"modified_date":"2020-08-28T13:19:39.637Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}},"delete":{"min_age":"90d","actions":{"delete":{"delete_searchable_snapshot":true}}}}}}}`;
+ parseData = ()=>{
+ let ds = JSON.parse(this.datasource);
+ var values = [];
+ for(let key in ds){
+ values.push({
+ name: key,
+ ...ds[key],
+ policy: JSON.stringify(ds[key].policy),
+ });
+ }
+ return values;
+ }
+ columns = [
+ {
+ title: '策略名称',
+ dataIndex: 'name',
+ },
+ {
+ title: '修改日期',
+ dataIndex: 'modified_date',
+ },
+ {
+ title: '版本',
+ dataIndex: 'version'
+ },
+ {
+ title: '操作',
+ render: (text, record) => (
+
+ this.handleUpdateModalVisible(true, record)}>设置
+
+ {
+ this.state.selectedRows.push(record);
+ this.handleDeleteClick();
+ }}>删除
+
+ ),
+ },
+ ];
+
+ componentDidMount() {
+ const { dispatch } = this.props;
+ // dispatch({
+ // type: 'pipeline/fetch',
+ // });
+ }
+
+ handleStandardTableChange = (pagination, filtersArg, sorter) => {
+ const { dispatch } = this.props;
+ const { formValues } = this.state;
+
+ const filters = Object.keys(filtersArg).reduce((obj, key) => {
+ const newObj = { ...obj };
+ newObj[key] = getValue(filtersArg[key]);
+ return newObj;
+ }, {});
+
+ const params = {
+ currentPage: pagination.current,
+ pageSize: pagination.pageSize,
+ ...formValues,
+ ...filters,
+ };
+ if (sorter.field) {
+ params.sorter = `${sorter.field}_${sorter.order}`;
+ }
+
+ dispatch({
+ type: 'pipeline/fetch',
+ payload: params,
+ });
+ };
+
+ handleFormReset = () => {
+ const { form, dispatch } = this.props;
+ form.resetFields();
+ this.setState({
+ formValues: {},
+ });
+ dispatch({
+ type: 'pipeline/fetch',
+ payload: {},
+ });
+ };
+
+ handleDeleteClick = e => {
+ const { dispatch } = this.props;
+ const { selectedRows } = this.state;
+
+ if (!selectedRows) return;
+ dispatch({
+ type: 'pipeline/delete',
+ payload: {
+ key: selectedRows.map(row => row.name),
+ },
+ callback: () => {
+ this.setState({
+ selectedRows: [],
+ });
+ },
+ });
+ };
+
+ handleSelectRows = rows => {
+ this.setState({
+ selectedRows: rows,
+ });
+ };
+
+ handleSearch = e => {
+ e.preventDefault();
+
+ const { dispatch, form } = this.props;
+
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+
+ const values = {
+ ...fieldsValue,
+ updatedAt: fieldsValue.updatedAt && fieldsValue.updatedAt.valueOf(),
+ };
+
+ this.setState({
+ formValues: values,
+ });
+
+ dispatch({
+ type: 'rule/fetch',
+ payload: values,
+ });
+ });
+ };
+
+ handleModalVisible = flag => {
+ this.setState({
+ modalVisible: !!flag,
+ });
+ };
+
+ handleUpdateModalVisible = (flag, record) => {
+ this.setState({
+ updateModalVisible: !!flag,
+ updateFormValues: record || {},
+ });
+ };
+
+ handleAdd = fields => {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'pipeline/add',
+ payload: {
+ name: fields.name,
+ desc: fields.desc,
+ processors: fields.processors,
+ },
+ });
+
+ message.success('添加成功');
+ this.handleModalVisible();
+ };
+
+ handleUpdate = fields => {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'pipeline/update',
+ payload: {
+ name: fields.name,
+ desc: fields.desc,
+ processors: fields.processors,
+ },
+ });
+
+ message.success('修改成功');
+ this.handleUpdateModalVisible();
+ };
+
+ renderSimpleForm() {
+ const {
+ form: { getFieldDecorator },
+ } = this.props;
+ return (
+
+ );
+ }
+
+ renderForm() {
+ return this.renderSimpleForm();
+ }
+
+ render() {
+ const data = {
+ list: this.parseData(),
+ pagination: {
+ pageSize: 5,
+ },
+ };
+ const { selectedRows, modalVisible, updateModalVisible, updateFormValues } = this.state;
+ const parentMethods = {
+ handleAdd: this.handleAdd,
+ handleModalVisible: this.handleModalVisible,
+ };
+ const updateMethods = {
+ handleUpdateModalVisible: this.handleUpdateModalVisible,
+ handleUpdate: this.handleUpdate,
+ };
+ return (
+
+
+
+
{this.renderForm()}
+
+
+ {selectedRows.length > 0 && (
+
+
+
+ )}
+
+
+
+
+
+ {updateFormValues && Object.keys(updateFormValues).length ? (
+
+ ) : null}
+
+ );
+ }
+}
+
+export default IndexLifeCycle;
diff --git a/web/src/pages/DataManagement/IndexSummary.js b/web/src/pages/DataManagement/IndexSummary.js
new file mode 100644
index 00000000..c4cc6516
--- /dev/null
+++ b/web/src/pages/DataManagement/IndexSummary.js
@@ -0,0 +1,198 @@
+import React, { Component,Fragment,useState, useEffect } from 'react';
+import { connect } from 'dva';
+import { Card, Select,Button,Table,Row,Col } from 'antd';
+import { formatMessage, FormattedMessage } from 'umi/locale';
+import DescriptionList from '@/components/DescriptionList';
+const { Description } = DescriptionList;
+
+import { Pie,Line } from '@ant-design/charts';
+
+ const piedata =[
+ {
+ health: 'green',
+ value: 27,
+ },
+ {
+ health: 'yellow',
+ value: 25,
+ },
+ {
+ health: 'red',
+ value: 18,
+ }
+ ];
+ const config = {
+ appendPadding: 10,
+ data: piedata,
+ angleField: 'value',
+ colorField: 'health',
+ color: (field) => {
+ return field.health;
+ },
+ height: 300,
+ radius: 1,
+ innerRadius: 0.56,
+ label: {
+ type: 'inner',
+ offset: -25,
+ autoRotate: false,
+ content: '{value}',
+ style: {
+ fill: '#333',
+ stroke: '#fff',
+ strokeWidth: 1,
+ fontSize: 24,
+ },
+ },
+ interactions: [{ type: 'element-selected' }, { type: 'element-active' }],
+ statistic: {
+ title: {
+ offsetY: -20,
+ style: { fontSize: 44 },
+ formatter: function formatter(datum) {
+ return datum ? datum.type : '总计';
+ },
+ },
+ content: {
+ offsetY: 30,
+ style: { fontSize: 44 },
+ formatter: function(datum, data) {
+ return datum
+ ? ' '.concat(datum.value)
+ : ' '.concat(
+ data.reduce(function (r, d) {
+ return r + d.value;
+ }, 0),
+ );
+ },
+ },
+ },
+ };
+ const shardData =[
+ {
+ shard: 'pri',
+ value: 27,
+ },
+ {
+ shard: 'rep',
+ value: 54,
+ }
+ ];
+ const shardConfig = {
+ appendPadding: 10,
+ data: shardData,
+ angleField: 'value',
+ colorField: 'shard',
+ height: 300,
+ radius: 1,
+ innerRadius: 0.56,
+ label: {
+ type: 'inner',
+ offset: -25,
+ autoRotate: false,
+ content: '{value}',
+ style: {
+ fill: '#333',
+ stroke: '#fff',
+ strokeWidth: 1,
+ fontSize: 24,
+ },
+ },
+ interactions: [{ type: 'element-selected' }, { type: 'element-active' }],
+ statistic: {
+ title: {
+ offsetY: -20,
+ style: { fontSize: 44 },
+ formatter: function formatter(datum) {
+ return datum ? datum.type : '总计';
+ },
+ },
+ content: {
+ offsetY: 30,
+ style: { fontSize: 44 },
+ formatter: function(datum, data) {
+ return datum
+ ? ' '.concat(datum.value)
+ : ' '.concat(
+ data.reduce(function (r, d) {
+ return r + d.value;
+ }, 0),
+ );
+ },
+ },
+ },
+ };
+const datasource = `[{"health":"green","status":"open","index":"blogs_fixed","uuid":"Q6zngGf9QVaWqpV0lF-0nw","pri":"1","rep":"1","docs.count":"1594","docs.deleted":"594","store.size":"17.9mb","pri.store.size":"8.9mb"},{"health":"red","status":"open","index":"elastic_qa","uuid":"_qkVlQ5LRoOKffV-nFj8Uw","pri":"1","rep":"1","docs.count":null,"docs.deleted":null,"store.size":null,"pri.store.size":null},{"health":"green","status":"open","index":".kibana-event-log-7.9.0-000001","uuid":"fgTtyl62Tc6F1ddJfPwqHA","pri":"1","rep":"1","docs.count":"20","docs.deleted":"0","store.size":"25kb","pri.store.size":"12.5kb"},{"health":"green","status":"open","index":"blogs","uuid":"Mb2n4wnNQSKqSToI_QO0Yg","pri":"1","rep":"1","docs.count":"1594","docs.deleted":"0","store.size":"11mb","pri.store.size":"5.5mb"},{"health":"green","status":"open","index":".kibana-event-log-7.9.0-000002","uuid":"8GpbwnDXR2KJUsw6srLnWw","pri":"1","rep":"1","docs.count":"9","docs.deleted":"0","store.size":"96.9kb","pri.store.size":"48.4kb"},{"health":"green","status":"open","index":".apm-agent-configuration","uuid":"vIaV9k2VS-W48oUOe2xNWA","pri":"1","rep":"1","docs.count":"0","docs.deleted":"0","store.size":"416b","pri.store.size":"208b"},{"health":"green","status":"open","index":"logs_server1","uuid":"u56jv2AyR2KOkruOfxIAnA","pri":"1","rep":"1","docs.count":"5386","docs.deleted":"0","store.size":"5.1mb","pri.store.size":"2.5mb"},{"health":"green","status":"open","index":".kibana_1","uuid":"dBCrfVblRPGVlYAIlP_Duw","pri":"1","rep":"1","docs.count":"3187","docs.deleted":"50","store.size":"24.8mb","pri.store.size":"12.4mb"},{"health":"green","status":"open","index":".tasks","uuid":"3RafayGeSNiqglO2BHof9Q","pri":"1","rep":"1","docs.count":"3","docs.deleted":"0","store.size":"39.9kb","pri.store.size":"19.9kb"},{"health":"green","status":"open","index":"filebeat-7.9.0-elastic_qa","uuid":"tktSYU14S3CrsrJb0ybpSQ","pri":"1","rep":"1","docs.count":"3009880","docs.deleted":"0","store.size":"1.6gb","pri.store.size":"850.1mb"},{"health":"green","status":"open","index":"analysis_test","uuid":"6ZHEAW1ST_qfg7mo4Bva4w","pri":"1","rep":"1","docs.count":"0","docs.deleted":"0","store.size":"416b","pri.store.size":"208b"},{"health":"green","status":"open","index":".apm-custom-link","uuid":"Y4N2TeVERrGacEGwY-NPAQ","pri":"1","rep":"1","docs.count":"0","docs.deleted":"0","store.size":"416b","pri.store.size":"208b"},{"health":"green","status":"open","index":"kibana_sample_data_ecommerce","uuid":"4FIWJKhGSr6bE72R0xEQyA","pri":"1","rep":"1","docs.count":"4675","docs.deleted":"0","store.size":"9.2mb","pri.store.size":"4.6mb"},{"health":"green","status":"open","index":".kibana_task_manager_1","uuid":"9afyndU_Q26oqOiEIoqRJw","pri":"1","rep":"1","docs.count":"6","docs.deleted":"2","store.size":"378.8kb","pri.store.size":"12.5kb"},{"health":"green","status":"open","index":".async-search","uuid":"2VbJgnN7SsqC-DWN64yXUQ","pri":"1","rep":"1","docs.count":"0","docs.deleted":"0","store.size":"3.9kb","pri.store.size":"3.7kb"}]`;
+const columns = [
+ {
+ title: '索引名称',
+ dataIndex: 'index',
+ key: 'name',
+ },
+ {
+ title: 'UUID',
+ dataIndex: 'uuid',
+ key: 'uuid',
+ },
+ {
+ title: '文档数',
+ dataIndex: 'docs.count',
+ key: 'docs',
+ },
+ {
+ title: '主分片数',
+ dataIndex: 'pri',
+ key: 'pri',
+ },
+ {
+ title: '从分片数',
+ dataIndex: 'rep',
+ key: 'rep',
+ },
+ {
+ title: '存储大小',
+ dataIndex: 'store.size',
+ key: 'size',
+ },
+];
+@connect(({ profile, loading }) => ({
+ profile,
+ loading: loading.effects['profile/fetchBasic'],
+}))
+
+class IndexSummary extends Component {
+ state = {
+ };
+ componentDidMount() {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'profile/fetchBasic',
+ });
+ }
+ render() {
+ let data = JSON.parse(datasource);
+ return (
+
+
+
+
+
+
+ 健康状态
+
+
+
+ 分片数
+
+
+
+
+
+
+ );
+ }
+}
+
+export default IndexSummary;
diff --git a/web/src/pages/DataManagement/IndexTemplate.js b/web/src/pages/DataManagement/IndexTemplate.js
new file mode 100644
index 00000000..8bbf8ccc
--- /dev/null
+++ b/web/src/pages/DataManagement/IndexTemplate.js
@@ -0,0 +1,430 @@
+import React, { PureComponent, Fragment } from 'react';
+import { connect } from 'dva';
+import {
+ Row,
+ Col,
+ Card,
+ Form,
+ Input,
+ Button,
+ Modal,
+ message,
+ Divider,
+} from 'antd';
+import StandardTable from '@/components/StandardTable';
+import PageHeaderWrapper from '@/components/PageHeaderWrapper';
+
+import styles from '../List/TableList.less';
+
+const FormItem = Form.Item;
+const { TextArea } = Input;
+
+const CreateForm = Form.create()(props => {
+ const { modalVisible, form, handleAdd, handleModalVisible } = props;
+ const okHandle = () => {
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ form.resetFields();
+ handleAdd(fieldsValue);
+ });
+ };
+ return (
+ handleModalVisible()}
+ >
+
+ {form.getFieldDecorator('name', {
+ rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
+ })()}
+
+
+ {form.getFieldDecorator('settings', {
+ rules: [{ required: true }],
+ })()}
+
+
+ );
+});
+
+const UpdateForm = Form.create()(props => {
+ const { updateModalVisible, handleUpdateModalVisible, handleUpdate,values,form } = props;
+
+ const okHandle = () => {
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ form.resetFields();
+ handleUpdate(fieldsValue);
+ });
+ };
+
+ return (
+ handleUpdateModalVisible()}
+ >
+
+ {form.getFieldDecorator('name', {
+ initialValue: values.name,
+ rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
+ })()}
+
+
+ {form.getFieldDecorator('settings', {
+ initialValue: values.processors,
+ rules: [{ required: true }],
+ })()}
+
+
+ );
+});
+
+/* eslint react/no-multi-comp:0 */
+@connect(({ pipeline, loading }) => ({
+ pipeline,
+ loading: loading.models.pipeline,
+}))
+@Form.create()
+class IndexTemplate extends PureComponent {
+ state = {
+ modalVisible: false,
+ updateModalVisible: false,
+ expandForm: false,
+ selectedRows: [],
+ formValues: {},
+ updateFormValues: {},
+ };
+ //index template detail example
+ // {
+ // ".ml-state" : {
+ // "order" : 0,
+ // "version" : 7090199,
+ // "index_patterns" : [
+ // ".ml-state*"
+ // ],
+ // "settings" : {
+ // "index" : {
+ // "hidden" : "true",
+ // "lifecycle" : {
+ // "name" : "ml-size-based-ilm-policy",
+ // "rollover_alias" : ".ml-state-write"
+ // },
+ // "auto_expand_replicas" : "0-1"
+ // }
+ // },
+ // "mappings" : {
+ // "_meta" : {
+ // "version" : "7090199"
+ // },
+ // "enabled" : false
+ // },
+ // "aliases" : { }
+ // }
+ // }
+ datasource = `
+ [
+ {
+ "name" : "filebeat-7.9.1",
+ "index_patterns" : "[filebeat-7.9.1-*]",
+ "order" : "1",
+ "version" : null,
+ "composed_of" : ""
+ },
+ {
+ "name" : "apm-7.9.1-span",
+ "index_patterns" : "[apm-7.9.1-span*]",
+ "order" : "2",
+ "version" : null,
+ "composed_of" : ""
+ },
+ {
+ "name" : ".lists-default",
+ "index_patterns" : "[.lists-default-*]",
+ "order" : "0",
+ "version" : null,
+ "composed_of" : ""
+ },
+ {
+ "name" : ".monitoring-es",
+ "index_patterns" : "[.monitoring-es-7-*]",
+ "order" : "0",
+ "version" : "7000199",
+ "composed_of" : ""
+ },
+ {
+ "name" : ".monitoring-beats",
+ "index_patterns" : "[.monitoring-beats-7-*]",
+ "order" : "0",
+ "version" : "7000199",
+ "composed_of" : ""
+ }]`;
+
+ columns = [
+ {
+ title: '模板名称',
+ dataIndex: 'name',
+ },
+ {
+ title: '索引模式',
+ dataIndex: 'index_patterns',
+ },
+ {
+ title: 'order',
+ dataIndex: 'order'
+ },
+ {
+ title: '版本',
+ dataIndex: 'version'
+ },
+ {
+ title: '操作',
+ render: (text, record) => (
+
+ this.handleUpdateModalVisible(true, record)}>设置
+
+ {
+ this.state.selectedRows.push(record);
+ this.handleDeleteClick();
+ }}>删除
+
+ ),
+ },
+ ];
+
+ componentDidMount() {
+ const { dispatch } = this.props;
+ // dispatch({
+ // type: 'pipeline/fetch',
+ // });
+ }
+
+ handleStandardTableChange = (pagination, filtersArg, sorter) => {
+ const { dispatch } = this.props;
+ const { formValues } = this.state;
+
+ const filters = Object.keys(filtersArg).reduce((obj, key) => {
+ const newObj = { ...obj };
+ newObj[key] = getValue(filtersArg[key]);
+ return newObj;
+ }, {});
+
+ const params = {
+ currentPage: pagination.current,
+ pageSize: pagination.pageSize,
+ ...formValues,
+ ...filters,
+ };
+ if (sorter.field) {
+ params.sorter = `${sorter.field}_${sorter.order}`;
+ }
+
+ dispatch({
+ type: 'pipeline/fetch',
+ payload: params,
+ });
+ };
+
+ handleFormReset = () => {
+ const { form, dispatch } = this.props;
+ form.resetFields();
+ this.setState({
+ formValues: {},
+ });
+ dispatch({
+ type: 'pipeline/fetch',
+ payload: {},
+ });
+ };
+
+ handleDeleteClick = e => {
+ const { dispatch } = this.props;
+ const { selectedRows } = this.state;
+
+ if (!selectedRows) return;
+ dispatch({
+ type: 'pipeline/delete',
+ payload: {
+ key: selectedRows.map(row => row.name),
+ },
+ callback: () => {
+ this.setState({
+ selectedRows: [],
+ });
+ },
+ });
+ };
+
+ handleSelectRows = rows => {
+ this.setState({
+ selectedRows: rows,
+ });
+ };
+
+ handleSearch = e => {
+ e.preventDefault();
+
+ const { dispatch, form } = this.props;
+
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+
+ const values = {
+ ...fieldsValue,
+ updatedAt: fieldsValue.updatedAt && fieldsValue.updatedAt.valueOf(),
+ };
+
+ this.setState({
+ formValues: values,
+ });
+
+ dispatch({
+ type: 'rule/fetch',
+ payload: values,
+ });
+ });
+ };
+
+ handleModalVisible = flag => {
+ this.setState({
+ modalVisible: !!flag,
+ });
+ };
+
+ handleUpdateModalVisible = (flag, record) => {
+ this.setState({
+ updateModalVisible: !!flag,
+ updateFormValues: record || {},
+ });
+ };
+
+ handleAdd = fields => {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'pipeline/add',
+ payload: {
+ name: fields.name,
+ desc: fields.desc,
+ processors: fields.processors,
+ },
+ });
+
+ message.success('添加成功');
+ this.handleModalVisible();
+ };
+
+ handleUpdate = fields => {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'pipeline/update',
+ payload: {
+ name: fields.name,
+ desc: fields.desc,
+ processors: fields.processors,
+ },
+ });
+
+ message.success('修改成功');
+ this.handleUpdateModalVisible();
+ };
+
+ renderSimpleForm() {
+ const {
+ form: { getFieldDecorator },
+ } = this.props;
+ return (
+
+ );
+ }
+
+ renderForm() {
+ return this.renderSimpleForm();
+ }
+
+ render() {
+ const data = {
+ list: JSON.parse(this.datasource),
+ pagination: {
+ pageSize: 5,
+ },
+ };
+ const { selectedRows, modalVisible, updateModalVisible, updateFormValues } = this.state;
+ const parentMethods = {
+ handleAdd: this.handleAdd,
+ handleModalVisible: this.handleModalVisible,
+ };
+ const updateMethods = {
+ handleUpdateModalVisible: this.handleUpdateModalVisible,
+ handleUpdate: this.handleUpdate,
+ };
+ return (
+
+
+
+
{this.renderForm()}
+
+
+ {selectedRows.length > 0 && (
+
+
+
+ )}
+
+
+
+
+
+ {updateFormValues && Object.keys(updateFormValues).length ? (
+
+ ) : null}
+
+ );
+ }
+}
+
+export default IndexTemplate;
diff --git a/web/src/pages/DataManagement/IngestPipeline.js b/web/src/pages/DataManagement/IngestPipeline.js
index 2834a035..12329d09 100644
--- a/web/src/pages/DataManagement/IngestPipeline.js
+++ b/web/src/pages/DataManagement/IngestPipeline.js
@@ -34,8 +34,6 @@ const getValue = obj =>
Object.keys(obj)
.map(key => obj[key])
.join(',');
-const statusMap = ['default', 'processing', 'success', 'error'];
-const status = ['关闭', '运行中', '已上线', '异常'];
const CreateForm = Form.create()(props => {
const { modalVisible, form, handleAdd, handleModalVisible } = props;
diff --git a/web/src/pages/DataManagement/IngestPipeline.less b/web/src/pages/DataManagement/IngestPipeline.less
new file mode 100644
index 00000000..e69de29b
diff --git a/web/src/pages/DataManagement/Rebuild.js b/web/src/pages/DataManagement/Rebuild.js
new file mode 100644
index 00000000..49760747
--- /dev/null
+++ b/web/src/pages/DataManagement/Rebuild.js
@@ -0,0 +1,222 @@
+import React, { Component } from 'react';
+import { connect } from 'dva';
+import PageHeaderWrapper from '@/components/PageHeaderWrapper';
+import {Steps, Card, Form, Select, Input,Button, Divider,message,Spin} from 'antd';
+
+const {Step} = Steps;
+const {Option} = Select;
+const {TextArea} = Input;
+
+@Form.create()
+@connect()
+class Rebuild extends Component {
+ state = {
+ currentStep: 0,
+ configData: {},
+ }
+ renderSteps(currentStep){
+ var stepDom = '';
+ const { getFieldDecorator } = this.props.form;
+ const formItemLayout = {
+ labelCol: {
+ xs: { span: 8 },
+ sm: { span: 8 },
+ md:{span:4},
+ },
+ wrapperCol: {
+ xs: { span: 16 },
+ sm: { span: 16 },
+ md:{span:20},
+ },
+ };
+ const tailFormItemLayout = {
+ wrapperCol: {
+ xs: {
+ span: 24,
+ offset: 0,
+ },
+ sm: {
+ span: 16,
+ offset: 8,
+ },
+ md:{
+ span: 20,
+ offset: 4,
+ }
+ },
+ };
+ switch(currentStep){
+ case 0:
+ stepDom = (
+
+
+ {getFieldDecorator('source_index', {
+ initialValue: this.state.configData.source_index,
+ rules: [{ required: true, message: '请选择要重建的索引' }],
+ })(
+ ,
+ )}
+
+
+ {getFieldDecorator('creterial', {
+ initialValue: this.state.configData.creterial,
+ rules: [
+ {required: true, },
+ ],
+ })(
+
+ )}
+
+
+ {this.renderFooter(currentStep)}
+
+
+ )
+ break;
+ case 1:
+ stepDom = (
+
+
+ {getFieldDecorator('target_index', {
+ initialValue: this.state.configData.target_index,
+ rules: [{ required: true, message: '请输入目标索引名称' }],
+ })(
+
+ )}
+
+
+ {getFieldDecorator('target_setting', {
+ initialValue: this.state.configData.target_setting,
+ rules: [
+ {required: true, },
+ ],
+ })(
+
+ )}
+
+
+ {this.renderFooter(currentStep)}
+
+
+ )
+ break;
+ case 2:
+ stepDom = (
+
+
+
+
+
+ {this.renderFooter(currentStep)}
+
+
+ )
+ }
+ return stepDom;
+ }
+
+ handleNext(currentStep){
+ const { form } = this.props;
+ const { configData: oldValue } = this.state;
+ var formValues = {};
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ switch(currentStep){
+ case 0:
+ break;
+ case 1:
+
+ break;
+ }
+ formValues = fieldsValue;
+ });
+ this.setState({
+ configData: {
+ ...oldValue,
+ ...formValues,
+ },
+ currentStep: currentStep+1
+ },()=>{
+ message.info(JSON.stringify(this.state));
+ });
+ }
+ backward(currentStep){
+ if(currentStep > 0){
+ currentStep = currentStep - 1;
+ }
+ this.setState({
+ currentStep: currentStep,
+ });
+ }
+ renderFooter = currentStep => {
+ if (currentStep === 1 || currentStep ==2) {
+ return [
+ ,
+ ,
+ ,
+ ];
+ }
+ if (currentStep === 3) {
+ return [
+ ,
+ ,
+ ,
+ ];
+ }
+ return [
+ ,
+ ,
+ ];
+ };
+ render() {
+ return (
+
+
+
+
+
+
+
+
+
+ {this.renderSteps(this.state.currentStep)}
+
+
+ );
+ }
+}
+
+export default Rebuild;
diff --git a/web/src/pages/DataManagement/backup/BakAndRestore.js b/web/src/pages/DataManagement/backup/BakAndRestore.js
new file mode 100644
index 00000000..019c4547
--- /dev/null
+++ b/web/src/pages/DataManagement/backup/BakAndRestore.js
@@ -0,0 +1,237 @@
+import React, { Component,Fragment } from 'react';
+import { connect } from 'dva';
+import { Card,Form,Input, Select,Button,message,Divider,Drawer,Descriptions } from 'antd';
+const { Option } = Select;
+import { formatMessage, FormattedMessage } from 'umi/locale';
+import StandardTable from '@/components/StandardTable';
+import styles from './BakAndRestore.less';
+const FormItem = Form.Item;
+const { TextArea } = Input;
+const operationTabList = [
+ {
+ key: 'tab1',
+ tab: '快照',
+ },
+ {
+ key: 'tab2',
+ tab: '仓库',
+ }
+ ];
+
+@connect(({logstash,loading }) => ({
+ data: logstash.logstash,
+ loading: loading.models.logstash,
+ submitting: loading.effects['logstash/submitLogstashConfig'],
+}))
+
+@Form.create()
+class BakAndRestore extends Component {
+ state = {
+ operationkey: 'tab1',
+ snapshotVisible: false,
+ repVisible: false,
+ };
+ componentDidMount() {
+ // message.loading('数据加载中..', 'initdata');
+ // const { dispatch } = this.props;
+ // dispatch({
+ // type: 'logstash/queryInitialLogstashConfig',
+ // });
+ }
+ onOperationTabChange = key => {
+ this.setState({ operationkey: key });
+ };
+
+ handleSnapshotClick(record){
+ this.setState({
+ snapshotVisible: true,
+ });
+ }
+
+ repoColumns = [
+ {
+ title: '仓库名',
+ dataIndex: 'id',
+ render: (text, record) => (
+ this.handleSnapshotClick(record)}>{record.id}
+
+ )
+ },
+ {
+ title: '创建时间',
+ dataIndex: 'dateCreated'
+ },
+ {
+ title: '操作',
+ render: (text, record) => (
+
+ {/* this.handleDownload(record)}>下载
+ */}
+ {
+ this.state.selectedRows.push(record);
+ this.handleDeleteClick();
+ }}>删除
+
+ ),
+ },
+ ];
+
+ repoData = [{
+ id: "my_local_repo",
+ dateCreated: "2020-10-09 20:30:23",
+ }];
+
+ repoTable = () =>{
+ var data = {
+ list: this.repoData,
+ pagination: {
+ pageSize: 5,
+ }
+ };
+ return (
+
+ );
+ };
+
+ onCloseRep = () => {
+ this.setState({
+ repVisible: false,
+ });
+ };
+
+ snapshotColumns = [
+ {
+ title: '快照',
+ dataIndex: 'id',
+ render: (text, record) => (
+ this.handleSnapshotClick(record)}>{record.id}
+
+ )
+ },
+ {
+ title: '仓库',
+ dataIndex: 'repository',
+ },
+ {
+ title: '索引个数',
+ dataIndex: 'indices'
+ },
+ {
+ title: '分片个数',
+ dataIndex: 'shards'
+ },
+ {
+ title: '时长',
+ dataIndex: 'duration'
+ },
+ {
+ title: '创建时间',
+ dataIndex: 'dateCreated'
+ },
+ {
+ title: '操作',
+ render: (text, record) => (
+
+ this.handleDownload(record)}>下载
+
+ {
+ this.state.selectedRows.push(record);
+ this.handleDeleteClick();
+ }}>删除
+
+ ),
+ },
+ ];
+
+ snapshotData = [{
+ id: "cluster_snapshot_1",
+ repository: "my_local_repo",
+ indices: 5,
+ shards: 5,
+ duration: "2s",
+ dateCreated: "2020-10-09 20:30:23",
+ }];
+
+ snapshotTable = () =>{
+ var data = {
+ list: this.snapshotData,
+ pagination: {
+ pageSize: 5,
+ }
+ };
+ return (
+
+ );
+ };
+
+ onCloseSnapshot = () => {
+ this.setState({
+ snapshotVisible: false,
+ });
+ };
+
+ render() {
+ const { operationkey } = this.state;
+ const contentList = {
+ tab1: (
+
+ {this.snapshotTable()}
+
+ ),
+ tab2: (
+
+ {this.repoTable()}
+
+ Some contents...
+ Some contents...
+ Some contents...
+
+
+ )
+ };
+ return (
+
+
+ {contentList[operationkey]}
+
+
+
+
+ Zhou Maomao
+ 1810000000
+
+
+
+
+
+ );
+ }
+}
+
+export default BakAndRestore;
diff --git a/web/src/pages/DataManagement/backup/BakAndRestore.less b/web/src/pages/DataManagement/backup/BakAndRestore.less
new file mode 100644
index 00000000..a1c68de0
--- /dev/null
+++ b/web/src/pages/DataManagement/backup/BakAndRestore.less
@@ -0,0 +1,12 @@
+
+.tabsCard {
+ :global {
+ .ant-card-head {
+ padding: 0 16px;
+ }
+ }
+}
+.btnRestore{
+ position:absolute;
+ bottom: 20px;
+}
diff --git a/web/src/pages/DataManagement/backup/BakCycle.js b/web/src/pages/DataManagement/backup/BakCycle.js
new file mode 100644
index 00000000..921f8f3b
--- /dev/null
+++ b/web/src/pages/DataManagement/backup/BakCycle.js
@@ -0,0 +1,386 @@
+import React, { PureComponent, Fragment } from 'react';
+import { connect } from 'dva';
+import {
+ Row,
+ Col,
+ Card,
+ Form,
+ Input,
+ Button,
+ Modal,
+ message,
+ Divider,
+ Drawer,
+} from 'antd';
+import StandardTable from '@/components/StandardTable';
+
+import styles from '../../List/TableList.less';
+
+const FormItem = Form.Item;
+const { TextArea } = Input;
+
+const CreateForm = Form.create()(props => {
+ const { modalVisible, form, handleAdd, handleModalVisible } = props;
+ const okHandle = () => {
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ form.resetFields();
+ handleAdd(fieldsValue);
+ });
+ };
+ return (
+ handleModalVisible()}
+ >
+
+ {form.getFieldDecorator('name', {
+ rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
+ })()}
+
+
+ {form.getFieldDecorator('settings', {
+ rules: [{ required: true }],
+ })()}
+
+
+ );
+});
+
+const UpdateForm = Form.create()(props => {
+ const { updateModalVisible, handleUpdateModalVisible, handleUpdate,values,form } = props;
+
+ const okHandle = () => {
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+ form.resetFields();
+ handleUpdate(fieldsValue);
+ });
+ };
+
+ return (
+ handleUpdateModalVisible()}
+ >
+
+ {form.getFieldDecorator('name', {
+ initialValue: values.name,
+ rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
+ })()}
+
+
+ {form.getFieldDecorator('policy', {
+ initialValue: values.policy,
+ rules: [{ required: true }],
+ })()}
+
+
+ );
+});
+
+/* eslint react/no-multi-comp:0 */
+@connect(({ pipeline, loading }) => ({
+ pipeline,
+ loading: loading.models.pipeline,
+}))
+@Form.create()
+class BakCycle extends PureComponent {
+ state = {
+ modalVisible: false,
+ updateModalVisible: false,
+ expandForm: false,
+ selectedRows: [],
+ formValues: {},
+ updateFormValues: {},
+ drawerVisible: false,
+ };
+ datasource = `{"ilm-history-ilm-policy":{"version":1,"modified_date":"2020-08-28T13:19:39.550Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}},"delete":{"min_age":"90d","actions":{"delete":{"delete_searchable_snapshot":true}}}}}},"watch-history-ilm-policy":{"version":1,"modified_date":"2020-08-28T13:19:39.460Z","policy":{"phases":{"delete":{"min_age":"7d","actions":{"delete":{"delete_searchable_snapshot":true}}}}}},"kibana-event-log-policy":{"version":1,"modified_date":"2020-08-28T13:43:28.035Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}},"delete":{"min_age":"90d","actions":{"delete":{"delete_searchable_snapshot":true}}}}}},"metrics":{"version":1,"modified_date":"2020-08-28T13:19:39.367Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}}}}},"ml-size-based-ilm-policy":{"version":1,"modified_date":"2020-08-28T13:19:39.166Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb"}}}}}},"filebeat":{"version":1,"modified_date":"2020-08-29T10:49:38.774Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}}}}},"logs":{"version":1,"modified_date":"2020-08-28T13:19:39.289Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}}}}},"slm-history-ilm-policy":{"version":1,"modified_date":"2020-08-28T13:19:39.637Z","policy":{"phases":{"hot":{"min_age":"0ms","actions":{"rollover":{"max_size":"50gb","max_age":"30d"}}},"delete":{"min_age":"90d","actions":{"delete":{"delete_searchable_snapshot":true}}}}}}}`;
+ parseData = ()=>{
+ let ds = JSON.parse(this.datasource);
+ var values = [];
+ for(let key in ds){
+ values.push({
+ name: key,
+ ...ds[key],
+ policy: JSON.stringify(ds[key].policy),
+ });
+ }
+ return values;
+ }
+ columns = [
+ {
+ title: '策略名称',
+ dataIndex: 'name',
+ },
+ {
+ title: '修改日期',
+ dataIndex: 'modified_date',
+ },
+ {
+ title: '版本',
+ dataIndex: 'version'
+ },
+ {
+ title: '操作',
+ render: (text, record) => (
+
+ this.handleUpdateModalVisible(true, record)}>设置
+
+ {
+ this.state.selectedRows.push(record);
+ this.handleDeleteClick();
+ }}>删除
+
+ ),
+ },
+ ];
+
+ componentDidMount() {
+ const { dispatch } = this.props;
+ // dispatch({
+ // type: 'pipeline/fetch',
+ // });
+ }
+
+ handleStandardTableChange = (pagination, filtersArg, sorter) => {
+ const { dispatch } = this.props;
+ const { formValues } = this.state;
+
+ const filters = Object.keys(filtersArg).reduce((obj, key) => {
+ const newObj = { ...obj };
+ newObj[key] = getValue(filtersArg[key]);
+ return newObj;
+ }, {});
+
+ const params = {
+ currentPage: pagination.current,
+ pageSize: pagination.pageSize,
+ ...formValues,
+ ...filters,
+ };
+ if (sorter.field) {
+ params.sorter = `${sorter.field}_${sorter.order}`;
+ }
+
+ dispatch({
+ type: 'pipeline/fetch',
+ payload: params,
+ });
+ };
+
+ handleFormReset = () => {
+ const { form, dispatch } = this.props;
+ form.resetFields();
+ this.setState({
+ formValues: {},
+ });
+ dispatch({
+ type: 'pipeline/fetch',
+ payload: {},
+ });
+ };
+
+ handleDeleteClick = e => {
+ const { dispatch } = this.props;
+ const { selectedRows } = this.state;
+
+ if (!selectedRows) return;
+ dispatch({
+ type: 'pipeline/delete',
+ payload: {
+ key: selectedRows.map(row => row.name),
+ },
+ callback: () => {
+ this.setState({
+ selectedRows: [],
+ });
+ },
+ });
+ };
+
+ handleSelectRows = rows => {
+ this.setState({
+ selectedRows: rows,
+ });
+ };
+
+ handleSearch = e => {
+ e.preventDefault();
+
+ const { dispatch, form } = this.props;
+
+ form.validateFields((err, fieldsValue) => {
+ if (err) return;
+
+ const values = {
+ ...fieldsValue,
+ updatedAt: fieldsValue.updatedAt && fieldsValue.updatedAt.valueOf(),
+ };
+
+ this.setState({
+ formValues: values,
+ });
+
+ dispatch({
+ type: 'rule/fetch',
+ payload: values,
+ });
+ });
+ };
+
+ handleModalVisible = flag => {
+ this.setState({
+ modalVisible: !!flag,
+ });
+ };
+
+ handleUpdateModalVisible = (flag, record) => {
+ this.setState({
+ updateModalVisible: !!flag,
+ updateFormValues: record || {},
+ });
+ };
+
+ handleAdd = fields => {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'pipeline/add',
+ payload: {
+ name: fields.name,
+ desc: fields.desc,
+ processors: fields.processors,
+ },
+ });
+
+ message.success('添加成功');
+ this.handleModalVisible();
+ };
+
+ handleUpdate = fields => {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'pipeline/update',
+ payload: {
+ name: fields.name,
+ desc: fields.desc,
+ processors: fields.processors,
+ },
+ });
+
+ message.success('修改成功');
+ this.handleUpdateModalVisible();
+ };
+
+ renderSimpleForm() {
+ const {
+ form: { getFieldDecorator },
+ } = this.props;
+ return (
+
+ );
+ }
+
+ renderForm() {
+ return this.renderSimpleForm();
+ }
+
+ render() {
+ const data = {
+ list: this.parseData(),
+ pagination: {
+ pageSize: 5,
+ },
+ };
+ const { selectedRows, modalVisible, updateModalVisible, updateFormValues } = this.state;
+ const parentMethods = {
+ handleAdd: this.handleAdd,
+ handleModalVisible: this.handleModalVisible,
+ };
+ const updateMethods = {
+ handleUpdateModalVisible: this.handleUpdateModalVisible,
+ handleUpdate: this.handleUpdate,
+ };
+ return (
+
+
+
+
{this.renderForm()}
+
+
+ {selectedRows.length > 0 && (
+
+
+
+ )}
+
+
+
+
+
+ {updateFormValues && Object.keys(updateFormValues).length ? (
+
+ ) : null}
+
+ Some contents...
+ Some contents...
+ Some contents...
+
+
+ );
+ }
+}
+
+export default BakCycle;
diff --git a/web/src/pages/DataManagement/indices.js b/web/src/pages/DataManagement/indices.js
new file mode 100644
index 00000000..c3538595
--- /dev/null
+++ b/web/src/pages/DataManagement/indices.js
@@ -0,0 +1,61 @@
+import React, { Component } from 'react';
+import router from 'umi/router';
+import { connect } from 'dva';
+import PageHeaderWrapper from '@/components/PageHeaderWrapper';
+
+@connect()
+class Indices extends Component {
+ handleTabChange = key => {
+ const { match } = this.props;
+ switch (key) {
+ case 'summary':
+ router.push(`${match.url}/summary`);
+ break;
+ case 'doc':
+ router.push(`${match.url}/doc`);
+ break;
+ case 'template':
+ router.push(`${match.url}/template`);
+ break;
+ case 'ilm':
+ router.push(`${match.url}/ilm`);
+ break;
+ default:
+ break;
+ }
+ }
+ render() {
+ const tabList = [
+ {
+ key: 'summary',
+ tab: '索引概览',
+ },
+ {
+ key: 'doc',
+ tab: '索引文档管理',
+ },
+ {
+ key: 'template',
+ tab: '索引模板管理',
+ },
+ {
+ key: 'ilm',
+ tab: '索引生命周期管理',
+ }
+ ];
+
+ const { match, children, location } = this.props;
+
+ return (
+
+ {children}
+
+ );
+ }
+}
+
+export default Indices;