fullfill document CURD preview
This commit is contained in:
parent
814405709f
commit
a74511ad4d
|
@ -0,0 +1,136 @@
|
|||
package index_management
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
httprouter "infini.sh/framework/core/api/router"
|
||||
"infini.sh/framework/core/elastic"
|
||||
"infini.sh/framework/core/util"
|
||||
)
|
||||
|
||||
type docReqBody struct {
|
||||
Index string `json:"index"`
|
||||
Action string `json:"action"`
|
||||
Payload map[string]interface{} `json:"payload"`
|
||||
PageIndex int `json:"pageIndex"`
|
||||
PageSize int `json:"pageSize"`
|
||||
Filter string `json:"filter"`
|
||||
Cluster string `json:"cluster"`
|
||||
}
|
||||
|
||||
func (handler APIHandler) HandleDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
||||
reqBody := docReqBody{}
|
||||
resResult := map[string]interface{}{
|
||||
"errno": "0",
|
||||
"errmsg": "",
|
||||
"payload": nil,
|
||||
}
|
||||
err := handler.DecodeJSON(req, &reqBody)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
indexName := ps.ByName("index")
|
||||
var id string
|
||||
if val, ok := reqBody.Payload["id"]; ok {
|
||||
id = val.(string)
|
||||
}
|
||||
if _, ok := reqBody.Payload["_index"]; ok {
|
||||
delete(reqBody.Payload, "_index")
|
||||
}
|
||||
switch reqBody.Action {
|
||||
case "ADD":
|
||||
id = util.GetUUID()
|
||||
//security problem
|
||||
_, err := client.Index(indexName, id, reqBody.Payload)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
reqBody.Payload["id"] = id
|
||||
resResult["payload"] = reqBody.Payload
|
||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
||||
case "SAVE":
|
||||
if id == "" {
|
||||
panic("empty id")
|
||||
}
|
||||
resp, err := client.Get(indexName, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
source := resp.Source
|
||||
for k, v := range reqBody.Payload {
|
||||
source[k] = v
|
||||
}
|
||||
_, err = client.Index(indexName, id, source)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
||||
|
||||
case "DELETE":
|
||||
if id == "" {
|
||||
panic("empty id")
|
||||
}
|
||||
_, err = client.Delete(indexName, id)
|
||||
if err != nil {
|
||||
resResult["errmsg"] = err.Error()
|
||||
resResult["errno"] = "E100003"
|
||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
||||
return
|
||||
}
|
||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
||||
default:
|
||||
var (
|
||||
pageSize = 10
|
||||
pageIndex = 1
|
||||
)
|
||||
if reqBody.PageSize > 0 {
|
||||
pageSize = reqBody.PageSize
|
||||
}
|
||||
if reqBody.PageIndex > 0 {
|
||||
pageIndex = reqBody.PageIndex
|
||||
}
|
||||
from := (pageIndex - 1) * pageSize
|
||||
filter := `{"match_all": {}}`
|
||||
if reqBody.Filter != "" {
|
||||
filter = reqBody.Filter
|
||||
}
|
||||
query := fmt.Sprintf(`{"from":%d, "size": %d, "query": %s}`, from, pageSize, filter)
|
||||
var reqBytes = []byte(query)
|
||||
resp, err := client.SearchWithRawQueryDSL(indexName, reqBytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
result := formatESSearchResult(resp)
|
||||
|
||||
handler.WriteJSON(w, map[string]interface{}{
|
||||
"errno": "0",
|
||||
"errmsg": "",
|
||||
"payload": result,
|
||||
}, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
func formatESSearchResult(esResp *elastic.SearchResponse) map[string]interface{} {
|
||||
total := esResp.Hits.Total
|
||||
if len(esResp.Hits.Hits) == 0 {
|
||||
return map[string]interface{}{
|
||||
"total": total,
|
||||
"data": nil,
|
||||
}
|
||||
}
|
||||
dataArr := make([]interface{}, 0, len(esResp.Hits.Hits))
|
||||
for _, hit := range esResp.Hits.Hits {
|
||||
if _, ok := hit.Source["id"]; !ok {
|
||||
hit.Source["id"] = hit.ID
|
||||
}
|
||||
hit.Source["_index"] = hit.Index
|
||||
dataArr = append(dataArr, hit.Source)
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"total": total,
|
||||
"data": dataArr,
|
||||
}
|
||||
}
|
|
@ -10,10 +10,12 @@ import (
|
|||
httprouter "infini.sh/framework/core/api/router"
|
||||
"infini.sh/framework/core/orm"
|
||||
"infini.sh/framework/core/util"
|
||||
"infini.sh/search-center/config"
|
||||
model2 "infini.sh/search-center/model"
|
||||
)
|
||||
|
||||
type APIHandler struct {
|
||||
Config *config.AppConfig
|
||||
api.Handler
|
||||
}
|
||||
|
||||
|
@ -44,37 +46,22 @@ func (handler APIHandler) GetDictListAction(w http.ResponseWriter, req *http.Req
|
|||
|
||||
func (handler APIHandler) CreateDictItemAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
//id := ps.ByName("id")
|
||||
jq, err := handler.GetJSON(req)
|
||||
if err != nil {
|
||||
handler.Error(w, err)
|
||||
return
|
||||
}
|
||||
name, err := jq.String("name")
|
||||
if err != nil {
|
||||
handler.Error(w, err)
|
||||
return
|
||||
}
|
||||
tags, err := jq.ArrayOfStrings("tags")
|
||||
if err != nil {
|
||||
handler.Error(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
content, err := jq.String("content")
|
||||
if err != nil {
|
||||
handler.Error(w, err)
|
||||
return
|
||||
}
|
||||
createdAt := time.Now()
|
||||
|
||||
dict := model2.Dict{
|
||||
ID: util.GetUUID(),
|
||||
Name: name,
|
||||
Tags: tags,
|
||||
Content: []byte(content),
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: createdAt,
|
||||
}
|
||||
err := handler.DecodeJSON(req, &dict)
|
||||
if err != nil {
|
||||
handler.WriteJSON(w, map[string]interface{}{
|
||||
"payload": nil,
|
||||
"errno": "E100001",
|
||||
"errmsg": err.Error(),
|
||||
}, http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
err = orm.Save(dict)
|
||||
if err != nil {
|
||||
|
@ -103,41 +90,18 @@ func (handler APIHandler) DeleteDictItemAction(w http.ResponseWriter, req *http.
|
|||
}
|
||||
|
||||
func (handler APIHandler) UpdateDictItemAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
jq, err := handler.GetJSON(req)
|
||||
dict := model2.Dict{}
|
||||
err := handler.DecodeJSON(req, &dict)
|
||||
if err != nil {
|
||||
handler.Error(w, err)
|
||||
handler.WriteJSON(w, map[string]interface{}{
|
||||
"payload": nil,
|
||||
"errno": "E100002",
|
||||
"errmsg": err.Error(),
|
||||
}, http.StatusOK)
|
||||
return
|
||||
}
|
||||
id, err := jq.String("id")
|
||||
if err != nil {
|
||||
handler.Error(w, err)
|
||||
return
|
||||
}
|
||||
name, err := jq.String("name")
|
||||
if err != nil {
|
||||
handler.Error(w, err)
|
||||
return
|
||||
}
|
||||
tags, err := jq.ArrayOfStrings("tags")
|
||||
if err != nil {
|
||||
handler.Error(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
content, err := jq.String("content")
|
||||
if err != nil {
|
||||
handler.Error(w, err)
|
||||
return
|
||||
}
|
||||
updatedAt := time.Now()
|
||||
|
||||
dict := model2.Dict{
|
||||
ID: id,
|
||||
Name: name,
|
||||
Tags: tags,
|
||||
Content: []byte(content),
|
||||
UpdatedAt: updatedAt,
|
||||
}
|
||||
dict.UpdatedAt = time.Now()
|
||||
|
||||
err = orm.Update(dict)
|
||||
if err != nil {
|
||||
|
|
|
@ -4,10 +4,13 @@ import (
|
|||
"infini.sh/framework/core/api"
|
||||
"infini.sh/framework/core/ui"
|
||||
"infini.sh/search-center/api/index_management"
|
||||
"infini.sh/search-center/config"
|
||||
)
|
||||
|
||||
func Init() {
|
||||
handler := index_management.APIHandler{}
|
||||
func Init(cfg *config.AppConfig) {
|
||||
handler := index_management.APIHandler{
|
||||
Config: cfg,
|
||||
}
|
||||
//ui.HandleUIMethod(api.POST, "/api/get_indices",index_management.API1)
|
||||
ui.HandleUIMethod(api.GET, "/api/dict/_search", handler.GetDictListAction)
|
||||
ui.HandleUIMethod(api.POST, "/api/dict/_create", handler.CreateDictItemAction)
|
||||
|
@ -15,4 +18,5 @@ func Init() {
|
|||
ui.HandleUIMethod(api.DELETE, "/api/dict/:id", handler.DeleteDictItemAction)
|
||||
//ui.HandleUIMethod(api.DELETE, "/api/dict/", handler.DeleteDictItemAction2)
|
||||
ui.HandleUIMethod(api.POST, "/api/dict/_update", handler.UpdateDictItemAction)
|
||||
ui.HandleUIMethod(api.POST, "/api/doc/:index", handler.HandleDocumentAction)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package config
|
||||
|
||||
type AppConfig struct {
|
||||
IndexName string `config:"index_name"`
|
||||
ElasticConfig string `config:"elastic_config"`
|
||||
UILocalPath string `config:"ui_path"`
|
||||
UILocalEnabled bool `config:"ui_local"`
|
||||
UIVFSEnabled bool `config:"ui_vfs"`
|
||||
IndexName string `config:"index_name"`
|
||||
Elasticsearch string `config:"elasticsearch"`
|
||||
UILocalPath string `config:"ui_path"`
|
||||
UILocalEnabled bool `config:"ui_local"`
|
||||
UIVFSEnabled bool `config:"ui_vfs"`
|
||||
}
|
||||
|
|
4
main.go
4
main.go
|
@ -47,7 +47,7 @@ func main() {
|
|||
modules.Register()
|
||||
|
||||
appConfig = &config.AppConfig{
|
||||
ElasticConfig: "default",
|
||||
Elasticsearch: "default",
|
||||
UILocalPath: ".public",
|
||||
UIVFSEnabled: true,
|
||||
UILocalEnabled: true,
|
||||
|
@ -62,7 +62,7 @@ func main() {
|
|||
}
|
||||
|
||||
//load web UI files
|
||||
appUI = &UI{config: appConfig}
|
||||
appUI = &UI{Config: appConfig}
|
||||
appUI.InitUI()
|
||||
|
||||
//start each module, with enabled provider
|
||||
|
|
|
@ -2,7 +2,7 @@ elasticsearch:
|
|||
- name: default
|
||||
enabled: true
|
||||
endpoint: http://localhost:9200
|
||||
index_prefix: infini-
|
||||
index_prefix:
|
||||
basic_auth:
|
||||
username: elastic
|
||||
password: ZBdkVQUUdF1Sir4X4BGB
|
||||
|
|
4
ui.go
4
ui.go
|
@ -15,7 +15,7 @@ import (
|
|||
|
||||
type UI struct {
|
||||
api.Handler
|
||||
config *config.AppConfig
|
||||
Config *config.AppConfig
|
||||
}
|
||||
|
||||
func (h UI) InitUI() {
|
||||
|
@ -24,7 +24,7 @@ func (h UI) InitUI() {
|
|||
|
||||
ui.HandleUI("/", vfs.FileServer(vfs.VFS()))
|
||||
|
||||
uiapi.Init()
|
||||
uiapi.Init(h.Config)
|
||||
|
||||
ui.HandleUIFunc("/api/", func(w http.ResponseWriter, req *http.Request) {
|
||||
log.Warn("api: ", req.URL, " not implemented")
|
||||
|
|
|
@ -90,7 +90,7 @@ export default [
|
|||
},
|
||||
{
|
||||
path: '/data/indices/doc',
|
||||
component: './DataManagement/Document',
|
||||
component: './DataManagement/Index',
|
||||
},
|
||||
{
|
||||
path: '/data/indices/template',
|
||||
|
@ -129,7 +129,7 @@ export default [
|
|||
},{
|
||||
path: '/data/doc',
|
||||
name: 'query',
|
||||
component: './DataManagement/Query',
|
||||
component: './DataManagement/Document',
|
||||
},
|
||||
]
|
||||
},
|
||||
|
|
|
@ -1,610 +1,392 @@
|
|||
import React, { PureComponent, Fragment } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'dva';
|
||||
import {
|
||||
Row,
|
||||
Col,
|
||||
Card,
|
||||
Form,
|
||||
Input,
|
||||
Button,
|
||||
Modal,
|
||||
message,
|
||||
Divider,
|
||||
Drawer,
|
||||
Tabs,
|
||||
Descriptions,
|
||||
Menu,
|
||||
Dropdown,
|
||||
Icon
|
||||
} from 'antd';
|
||||
import StandardTable from '@/components/StandardTable';
|
||||
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
|
||||
import { Col, Form, Row,Select, Input, Card,Icon, Table, InputNumber, Popconfirm,
|
||||
Divider,Button,Tooltip, Cascader } from 'antd';
|
||||
const {Option} = Select;
|
||||
|
||||
import styles from '../List/TableList.less';
|
||||
import JSONPretty from 'react-json-prettify';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { TextArea } = Input;
|
||||
const {TabPane} = Tabs;
|
||||
|
||||
class JSONWrapper extends PureComponent {
|
||||
state ={
|
||||
height: 400,
|
||||
}
|
||||
componentDidMount(){
|
||||
|
||||
let getElementTop = (elem)=>{
|
||||
var elemTop=elem.offsetTop;
|
||||
elem=elem.offsetParent;
|
||||
|
||||
while(elem!=null){
|
||||
elemTop+=elem.offsetTop;
|
||||
elem=elem.offsetParent;
|
||||
}
|
||||
|
||||
return elemTop;
|
||||
const EditableContext = React.createContext();
|
||||
|
||||
class EditableCell extends React.Component {
|
||||
getInput = () => {
|
||||
let {record, dataIndex} = this.props;
|
||||
if (typeof record[dataIndex] === 'number') {
|
||||
return <InputNumber />;
|
||||
}
|
||||
console.log(getElementTop(this.refs.jsonw));
|
||||
this.setState({height: window.innerHeight - getElementTop(this.refs.jsonw) -50});
|
||||
return <Input />;
|
||||
};
|
||||
|
||||
renderCell = ({ getFieldDecorator }) => {
|
||||
const {
|
||||
editing,
|
||||
dataIndex,
|
||||
title,
|
||||
record,
|
||||
index,
|
||||
children,
|
||||
...restProps
|
||||
} = this.props;
|
||||
return (
|
||||
<td {...restProps}>
|
||||
{editing ? (
|
||||
<Form.Item style={{ margin: 0 }}>
|
||||
{getFieldDecorator(dataIndex, {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: `Please Input ${title}!`,
|
||||
},
|
||||
],
|
||||
initialValue: record[dataIndex],
|
||||
})(this.getInput())}
|
||||
</Form.Item>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</td>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>;
|
||||
}
|
||||
}
|
||||
render(){
|
||||
return (
|
||||
<div id="jsonw" ref="jsonw" onClick={()=>{console.log(document.getElementById('jsonw').offsetTop)}} style={{overflow:"scroll", height: this.state.height}}> {this.props.children}</div>
|
||||
)
|
||||
|
||||
@Form.create()
|
||||
class EditableTable extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.operField = {
|
||||
title: 'operation',
|
||||
dataIndex: 'operation',
|
||||
render: (text, record) => {
|
||||
const { editingKey } = this.props.doclist;
|
||||
const editable = this.isEditing(record);
|
||||
return editable ? (
|
||||
<span>
|
||||
<EditableContext.Consumer>
|
||||
{form => (
|
||||
<a
|
||||
onClick={() => this.save(form, record.id)}
|
||||
style={{ marginRight: 8 }}
|
||||
>
|
||||
Save
|
||||
</a>
|
||||
)}
|
||||
</EditableContext.Consumer>
|
||||
<Popconfirm title="Sure to cancel?" onConfirm={() => this.cancel(record.id)}>
|
||||
<a>Cancel</a>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
) : (<div>
|
||||
<a disabled={editingKey !== ''} onClick={() => this.edit(record)}>
|
||||
Edit
|
||||
</a>
|
||||
<Divider type="vertical"/>
|
||||
<Popconfirm title="Sure to delete?" onConfirm={() => this.delete(record)}>
|
||||
<a>Delete</a>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
isEditing = record => record.id === this.props.doclist.editingKey;
|
||||
|
||||
cancel = () => {
|
||||
const {dispatch, doclist} = this.props;
|
||||
if(!doclist.isAddNew){
|
||||
dispatch({
|
||||
type: 'document/saveData',
|
||||
payload: { editingKey: '' },
|
||||
});
|
||||
}else{
|
||||
dispatch({
|
||||
type: 'document/cancelNew',
|
||||
payload: {},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
save(form, key) {
|
||||
const {dispatch,doclist} = this.props;
|
||||
form.validateFields((error, row) => {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
//console.log(row, key, doclist._index);
|
||||
if(!doclist.isAddNew){
|
||||
dispatch({
|
||||
type: 'document/saveDocItem',
|
||||
payload: {
|
||||
index: doclist._index,
|
||||
data: {
|
||||
id: key,
|
||||
...row,
|
||||
}
|
||||
}
|
||||
})
|
||||
}else{
|
||||
dispatch({
|
||||
type: 'document/addDocItem',
|
||||
payload: {
|
||||
index: doclist.index,
|
||||
data: row,
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
edit(record) {
|
||||
const {dispatch} = this.props;
|
||||
dispatch({
|
||||
type: 'document/saveData',
|
||||
payload: { editingKey: record.id, _index: record._index }
|
||||
});
|
||||
}
|
||||
|
||||
delete(record) {
|
||||
const {dispatch} = this.props;
|
||||
dispatch({
|
||||
type: 'document/deleteDocItem',
|
||||
payload: {
|
||||
index: record._index,
|
||||
data: {
|
||||
id: record.id,
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
handlePageChange = (pageIndex)=>{
|
||||
const {fetchData, doclist} = this.props;
|
||||
fetchData({
|
||||
pageIndex: pageIndex,
|
||||
pageSize: doclist.pageSize,
|
||||
index: doclist.index,
|
||||
cluster: doclist.cluster,
|
||||
filter: doclist.filter,
|
||||
})
|
||||
}
|
||||
|
||||
onShowSizeChange(current, pageSize) {
|
||||
console.log(current, pageSize);
|
||||
}
|
||||
|
||||
render() {
|
||||
let {doclist} = this.props;
|
||||
let columns = [];
|
||||
if(doclist.data && doclist.data.length > 0 ){
|
||||
for(let key in doclist.data[0]){
|
||||
if(["_index"].includes(key)){
|
||||
continue;
|
||||
}
|
||||
let col = {
|
||||
title: key,
|
||||
dataIndex: key,
|
||||
ellipsis: true,
|
||||
render: (text)=>(<Tooltip placement="top" title={text}>{text}</Tooltip>),
|
||||
onCell: record => ({
|
||||
record,
|
||||
dataIndex: key,
|
||||
title: key,
|
||||
editing: this.isEditing(record),
|
||||
// onMouseEnter: event => {console.log(event)},
|
||||
// onMouseLeave: event => {},
|
||||
}),
|
||||
}
|
||||
if(["id"].includes(key)){
|
||||
col.onCell = "";
|
||||
}
|
||||
columns.push(col)
|
||||
}
|
||||
}
|
||||
columns.push(this.operField);
|
||||
//console.log(columns);
|
||||
|
||||
const components = {
|
||||
body: {
|
||||
cell: EditableCell,
|
||||
},
|
||||
};
|
||||
return (
|
||||
<EditableContext.Provider value={this.props.form}>
|
||||
<Table
|
||||
components={components}
|
||||
bordered
|
||||
rowKey="id"
|
||||
size="small"
|
||||
loading={doclist.isLoading}
|
||||
dataSource={doclist.data}
|
||||
columns={columns}
|
||||
rowClassName="editable-row"
|
||||
pagination={{
|
||||
onChange: this.cancel,
|
||||
//showSizeChanger: true,
|
||||
//onShowSizeChange: this.onShowSizeChange,
|
||||
total: doclist.total? doclist.total.value: 0,
|
||||
pageSize: doclist.pageSize,
|
||||
current: doclist.pageIndex,
|
||||
onChange: this.handlePageChange,
|
||||
showTotal: (total, range) => `Total ${total} items`,
|
||||
size: 'small',
|
||||
}}
|
||||
/>
|
||||
</EditableContext.Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 (
|
||||
<Modal
|
||||
destroyOnClose
|
||||
title="新建索引"
|
||||
visible={modalVisible}
|
||||
width={640}
|
||||
onOk={okHandle}
|
||||
onCancel={() => handleModalVisible()}
|
||||
>
|
||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="索引名称">
|
||||
{form.getFieldDecorator('index', {
|
||||
rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
|
||||
})(<Input placeholder="请输入名称" />)}
|
||||
</FormItem>
|
||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="索引设置">
|
||||
{form.getFieldDecorator('settings', {
|
||||
rules: [{ required: true }],
|
||||
})(<TextArea
|
||||
style={{ minHeight: 24 }}
|
||||
placeholder="请输入"
|
||||
rows={9}
|
||||
/>)}
|
||||
</FormItem>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
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 (
|
||||
<Modal
|
||||
destroyOnClose
|
||||
title="索引设置"
|
||||
visible={updateModalVisible}
|
||||
width={640}
|
||||
onOk={okHandle}
|
||||
onCancel={() => handleUpdateModalVisible()}
|
||||
>
|
||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="索引名称">
|
||||
{form.getFieldDecorator('index', {
|
||||
initialValue: values.index,
|
||||
rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
|
||||
})(<Input placeholder="请输入名称" />)}
|
||||
</FormItem>
|
||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="索引设置">
|
||||
{form.getFieldDecorator('settings', {
|
||||
initialValue: values.processors,
|
||||
rules: [{ required: true }],
|
||||
})(<TextArea
|
||||
style={{ minHeight: 24 }}
|
||||
placeholder="请输入"
|
||||
rows={9}
|
||||
/>)}
|
||||
</FormItem>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
/* eslint react/no-multi-comp:0 */
|
||||
@connect(({ pipeline, loading }) => ({
|
||||
pipeline,
|
||||
loading: loading.models.pipeline,
|
||||
@connect(({document})=>({
|
||||
document
|
||||
}))
|
||||
@Form.create()
|
||||
class Document extends PureComponent {
|
||||
state = {
|
||||
modalVisible: false,
|
||||
updateModalVisible: false,
|
||||
expandForm: false,
|
||||
selectedRows: [],
|
||||
formValues: {},
|
||||
updateFormValues: {},
|
||||
drawerVisible: false,
|
||||
editingIndex:{},
|
||||
};
|
||||
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',
|
||||
render: (text, record) => (
|
||||
<a onClick={()=>{
|
||||
this.setState({
|
||||
editingIndex: record,
|
||||
drawerVisible: true,
|
||||
});
|
||||
}}>{text}</a>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '文档数',
|
||||
dataIndex: 'docs.count',
|
||||
},
|
||||
{
|
||||
title: '主分片数',
|
||||
dataIndex: 'pri'
|
||||
},
|
||||
{
|
||||
title: '从分片数',
|
||||
dataIndex: 'rep'
|
||||
},
|
||||
{
|
||||
title: '存储大小',
|
||||
dataIndex: 'store.size'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
render: (text, record) => (
|
||||
<Fragment>
|
||||
{/* <a onClick={() => this.handleUpdateModalVisible(true, record)}>设置</a>
|
||||
<Divider type="vertical" /> */}
|
||||
<a onClick={() => {
|
||||
this.state.selectedRows.push(record);
|
||||
this.handleDeleteClick();
|
||||
}}>删除</a>
|
||||
<Divider type="vertical" />
|
||||
<a onClick={() => {
|
||||
this.state.selectedRows.push(record);
|
||||
this.handleDeleteClick();
|
||||
}}>文档管理</a>
|
||||
</Fragment>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
componentDidMount() {
|
||||
const { dispatch } = this.props;
|
||||
// dispatch({
|
||||
// type: 'pipeline/fetch',
|
||||
// });
|
||||
class Doucment extends React.Component {
|
||||
state={
|
||||
bodyDisplay: 'none',
|
||||
}
|
||||
|
||||
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}`;
|
||||
}
|
||||
|
||||
fetchData = (params) => {
|
||||
const {dispatch} = this.props;
|
||||
dispatch({
|
||||
type: 'pipeline/fetch',
|
||||
type: 'document/fetchDocList',
|
||||
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 (
|
||||
<Form onSubmit={this.handleSearch} layout="inline">
|
||||
<Row gutter={{ md: 8, lg: 24, xl: 48 }}>
|
||||
<Col md={8} sm={24}>
|
||||
<FormItem label="索引名称">
|
||||
{getFieldDecorator('name')(<Input placeholder="请输入" />)}
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col md={8} sm={24}>
|
||||
<span className={styles.submitButtons}>
|
||||
<Button type="primary" htmlType="submit">
|
||||
查询
|
||||
</Button>
|
||||
<Button style={{ marginLeft: 8 }} onClick={this.handleFormReset}>
|
||||
重置
|
||||
</Button>
|
||||
</span>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
renderForm() {
|
||||
return this.renderSimpleForm();
|
||||
componentDidMount(){
|
||||
this.fetchData({
|
||||
pageSize: 10,
|
||||
pageIndex: 1,
|
||||
index: 'infini-test',
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = {
|
||||
list: JSON.parse(this.datasource),
|
||||
pagination: {
|
||||
pageSize: 5,
|
||||
},
|
||||
};
|
||||
const { selectedRows, modalVisible, updateModalVisible, updateFormValues,editingIndex, drawerVisible } = this.state;
|
||||
const parentMethods = {
|
||||
handleAdd: this.handleAdd,
|
||||
handleModalVisible: this.handleModalVisible,
|
||||
};
|
||||
const updateMethods = {
|
||||
handleUpdateModalVisible: this.handleUpdateModalVisible,
|
||||
handleUpdate: this.handleUpdate,
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Card bordered={false}>
|
||||
<div className={styles.tableList}>
|
||||
<div className={styles.tableListForm}>{this.renderForm()}</div>
|
||||
<div className={styles.tableListOperator}>
|
||||
<Button icon="plus" type="primary" onClick={() => this.handleModalVisible(true)}>
|
||||
新建
|
||||
</Button>
|
||||
{selectedRows.length > 0 && (
|
||||
<span>
|
||||
<Button onClick={() => this.handleDeleteClick()}>删除</Button>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<StandardTable
|
||||
selectedRows={selectedRows}
|
||||
data={data}
|
||||
columns={this.columns}
|
||||
onSelectRow={this.handleSelectRows}
|
||||
onChange={this.handleStandardTableChange}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
<CreateForm {...parentMethods} modalVisible={modalVisible} />
|
||||
{updateFormValues && Object.keys(updateFormValues).length ? (
|
||||
<UpdateForm
|
||||
{...updateMethods}
|
||||
updateModalVisible={updateModalVisible}
|
||||
values={updateFormValues}
|
||||
/>
|
||||
) : null}
|
||||
<Drawer title={editingIndex.index}
|
||||
visible={drawerVisible}
|
||||
onClose={()=>{
|
||||
this.setState({
|
||||
drawerVisible: false,
|
||||
});
|
||||
}}
|
||||
width={640}
|
||||
>
|
||||
<Tabs defaultActiveKey="1" onChange={()=>{}}>
|
||||
<TabPane tab="Summary" key="1">
|
||||
<Descriptions title="General" column={2}>
|
||||
<Descriptions.Item label="Health">green</Descriptions.Item>
|
||||
<Descriptions.Item label="Status">open</Descriptions.Item>
|
||||
<Descriptions.Item label="Primaries">1</Descriptions.Item>
|
||||
<Descriptions.Item label="Replicas">0</Descriptions.Item>
|
||||
<Descriptions.Item label="Docs Count">5</Descriptions.Item>
|
||||
<Descriptions.Item label="Docs Deleted">0</Descriptions.Item>
|
||||
<Descriptions.Item label="Storage Size">115.3kb</Descriptions.Item>
|
||||
<Descriptions.Item label="Primary Storage Size"></Descriptions.Item>
|
||||
<Descriptions.Item label="Alias">
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</TabPane>
|
||||
<TabPane tab="Mappings" key="2">
|
||||
<JSONWrapper>
|
||||
<JSONPretty json={JSON.parse(`{
|
||||
"mappings": {
|
||||
"_doc": {
|
||||
"dynamic": "strict",
|
||||
"_meta": {
|
||||
"migrationMappingPropertyHashes": {
|
||||
"migrationVersion": "4a1746014a75ade3a714e1db5763276f",
|
||||
"originId": "2f4316de49999235636386fe51dc06c1",
|
||||
"task": "235412e52d09e7165fac8a67a43ad6b4",
|
||||
"updated_at": "00da57df13e94e9d98437d13ace4bfe0",
|
||||
"references": "7997cf5a56cc02bdc9c93361bde732b0",
|
||||
"namespace": "2f4316de49999235636386fe51dc06c1",
|
||||
"type": "2f4316de49999235636386fe51dc06c1",
|
||||
"namespaces": "2f4316de49999235636386fe51dc06c1"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"migrationVersion": {
|
||||
"dynamic": "true",
|
||||
"properties": {
|
||||
"task": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"namespace": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"namespaces": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"originId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"references": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"name": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"type": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"task": {
|
||||
"properties": {
|
||||
"attempts": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ownerId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"params": {
|
||||
"type": "text"
|
||||
},
|
||||
"retryAt": {
|
||||
"type": "date"
|
||||
},
|
||||
"runAt": {
|
||||
"type": "date"
|
||||
},
|
||||
"schedule": {
|
||||
"properties": {
|
||||
"interval": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scheduledAt": {
|
||||
"type": "date"
|
||||
},
|
||||
"scope": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"startedAt": {
|
||||
"type": "date"
|
||||
},
|
||||
"state": {
|
||||
"type": "text"
|
||||
},
|
||||
"status": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"taskType": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"user": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "date"
|
||||
}
|
||||
}
|
||||
handleNewClick = ()=>{
|
||||
const {dispatch, document} = this.props;
|
||||
if(!document.data || document.data.length == 0 || document.isAddNew){
|
||||
return;
|
||||
}
|
||||
let keys = Object.keys(document.data[0])
|
||||
let newDoc = {};
|
||||
for(let key of keys){
|
||||
newDoc[key] = ""
|
||||
}
|
||||
dispatch({
|
||||
type: 'document/_addNew',
|
||||
payload: {
|
||||
docItem: newDoc,
|
||||
extra: {
|
||||
isAddNew: true
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
`)} theme={{
|
||||
background: '#F5F7FA',
|
||||
brace: '#343741',
|
||||
keyQuotes: '#343741',
|
||||
valueQuotes: '#343741',
|
||||
colon: '#343741',
|
||||
comma: '#343741',
|
||||
key: '#343741',
|
||||
value: {
|
||||
string: '#343741',
|
||||
null: '#343741',
|
||||
number: '#343741',
|
||||
boolean: '#343741',
|
||||
},
|
||||
bracket: '#343741',
|
||||
}} /></JSONWrapper>
|
||||
</TabPane>
|
||||
<TabPane tab="Stats" key="3">
|
||||
Content of Tab Pane 3
|
||||
</TabPane>
|
||||
<TabPane tab="Edit settings" key="4">
|
||||
Content of Tab Pane 3
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
<div style={{position:'absolute', bottom: 10}}>
|
||||
<Dropdown
|
||||
placement="topLeft"
|
||||
overlay={(
|
||||
<Menu onClick={()=>{}}>
|
||||
<Menu.Item key="1">
|
||||
<Icon type="delete" />
|
||||
Delete
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2">
|
||||
<Icon type="edit" />
|
||||
Edit
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3">
|
||||
<Icon type="close" />
|
||||
Close
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
)}>
|
||||
<Button type="primary">
|
||||
Manage <Icon type="up" />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
handleSearchClick = (value)=>{
|
||||
const [cluster, index] = this.indexEl.state.value;
|
||||
let targetIndex = index;
|
||||
if(value != ""){
|
||||
targetIndex = value;
|
||||
}
|
||||
console.log(targetIndex);
|
||||
this.fetchData({
|
||||
cluster,
|
||||
index: targetIndex,
|
||||
pageSize: 10,
|
||||
pageIndex: 1,
|
||||
filter: this.filterEl.state.value,
|
||||
})
|
||||
}
|
||||
|
||||
renderNew = ()=>{
|
||||
const {indices} = this.props.document;
|
||||
if((indices && indices.length > 1)){
|
||||
return;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{(indices && indices.length > 1) ? (<Select style={{width: 200, marginRight:5}} placeholder="please select a index">
|
||||
{indices.map(item=>{
|
||||
return (<Select.Option key={item} label={item}>{item}</Select.Option>)
|
||||
})}
|
||||
</Select>) : ''}
|
||||
<Button type="primary" icon="plus" onClick={this.handleNewClick}>新建</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render(){
|
||||
// const {getFieldDecorator} = this.props.form;
|
||||
//console.log(this.props.document);
|
||||
const options =[
|
||||
{
|
||||
value: 'single-es',
|
||||
label: 'single-es',
|
||||
children: [
|
||||
{
|
||||
value: 'infini-test',
|
||||
label: 'infini-test',
|
||||
}
|
||||
]}];
|
||||
return (
|
||||
<div>
|
||||
<Card>
|
||||
<Row gutter={[16, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
|
||||
<Col span={20}>
|
||||
<Input.Group compact>
|
||||
<Cascader
|
||||
options={options}
|
||||
ref={el=>{this.indexEl=el}}
|
||||
style={{width: '20%'}}
|
||||
onChange={(value, selectedOptions)=>{console.log(value)}}
|
||||
placeholder="Please select index"
|
||||
showSearch={{filter: (inputValue, path)=>path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1) }}
|
||||
/>
|
||||
<Input.Search
|
||||
style={{width:"80%"}}
|
||||
placeholder="input rewrite index or index pattern"
|
||||
enterButton="execute"
|
||||
onSearch={this.handleSearchClick}
|
||||
/>
|
||||
</Input.Group>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<a style={{marginTop:5,display:'block'}} onClick={(e)=>{
|
||||
this.setState((preState)=>{
|
||||
if(preState.bodyDisplay == 'none') {
|
||||
return {
|
||||
bodyDisplay: 'block',
|
||||
};
|
||||
}else{
|
||||
return {
|
||||
bodyDisplay: 'none'
|
||||
};
|
||||
}
|
||||
});
|
||||
}}>{this.state.bodyDisplay == 'none' ? '高级':'收起'}<Icon type="down" /></a>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{display: this.state.bodyDisplay}} gutter={[16, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
|
||||
<Col span={20}>
|
||||
<Input.TextArea ref={el=>{this.filterEl=el}} placeholder="input query filter (elasticsearch query DSL)" rows={8}/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
<div>
|
||||
<Card title={`Index: ${this.props.document.index}`}
|
||||
bodyStyle={{padding:0, paddingBottom: 24}}
|
||||
extra={this.renderNew()}
|
||||
bordered={false}>
|
||||
<EditableTable doclist={this.props.document} dispatch={this.props.dispatch}
|
||||
fetchData={(params)=>{this.fetchData(params)}}/>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
</Fragment>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Document;
|
||||
export default Doucment;
|
|
@ -0,0 +1,610 @@
|
|||
import React, { PureComponent, Fragment } from 'react';
|
||||
import { connect } from 'dva';
|
||||
import {
|
||||
Row,
|
||||
Col,
|
||||
Card,
|
||||
Form,
|
||||
Input,
|
||||
Button,
|
||||
Modal,
|
||||
message,
|
||||
Divider,
|
||||
Drawer,
|
||||
Tabs,
|
||||
Descriptions,
|
||||
Menu,
|
||||
Dropdown,
|
||||
Icon
|
||||
} from 'antd';
|
||||
import StandardTable from '@/components/StandardTable';
|
||||
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
|
||||
|
||||
import styles from '../List/TableList.less';
|
||||
import JSONPretty from 'react-json-prettify';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { TextArea } = Input;
|
||||
const {TabPane} = Tabs;
|
||||
|
||||
class JSONWrapper extends PureComponent {
|
||||
state ={
|
||||
height: 400,
|
||||
}
|
||||
componentDidMount(){
|
||||
|
||||
let getElementTop = (elem)=>{
|
||||
var elemTop=elem.offsetTop;
|
||||
elem=elem.offsetParent;
|
||||
|
||||
while(elem!=null){
|
||||
elemTop+=elem.offsetTop;
|
||||
elem=elem.offsetParent;
|
||||
}
|
||||
|
||||
return elemTop;
|
||||
|
||||
}
|
||||
console.log(getElementTop(this.refs.jsonw));
|
||||
this.setState({height: window.innerHeight - getElementTop(this.refs.jsonw) -50});
|
||||
}
|
||||
render(){
|
||||
return (
|
||||
<div id="jsonw" ref="jsonw" onClick={()=>{console.log(document.getElementById('jsonw').offsetTop)}} style={{overflow:"scroll", height: this.state.height}}> {this.props.children}</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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 (
|
||||
<Modal
|
||||
destroyOnClose
|
||||
title="新建索引"
|
||||
visible={modalVisible}
|
||||
width={640}
|
||||
onOk={okHandle}
|
||||
onCancel={() => handleModalVisible()}
|
||||
>
|
||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="索引名称">
|
||||
{form.getFieldDecorator('index', {
|
||||
rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
|
||||
})(<Input placeholder="请输入名称" />)}
|
||||
</FormItem>
|
||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="索引设置">
|
||||
{form.getFieldDecorator('settings', {
|
||||
rules: [{ required: true }],
|
||||
})(<TextArea
|
||||
style={{ minHeight: 24 }}
|
||||
placeholder="请输入"
|
||||
rows={9}
|
||||
/>)}
|
||||
</FormItem>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
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 (
|
||||
<Modal
|
||||
destroyOnClose
|
||||
title="索引设置"
|
||||
visible={updateModalVisible}
|
||||
width={640}
|
||||
onOk={okHandle}
|
||||
onCancel={() => handleUpdateModalVisible()}
|
||||
>
|
||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="索引名称">
|
||||
{form.getFieldDecorator('index', {
|
||||
initialValue: values.index,
|
||||
rules: [{ required: true, message: '请输入至少五个字符的名称!', min: 5 }],
|
||||
})(<Input placeholder="请输入名称" />)}
|
||||
</FormItem>
|
||||
<FormItem labelCol={{ span: 5 }} wrapperCol={{ span: 15 }} label="索引设置">
|
||||
{form.getFieldDecorator('settings', {
|
||||
initialValue: values.processors,
|
||||
rules: [{ required: true }],
|
||||
})(<TextArea
|
||||
style={{ minHeight: 24 }}
|
||||
placeholder="请输入"
|
||||
rows={9}
|
||||
/>)}
|
||||
</FormItem>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
/* eslint react/no-multi-comp:0 */
|
||||
@connect(({ pipeline, loading }) => ({
|
||||
pipeline,
|
||||
loading: loading.models.pipeline,
|
||||
}))
|
||||
@Form.create()
|
||||
class Index extends PureComponent {
|
||||
state = {
|
||||
modalVisible: false,
|
||||
updateModalVisible: false,
|
||||
expandForm: false,
|
||||
selectedRows: [],
|
||||
formValues: {},
|
||||
updateFormValues: {},
|
||||
drawerVisible: false,
|
||||
editingIndex:{},
|
||||
};
|
||||
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',
|
||||
render: (text, record) => (
|
||||
<a onClick={()=>{
|
||||
this.setState({
|
||||
editingIndex: record,
|
||||
drawerVisible: true,
|
||||
});
|
||||
}}>{text}</a>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '文档数',
|
||||
dataIndex: 'docs.count',
|
||||
},
|
||||
{
|
||||
title: '主分片数',
|
||||
dataIndex: 'pri'
|
||||
},
|
||||
{
|
||||
title: '从分片数',
|
||||
dataIndex: 'rep'
|
||||
},
|
||||
{
|
||||
title: '存储大小',
|
||||
dataIndex: 'store.size'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
render: (text, record) => (
|
||||
<Fragment>
|
||||
{/* <a onClick={() => this.handleUpdateModalVisible(true, record)}>设置</a>
|
||||
<Divider type="vertical" /> */}
|
||||
<a onClick={() => {
|
||||
this.state.selectedRows.push(record);
|
||||
this.handleDeleteClick();
|
||||
}}>删除</a>
|
||||
<Divider type="vertical" />
|
||||
<a onClick={() => {
|
||||
this.state.selectedRows.push(record);
|
||||
this.handleDeleteClick();
|
||||
}}>文档管理</a>
|
||||
</Fragment>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
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 (
|
||||
<Form onSubmit={this.handleSearch} layout="inline">
|
||||
<Row gutter={{ md: 8, lg: 24, xl: 48 }}>
|
||||
<Col md={8} sm={24}>
|
||||
<FormItem label="索引名称">
|
||||
{getFieldDecorator('name')(<Input placeholder="请输入" />)}
|
||||
</FormItem>
|
||||
</Col>
|
||||
<Col md={8} sm={24}>
|
||||
<span className={styles.submitButtons}>
|
||||
<Button type="primary" htmlType="submit">
|
||||
查询
|
||||
</Button>
|
||||
<Button style={{ marginLeft: 8 }} onClick={this.handleFormReset}>
|
||||
重置
|
||||
</Button>
|
||||
</span>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
renderForm() {
|
||||
return this.renderSimpleForm();
|
||||
}
|
||||
|
||||
render() {
|
||||
const data = {
|
||||
list: JSON.parse(this.datasource),
|
||||
pagination: {
|
||||
pageSize: 5,
|
||||
},
|
||||
};
|
||||
const { selectedRows, modalVisible, updateModalVisible, updateFormValues,editingIndex, drawerVisible } = this.state;
|
||||
const parentMethods = {
|
||||
handleAdd: this.handleAdd,
|
||||
handleModalVisible: this.handleModalVisible,
|
||||
};
|
||||
const updateMethods = {
|
||||
handleUpdateModalVisible: this.handleUpdateModalVisible,
|
||||
handleUpdate: this.handleUpdate,
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Card bordered={false}>
|
||||
<div className={styles.tableList}>
|
||||
<div className={styles.tableListForm}>{this.renderForm()}</div>
|
||||
<div className={styles.tableListOperator}>
|
||||
<Button icon="plus" type="primary" onClick={() => this.handleModalVisible(true)}>
|
||||
新建
|
||||
</Button>
|
||||
{selectedRows.length > 0 && (
|
||||
<span>
|
||||
<Button onClick={() => this.handleDeleteClick()}>删除</Button>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<StandardTable
|
||||
selectedRows={selectedRows}
|
||||
data={data}
|
||||
columns={this.columns}
|
||||
onSelectRow={this.handleSelectRows}
|
||||
onChange={this.handleStandardTableChange}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
<CreateForm {...parentMethods} modalVisible={modalVisible} />
|
||||
{updateFormValues && Object.keys(updateFormValues).length ? (
|
||||
<UpdateForm
|
||||
{...updateMethods}
|
||||
updateModalVisible={updateModalVisible}
|
||||
values={updateFormValues}
|
||||
/>
|
||||
) : null}
|
||||
<Drawer title={editingIndex.index}
|
||||
visible={drawerVisible}
|
||||
onClose={()=>{
|
||||
this.setState({
|
||||
drawerVisible: false,
|
||||
});
|
||||
}}
|
||||
width={640}
|
||||
>
|
||||
<Tabs defaultActiveKey="1" onChange={()=>{}}>
|
||||
<TabPane tab="Summary" key="1">
|
||||
<Descriptions title="General" column={2}>
|
||||
<Descriptions.Item label="Health">green</Descriptions.Item>
|
||||
<Descriptions.Item label="Status">open</Descriptions.Item>
|
||||
<Descriptions.Item label="Primaries">1</Descriptions.Item>
|
||||
<Descriptions.Item label="Replicas">0</Descriptions.Item>
|
||||
<Descriptions.Item label="Docs Count">5</Descriptions.Item>
|
||||
<Descriptions.Item label="Docs Deleted">0</Descriptions.Item>
|
||||
<Descriptions.Item label="Storage Size">115.3kb</Descriptions.Item>
|
||||
<Descriptions.Item label="Primary Storage Size"></Descriptions.Item>
|
||||
<Descriptions.Item label="Alias">
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</TabPane>
|
||||
<TabPane tab="Mappings" key="2">
|
||||
<JSONWrapper>
|
||||
<JSONPretty json={JSON.parse(`{
|
||||
"mappings": {
|
||||
"_doc": {
|
||||
"dynamic": "strict",
|
||||
"_meta": {
|
||||
"migrationMappingPropertyHashes": {
|
||||
"migrationVersion": "4a1746014a75ade3a714e1db5763276f",
|
||||
"originId": "2f4316de49999235636386fe51dc06c1",
|
||||
"task": "235412e52d09e7165fac8a67a43ad6b4",
|
||||
"updated_at": "00da57df13e94e9d98437d13ace4bfe0",
|
||||
"references": "7997cf5a56cc02bdc9c93361bde732b0",
|
||||
"namespace": "2f4316de49999235636386fe51dc06c1",
|
||||
"type": "2f4316de49999235636386fe51dc06c1",
|
||||
"namespaces": "2f4316de49999235636386fe51dc06c1"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"migrationVersion": {
|
||||
"dynamic": "true",
|
||||
"properties": {
|
||||
"task": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"namespace": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"namespaces": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"originId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"references": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"name": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"type": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"task": {
|
||||
"properties": {
|
||||
"attempts": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ownerId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"params": {
|
||||
"type": "text"
|
||||
},
|
||||
"retryAt": {
|
||||
"type": "date"
|
||||
},
|
||||
"runAt": {
|
||||
"type": "date"
|
||||
},
|
||||
"schedule": {
|
||||
"properties": {
|
||||
"interval": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scheduledAt": {
|
||||
"type": "date"
|
||||
},
|
||||
"scope": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"startedAt": {
|
||||
"type": "date"
|
||||
},
|
||||
"state": {
|
||||
"type": "text"
|
||||
},
|
||||
"status": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"taskType": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"user": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "date"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
`)} theme={{
|
||||
background: '#F5F7FA',
|
||||
brace: '#343741',
|
||||
keyQuotes: '#343741',
|
||||
valueQuotes: '#343741',
|
||||
colon: '#343741',
|
||||
comma: '#343741',
|
||||
key: '#343741',
|
||||
value: {
|
||||
string: '#343741',
|
||||
null: '#343741',
|
||||
number: '#343741',
|
||||
boolean: '#343741',
|
||||
},
|
||||
bracket: '#343741',
|
||||
}} /></JSONWrapper>
|
||||
</TabPane>
|
||||
<TabPane tab="Stats" key="3">
|
||||
Content of Tab Pane 3
|
||||
</TabPane>
|
||||
<TabPane tab="Edit settings" key="4">
|
||||
Content of Tab Pane 3
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
<div style={{position:'absolute', bottom: 10}}>
|
||||
<Dropdown
|
||||
placement="topLeft"
|
||||
overlay={(
|
||||
<Menu onClick={()=>{}}>
|
||||
<Menu.Item key="1">
|
||||
<Icon type="delete" />
|
||||
Delete
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2">
|
||||
<Icon type="edit" />
|
||||
Edit
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3">
|
||||
<Icon type="close" />
|
||||
Close
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
)}>
|
||||
<Button type="primary">
|
||||
Manage <Icon type="up" />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</Drawer>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Index;
|
|
@ -1,141 +0,0 @@
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'dva';
|
||||
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
|
||||
import { Col, Form, Row,Select, Input, Card,Icon,List, Descriptions } from 'antd';
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
@Form.create()
|
||||
class Query extends React.Component {
|
||||
state={
|
||||
bodyDisplay: 'none',
|
||||
data: [{
|
||||
index: 'blogs-001',
|
||||
id: 'dpOsA3YBCjFOm54VZoNF',
|
||||
source: `{
|
||||
"title" : "elastic search test title",
|
||||
"content": "如默认结构不满足需求,可以自定义该模板,但是自定义模板时必须包含各个 dom 节点的 class,样式可以自定义。",
|
||||
"created_at" : "2020-11-23"
|
||||
}`
|
||||
},
|
||||
{
|
||||
index: 'blogs-002',
|
||||
id: "dpOsA3YBCjFOm54VZoNB",
|
||||
source: `{
|
||||
"title" : "elastic search test title",
|
||||
"created_at" : "2020-11-23",
|
||||
"content": "如默认结构不满足需求,可以自定义该模板,但是自定义模板时必须包含各个 dom 节点的 class,样式可以自定义。"
|
||||
}`
|
||||
},
|
||||
{
|
||||
index: 'blogs-002',
|
||||
id: "dpOsA3YBCjFOm54VZoNC",
|
||||
source: `{
|
||||
"title" : "elastic search test title",
|
||||
"created_at" : "2020-11-23",
|
||||
"content":"如默认结构不满足需求,可以自定义该模板,但是自定义模板时必须包含各个 dom 节点的 class,样式可以自定义。"
|
||||
}`
|
||||
},
|
||||
{
|
||||
index: 'blogs-001',
|
||||
id:"dpOsA3YBCjFOm54VZoNG",
|
||||
source: `{
|
||||
"title" : "elastic search test title",
|
||||
"content":"如默认结构不满足需求,可以自定义该模板,但是自定义模板时必须包含各个 dom 节点的 class,样式可以自定义。",
|
||||
"created_at" : "2020-11-23"
|
||||
}`
|
||||
}, {
|
||||
index: 'blogs-001',
|
||||
id:"dpOsA3YBCjFOm54VZoNG",
|
||||
source: `{
|
||||
"title" : "elastic search test title",
|
||||
"content":"如默认结构不满足需求,可以自定义该模板,但是自定义模板时必须包含各个 dom 节点的 class,样式可以自定义。",
|
||||
"created_at" : "2020-11-23"
|
||||
}`
|
||||
}]
|
||||
}
|
||||
|
||||
render(){
|
||||
// const {getFieldDecorator} = this.props.form;
|
||||
return (
|
||||
<div>
|
||||
<Card>
|
||||
<Row gutter={[16, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
|
||||
<Col span={20}>
|
||||
<Input.Group compact>
|
||||
<Select
|
||||
defaultValue="GET"
|
||||
style={{ width: 80 }}
|
||||
>
|
||||
<Option value="GET">GET</Option>
|
||||
<Option value="POST">POST</Option>
|
||||
<Option value="PUT">PUT</Option>
|
||||
</Select>
|
||||
<Input.Search
|
||||
style={{width:"80%"}}
|
||||
placeholder="input query url"
|
||||
enterButton="execute"
|
||||
onSearch={value => console.log(value)}
|
||||
/>
|
||||
</Input.Group>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<a style={{marginTop:5,display:'block'}} onClick={(e)=>{
|
||||
this.setState((preState)=>{
|
||||
if(preState.bodyDisplay == 'none') {
|
||||
return {
|
||||
bodyDisplay: 'block',
|
||||
};
|
||||
}else{
|
||||
return {
|
||||
bodyDisplay: 'none'
|
||||
};
|
||||
}
|
||||
});
|
||||
}}>{this.state.bodyDisplay == 'none' ? '展开':'收起'}<Icon type="down" /></a>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{display: this.state.bodyDisplay}} gutter={[16, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
|
||||
<Col span={20}>
|
||||
<Input.TextArea placeholder="query body" rows={8}/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<List
|
||||
grid={{ gutter: 16, column: 2}}
|
||||
dataSource={this.state.data}
|
||||
pagination={{
|
||||
onChange: page => {
|
||||
console.log(page);
|
||||
},
|
||||
pageSize: 4,
|
||||
total: 50
|
||||
}}
|
||||
renderItem={item => (
|
||||
<List.Item>
|
||||
<Card title={`${item.index} ${item.id}`}
|
||||
extra={<a onClick={()=>{}}>More</a>}
|
||||
actions={[
|
||||
<Icon type="edit" key="edit" onClick={(e)=>{}} />,
|
||||
<Icon type="delete" key="delete" />,
|
||||
]}>
|
||||
<Descriptions bordered column={1}>
|
||||
{/* <Descriptions.Item label="ID">
|
||||
{item.id}
|
||||
</Descriptions.Item> */}
|
||||
<Descriptions.Item label="Source">
|
||||
{item.source}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</Card>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Query;
|
|
@ -0,0 +1,208 @@
|
|||
import {getDocList, saveDoc, deleteDoc, addDoc} from '@/services/doc';
|
||||
import { message } from 'antd';
|
||||
|
||||
function encodeObjectField(doc){
|
||||
//let rawData = {};
|
||||
for(let key of Object.keys(doc)){
|
||||
if(typeof doc[key] == 'object'){
|
||||
// let docId = doc['id'];
|
||||
// !rawData[docId] && (rawData[docId] = {});
|
||||
// rawData[docId][key] = doc[key];
|
||||
doc[key] = JSON.stringify(doc[key]);
|
||||
}
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
function decodeObjectField(doc){
|
||||
for(let key of Object.keys(doc)){
|
||||
if(['[', '{'].includes(doc[key][0])){
|
||||
try{
|
||||
doc[key] = JSON.parse(doc[key])
|
||||
}catch(e){
|
||||
message.warn(key +': json format error');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
export default {
|
||||
namespace: "document",
|
||||
state: {
|
||||
index: '',
|
||||
editingKey: '',
|
||||
isLoading: false,
|
||||
},
|
||||
effects: {
|
||||
*fetchDocList({payload}, {call, put}){
|
||||
yield put({
|
||||
type: 'saveData',
|
||||
payload: {
|
||||
isLoading: true,
|
||||
}
|
||||
});
|
||||
let res = yield call(getDocList, payload);
|
||||
if(res.errno != "0"){
|
||||
message.warn("加载数据失败")
|
||||
return
|
||||
}
|
||||
let indices = [];
|
||||
if(res.payload.data && res.payload.data.length > 0){
|
||||
for(let doc of res.payload.data){
|
||||
if(!indices.includes(doc._index)){
|
||||
indices.push(doc._index);
|
||||
}
|
||||
encodeObjectField(doc);
|
||||
}
|
||||
}
|
||||
yield put({
|
||||
type: 'saveData',
|
||||
payload: {
|
||||
pageIndex: payload.pageIndex,
|
||||
pageSize: payload.pageSize,
|
||||
isLoading: false,
|
||||
index: payload.index,
|
||||
indices,
|
||||
cluster: payload.cluster || '',
|
||||
filter: payload.filter || '',
|
||||
...res.payload,
|
||||
}
|
||||
})
|
||||
},
|
||||
*saveDocItem({payload}, {call, put, select}){
|
||||
yield put({
|
||||
type: 'saveData',
|
||||
payload: {
|
||||
isLoading: true,
|
||||
}
|
||||
});
|
||||
let doc = payload.data;
|
||||
//let {rawData} = yield select(state => state.document);
|
||||
if(decodeObjectField(doc) === false){
|
||||
return;
|
||||
}
|
||||
let res = yield call(saveDoc, payload);
|
||||
if(res.errno != "0"){
|
||||
message.warn("保存数据失败")
|
||||
return
|
||||
}
|
||||
encodeObjectField(doc);
|
||||
yield put({
|
||||
type: '_saveDocItem',
|
||||
payload: {
|
||||
docItem: payload.data,
|
||||
extra: {
|
||||
editingKey: '',
|
||||
isLoading: false,
|
||||
_index: ''
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
*deleteDocItem({payload}, {call, put}){
|
||||
yield put({
|
||||
type: 'saveData',
|
||||
payload: {
|
||||
isLoading: true,
|
||||
}
|
||||
});
|
||||
let res = yield call(deleteDoc, payload);
|
||||
if(res.errno != "0"){
|
||||
message.warn("删除数据失败")
|
||||
return
|
||||
}
|
||||
yield put({
|
||||
type: '_deleteDocItem',
|
||||
payload: {
|
||||
docItem: payload.data,
|
||||
extra: {
|
||||
isLoading: false,
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
*addDocItem({payload},{call, put}){
|
||||
yield put({
|
||||
type: 'saveData',
|
||||
payload: {
|
||||
isLoading: true,
|
||||
}
|
||||
});
|
||||
if(decodeObjectField(payload.data) === false){
|
||||
return;
|
||||
}
|
||||
let res = yield call(addDoc, payload);
|
||||
if(res.errno != "0"){
|
||||
message.warn("添加文档失败")
|
||||
return
|
||||
}
|
||||
encodeObjectField(res.payload);
|
||||
yield put({
|
||||
type: '_addNew',
|
||||
payload: {
|
||||
docItem: res.payload,
|
||||
extra: {
|
||||
isLoading: false,
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
reducers: {
|
||||
saveData(state, {payload}){
|
||||
return {
|
||||
...state,
|
||||
...payload,
|
||||
}
|
||||
},
|
||||
_saveDocItem(state, {payload}){
|
||||
let idx = state.data.findIndex((item) => {
|
||||
return item.id == payload.docItem.id;
|
||||
});
|
||||
idx > -1 && (state.data[idx] = {
|
||||
...state.data[idx],
|
||||
...payload.docItem,
|
||||
})
|
||||
|
||||
return {
|
||||
...state,
|
||||
...payload.extra,
|
||||
};
|
||||
},
|
||||
_deleteDocItem(state, {payload}){
|
||||
let idx = state.data.findIndex((item) => {
|
||||
return item.id == payload.docItem.id;
|
||||
});
|
||||
state.data.splice(idx, 1);
|
||||
return {
|
||||
...state,
|
||||
...payload.extra
|
||||
};
|
||||
},
|
||||
_addNew(state, {payload}){
|
||||
if(payload.extra && payload.extra.isAddNew){
|
||||
state.data.unshift(payload.docItem)
|
||||
return {
|
||||
...state,
|
||||
...payload.extra,
|
||||
}
|
||||
}else{
|
||||
state.data[0] = payload.docItem;
|
||||
return {
|
||||
...state,
|
||||
...payload.extra
|
||||
}
|
||||
}
|
||||
},
|
||||
cancelNew(state,{payload}){
|
||||
state.data.shift()
|
||||
return {
|
||||
...state,
|
||||
isAddNew: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ const UpdateForm = Form.create()(props => {
|
|||
form.validateFields((err, fieldsValue) => {
|
||||
if (err) return;
|
||||
form.resetFields();
|
||||
let upVals = Object.assign(values, fieldsValue);
|
||||
let upVals = Object.assign(_.cloneDeep(values), fieldsValue);
|
||||
handleUpdate(upVals);
|
||||
});
|
||||
};
|
||||
|
@ -69,33 +69,22 @@ class Pro extends React.Component {
|
|||
super(props);
|
||||
this.handleUpdate = this.handleUpdate.bind(this);
|
||||
}
|
||||
state = {
|
||||
updateFormValues: null,
|
||||
currentFormOp: null,
|
||||
data: [],
|
||||
search: {
|
||||
size: 6,
|
||||
name: "",
|
||||
tags: "",
|
||||
pageIndex: 1,
|
||||
}
|
||||
}
|
||||
componentDidMount(){
|
||||
this.fetchData();
|
||||
const {size} = this.props.dict.search;
|
||||
this.fetchData({
|
||||
from: 0,
|
||||
size: size,
|
||||
});
|
||||
}
|
||||
|
||||
handleReset = ()=>{
|
||||
const {form} = this.props;
|
||||
form.resetFields();
|
||||
this.setState({
|
||||
search: {
|
||||
size: 6,
|
||||
name: "",
|
||||
tags: "",
|
||||
pageIndex: 1,
|
||||
}
|
||||
},()=>{
|
||||
this.fetchData();
|
||||
this.fetchData({
|
||||
from: 0,
|
||||
size: this.props.dict.search.size,
|
||||
name: '',
|
||||
tags: ''
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -104,14 +93,12 @@ class Pro extends React.Component {
|
|||
let me = this;
|
||||
form.validateFields((err, fieldsValue) => {
|
||||
if (err) return;
|
||||
me.setState({search:{
|
||||
...me.state.search,
|
||||
pageIndex: 1,
|
||||
me.fetchData({
|
||||
form: 0,
|
||||
size: me.props.dict.search.size,
|
||||
name: fieldsValue.name,
|
||||
tags: fieldsValue.tags.join(',')
|
||||
}},()=>{
|
||||
me.fetchData();
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -161,18 +148,24 @@ class Pro extends React.Component {
|
|||
);
|
||||
}
|
||||
handleNewClick = () => {
|
||||
this.setState({
|
||||
currentFormOp: 'NEW',
|
||||
updateFormValues: {},
|
||||
formTitle: '添加词典'
|
||||
const {dispatch} = this.props;
|
||||
dispatch({
|
||||
type: 'dict/saveData',
|
||||
payload: {
|
||||
currentFormOp: 'NEW',
|
||||
updateFormValues: {},
|
||||
formTitle: '添加词典'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
handleDelete = (item) =>{
|
||||
const {dispatch} = this.props;
|
||||
const {dispatch, dict} = this.props;
|
||||
const search = dict.search;
|
||||
const me = this;
|
||||
Modal.confirm({
|
||||
title: '删除Pipeline',
|
||||
content: '确定删除该Pipeline吗?',
|
||||
title: '删除词典',
|
||||
content: '确定删除该词典吗?',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
|
@ -188,15 +181,19 @@ class Pro extends React.Component {
|
|||
}
|
||||
|
||||
handleModifyClick = (item)=>{
|
||||
this.setState({
|
||||
updateFormValues: item,
|
||||
formTitle: '修改词典',
|
||||
currentFormOp: 'UPDATE',
|
||||
})
|
||||
const {dispatch} = this.props;
|
||||
dispatch({
|
||||
type: 'dict/saveData',
|
||||
payload: {
|
||||
updateFormValues: item,
|
||||
formTitle: '修改词典',
|
||||
currentFormOp: 'UPDATE',
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handleUpdate(values){
|
||||
let {currentFormOp, data} = this.state;
|
||||
let {currentFormOp} = this.props.dict;
|
||||
const {dispatch} = this.props;
|
||||
let me = this;
|
||||
switch(currentFormOp){
|
||||
|
@ -204,69 +201,51 @@ class Pro extends React.Component {
|
|||
dispatch({
|
||||
type: 'dict/addDictItem',
|
||||
payload: values,
|
||||
callback: ()=>{
|
||||
me.setState({
|
||||
updateFormValues: null,
|
||||
currentFormOp: null
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "UPDATE":
|
||||
dispatch({
|
||||
type: 'dict/updateDictItem',
|
||||
payload: values,
|
||||
callback: ()=>{
|
||||
me.setState({
|
||||
updateFormValues: null,
|
||||
currentFormOp: null
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fetchData = ()=>{
|
||||
fetchData = (params)=>{
|
||||
const {dispatch} = this.props;
|
||||
let {size, pageIndex} = this.state.search;
|
||||
let me = this;
|
||||
dispatch({
|
||||
type: 'dict/fetchDictList',
|
||||
payload: {
|
||||
from: (pageIndex - 1) * size,
|
||||
...this.state.search
|
||||
},
|
||||
callback: ()=>{
|
||||
}
|
||||
payload: params
|
||||
});
|
||||
}
|
||||
|
||||
handlePageChange = (p)=>{
|
||||
this.setState({
|
||||
search: {
|
||||
...this.state.search,
|
||||
pageIndex: p,
|
||||
}
|
||||
},()=>{
|
||||
this.fetchData();
|
||||
})
|
||||
let search = this.props.dict.search;
|
||||
|
||||
this.fetchData({
|
||||
...search,
|
||||
from: (p-1) * search.size,
|
||||
pageIndex: p,
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
let data = this.props.dict ? this.props.dict.dictList : [];
|
||||
let total = this.props.dict ? this.props.dict.total: 0;
|
||||
let updateFormValues = this.state.updateFormValues;
|
||||
let size = this.state.search.size;
|
||||
//console.log('render');
|
||||
let {dictList, search, updateFormValues, total, formTitle} = this.props.dict;
|
||||
let {pageIndex, size} = search;
|
||||
const {dispatch} = this.props;
|
||||
const updateMethods = {
|
||||
handleUpdate: this.handleUpdate,
|
||||
handleUpdateModalVisible: ()=>{
|
||||
this.setState({
|
||||
updateFormValues: null,
|
||||
currentFormOp: null,
|
||||
})
|
||||
dispatch({
|
||||
type:'dict/saveData',
|
||||
payload: {
|
||||
updateFormValues: null,
|
||||
currentFormOp: null,
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
console.log('render');
|
||||
return (
|
||||
<div>
|
||||
<Card bordered={false} bodyStyle={{paddingBottom:0}} >
|
||||
|
@ -278,11 +257,11 @@ class Pro extends React.Component {
|
|||
bordered={false}>
|
||||
<List
|
||||
className="dic-list"
|
||||
dataSource={data}
|
||||
dataSource={dictList}
|
||||
pagination={{
|
||||
pageSize: size,
|
||||
total: total,
|
||||
current: this.state.search.pageIndex,
|
||||
current: pageIndex,
|
||||
onChange: this.handlePageChange
|
||||
}}
|
||||
grid={{
|
||||
|
@ -320,7 +299,7 @@ class Pro extends React.Component {
|
|||
</Card>
|
||||
{updateFormValues ? (
|
||||
<UpdateForm
|
||||
title={this.state.formTitle}
|
||||
title={formTitle}
|
||||
{...updateMethods}
|
||||
values={updateFormValues}
|
||||
/>
|
||||
|
|
|
@ -50,9 +50,18 @@ export default {
|
|||
namespace: 'dict',
|
||||
|
||||
state: {
|
||||
updateFormValues: null,
|
||||
currentFormOp: null,
|
||||
formTitle: '',
|
||||
search: {
|
||||
size: 6,
|
||||
name: "",
|
||||
tags: "",
|
||||
pageIndex: 1,
|
||||
}
|
||||
},
|
||||
effects: {
|
||||
*fetchDictList({payload, callback}, {call, put}){
|
||||
*fetchDictList({payload}, {call, put}){
|
||||
const resp = yield call(getDictList, payload);
|
||||
if(resp.errno != "0" || !resp.data.Result){
|
||||
return
|
||||
|
@ -61,21 +70,26 @@ export default {
|
|||
item.content = utf8.decode(atob(item.content))
|
||||
return item;
|
||||
})
|
||||
let search = {name:'', tags: ''};
|
||||
payload.pageIndex = payload.from / payload.size + 1;
|
||||
search = Object.assign(search, payload);
|
||||
|
||||
yield put({
|
||||
type: 'saveData',
|
||||
payload: {
|
||||
dictList: resp.data.Result,
|
||||
total: resp.data.Total,
|
||||
...payload,
|
||||
search: search,
|
||||
},
|
||||
});
|
||||
if(callback && typeof callback == 'function'){
|
||||
callback(resp);
|
||||
}
|
||||
//message.loading('数据加载完成', 'initdata');
|
||||
},
|
||||
*addDictItem({payload, callback}, {call, put}){
|
||||
const rel = yield call(addDict, payload);
|
||||
*addDictItem({payload}, {call, put}){
|
||||
let upVals = {
|
||||
...payload,
|
||||
}
|
||||
upVals.content = btoa(utf8.encode(upVals.content));
|
||||
const rel = yield call(addDict, upVals);
|
||||
if(rel.errno != "0"){
|
||||
message.warn('添加失败:'+ rel.errmsg)
|
||||
return
|
||||
|
@ -83,25 +97,34 @@ export default {
|
|||
rel.payload.content = utf8.decode(atob(rel.payload.content));
|
||||
yield put({
|
||||
type: 'addDict',
|
||||
payload: rel.payload,
|
||||
payload: {
|
||||
dictItem: rel.payload,
|
||||
extra: {
|
||||
updateFormValues: null,
|
||||
currentFormOp: null
|
||||
}
|
||||
}
|
||||
})
|
||||
if(callback && typeof callback == 'function'){
|
||||
callback(rel);
|
||||
}
|
||||
},
|
||||
*updateDictItem({payload, callback}, {call, put}){
|
||||
*updateDictItem({payload}, {call, put}){
|
||||
let rawContent = payload.content;
|
||||
payload.content = btoa(utf8.encode(payload.content));
|
||||
const rel = yield call(updateDict, payload);
|
||||
if(rel.errno != "0"){
|
||||
message.warn('修改:'+ rel.errmsg)
|
||||
return
|
||||
}
|
||||
payload.content = rawContent;
|
||||
yield put({
|
||||
type: 'updateDict',
|
||||
payload: payload,
|
||||
payload: {
|
||||
dictItem: payload,
|
||||
extra:{
|
||||
updateFormValues: null,
|
||||
currentFormOp: null
|
||||
}
|
||||
}
|
||||
})
|
||||
if(callback && typeof callback == 'function'){
|
||||
callback(rel);
|
||||
}
|
||||
},
|
||||
*deleteDictItem({payload}, {call, put, select}){
|
||||
let rel = yield call(deleteDict, payload);
|
||||
|
@ -112,14 +135,20 @@ export default {
|
|||
message.warn('删除失败:'+ rel.errmsg)
|
||||
return
|
||||
}
|
||||
const state = yield select(state => state.dict)
|
||||
|
||||
yield put({
|
||||
type: 'fetchDictList',
|
||||
type:'deleteDict',
|
||||
payload: {
|
||||
from: state.from,
|
||||
size: state.size,
|
||||
dictItem: payload,
|
||||
}
|
||||
})
|
||||
});
|
||||
//const search = yield select(state => state.dict.search)
|
||||
|
||||
// yield put({
|
||||
// type: 'fetchDictList',
|
||||
// payload: search,
|
||||
// })
|
||||
//yield take('fetchDictList/@@end')
|
||||
}
|
||||
},
|
||||
reducers: {
|
||||
|
@ -131,17 +160,35 @@ export default {
|
|||
},
|
||||
addDict(state, {payload}){
|
||||
let dictList = state.dictList || [];
|
||||
dictList.unshift(payload);
|
||||
dictList.unshift(payload.dictItem);
|
||||
state.dictList = dictList;
|
||||
return state;
|
||||
return {
|
||||
...state,
|
||||
...payload.extra,
|
||||
total: state.total + 1,
|
||||
};
|
||||
},
|
||||
updateDict(state, {payload}){
|
||||
let cdata = state.dictList;
|
||||
let idx = cdata.findIndex((item)=>{
|
||||
return item.id == payload.id;
|
||||
return item.id == payload.dictItem.id;
|
||||
})
|
||||
idx > -1 && (cdata[idx] = values);
|
||||
return state;
|
||||
idx > -1 && (cdata[idx] = payload.dictItem);
|
||||
return {
|
||||
...state,
|
||||
...payload.extra,
|
||||
}
|
||||
},
|
||||
deleteDict(state, {payload}){
|
||||
let cdata = state.dictList;
|
||||
let idx = cdata.findIndex((item)=>{
|
||||
return item.id == payload.dictItem.id;
|
||||
})
|
||||
idx > -1 && (state.dictList.splice(idx, 1));
|
||||
return {
|
||||
...state,
|
||||
total: state.total - 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import request from '@/utils/request';
|
||||
|
||||
export async function getDocList(params) {
|
||||
return request(`/api/doc/${params.index}`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
action: 'SEARCH',
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function saveDoc(params) {
|
||||
return request(`/api/doc/${params.index}`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
payload: params.data,
|
||||
index: params.index,
|
||||
action: 'SAVE',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteDoc(params) {
|
||||
return request(`/api/doc/${params.index}`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
index: params.index,
|
||||
action: 'DELETE',
|
||||
payload: params.data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function addDoc(params) {
|
||||
return request(`/api/doc/${params.index}`, {
|
||||
method: 'POST',
|
||||
body: {
|
||||
payload: params.data,
|
||||
index: params.index,
|
||||
action: 'ADD',
|
||||
},
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue