add global cluster select and init rebuild
This commit is contained in:
parent
9fd1d490ac
commit
e44729fcb8
2
Makefile
2
Makefile
|
@ -36,7 +36,7 @@ INFINI_BASE_FOLDER := $(OLDGOPATH)/src/infini.sh/
|
||||||
FRAMEWORK_FOLDER := $(INFINI_BASE_FOLDER)framework/
|
FRAMEWORK_FOLDER := $(INFINI_BASE_FOLDER)framework/
|
||||||
FRAMEWORK_REPO := ssh://git@git.infini.ltd:64221/infini/framework.git
|
FRAMEWORK_REPO := ssh://git@git.infini.ltd:64221/infini/framework.git
|
||||||
FRAMEWORK_BRANCH := master
|
FRAMEWORK_BRANCH := master
|
||||||
FRAMEWORK_VENDOR_FOLDER := $(CURDIR)/../vendor/
|
FRAMEWORK_VENDOR_FOLDER := $(CURDIR)/vendor/
|
||||||
FRAMEWORK_VENDOR_REPO := ssh://git@git.infini.ltd:64221/infini/framework-vendor.git
|
FRAMEWORK_VENDOR_REPO := ssh://git@git.infini.ltd:64221/infini/framework-vendor.git
|
||||||
FRAMEWORK_VENDOR_BRANCH := master
|
FRAMEWORK_VENDOR_BRANCH := master
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
package index_management
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
httprouter "infini.sh/framework/core/api/router"
|
||||||
|
"infini.sh/framework/core/elastic"
|
||||||
|
"infini.sh/framework/core/util"
|
||||||
|
"infini.sh/search-center/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (handler APIHandler) ReindexAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
|
reindexItem := &model.InfiniReindex{}
|
||||||
|
resResult := map[string]interface{}{
|
||||||
|
"errno": "0",
|
||||||
|
"errmsg": "",
|
||||||
|
"payload": nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := handler.DecodeJSON(req, reindexItem)
|
||||||
|
if err != nil {
|
||||||
|
resResult["errno"] = "E20001"
|
||||||
|
resResult["errmsg"] = err.Error()
|
||||||
|
handler.WriteJSON(w, resResult, http.StatusOK)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(reindexItem)
|
||||||
|
|
||||||
|
taskID, err := reindex(handler.Config.Elasticsearch, reindexItem)
|
||||||
|
if err != nil {
|
||||||
|
resResult["errno"] = "E20002"
|
||||||
|
resResult["errmsg"] = err.Error()
|
||||||
|
handler.WriteJSON(w, resResult, http.StatusOK)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resResult["payload"] = taskID
|
||||||
|
handler.WriteJSON(w, resResult, http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func reindex(esName string, body *model.InfiniReindex) (string, error) {
|
||||||
|
client := elastic.GetClient(esName)
|
||||||
|
esConfig := elastic.GetConfig(esName)
|
||||||
|
url := fmt.Sprintf("%s/_reindex?wait_for_completion=false", esConfig.Endpoint)
|
||||||
|
source := map[string]interface{}{
|
||||||
|
"index": body.Source.Index,
|
||||||
|
}
|
||||||
|
if body.Source.MaxDocs > 0 {
|
||||||
|
source["max_docs"] = body.Source.MaxDocs
|
||||||
|
}
|
||||||
|
if body.Source.Query != nil {
|
||||||
|
source["query"] = body.Source.Query
|
||||||
|
}
|
||||||
|
if body.Source.Sort != "" {
|
||||||
|
source["sort"] = body.Source.Sort
|
||||||
|
}
|
||||||
|
if body.Source.Source != "" {
|
||||||
|
source["_source"] = body.Source.Source
|
||||||
|
}
|
||||||
|
dest := map[string]string{
|
||||||
|
"index": body.Dest.Index,
|
||||||
|
}
|
||||||
|
if body.Dest.Pipeline != "" {
|
||||||
|
dest["pipeline"] = body.Dest.Pipeline
|
||||||
|
}
|
||||||
|
esBody := map[string]interface{}{
|
||||||
|
"source": source,
|
||||||
|
"dest": dest,
|
||||||
|
}
|
||||||
|
buf, _ := json.Marshal(esBody)
|
||||||
|
fmt.Println(string(buf))
|
||||||
|
reindexRes, err := client.Request("POST", url, buf)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
resBody := struct {
|
||||||
|
Task string `json:"task"`
|
||||||
|
}{}
|
||||||
|
err = json.Unmarshal(reindexRes.Body, &resBody)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
body.ID = util.GetUUID()
|
||||||
|
body.TaskId = resBody.Task
|
||||||
|
body.CreatedAt = time.Now()
|
||||||
|
|
||||||
|
_, err = client.Index("infinireindex", body.ID, body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return body.ID, nil
|
||||||
|
}
|
15
api/init.go
15
api/init.go
|
@ -11,13 +11,16 @@ func Init(cfg *config.AppConfig) {
|
||||||
handler := index_management.APIHandler{
|
handler := index_management.APIHandler{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
}
|
}
|
||||||
|
var pathPrefix = "/_search-center/"
|
||||||
//ui.HandleUIMethod(api.POST, "/api/get_indices",index_management.API1)
|
//ui.HandleUIMethod(api.POST, "/api/get_indices",index_management.API1)
|
||||||
ui.HandleUIMethod(api.GET, "/api/dict/_search", handler.GetDictListAction)
|
ui.HandleUIMethod(api.GET, pathPrefix+"dict/_search", handler.GetDictListAction)
|
||||||
ui.HandleUIMethod(api.POST, "/api/dict/_create", handler.CreateDictItemAction)
|
ui.HandleUIMethod(api.POST, pathPrefix+"dict/_create", handler.CreateDictItemAction)
|
||||||
//ui.HandleUIMethod(api.GET, "/api/dict/:id",handler.GetDictItemAction)
|
//ui.HandleUIMethod(api.GET, "/api/dict/:id",handler.GetDictItemAction)
|
||||||
ui.HandleUIMethod(api.DELETE, "/api/dict/:id", handler.DeleteDictItemAction)
|
ui.HandleUIMethod(api.DELETE, pathPrefix+"dict/:id", handler.DeleteDictItemAction)
|
||||||
//ui.HandleUIMethod(api.DELETE, "/api/dict/", handler.DeleteDictItemAction2)
|
//ui.HandleUIMethod(api.DELETE, "/api/dict/", handler.DeleteDictItemAction2)
|
||||||
ui.HandleUIMethod(api.POST, "/api/dict/_update", handler.UpdateDictItemAction)
|
ui.HandleUIMethod(api.POST, pathPrefix+"dict/_update", handler.UpdateDictItemAction)
|
||||||
ui.HandleUIMethod(api.POST, "/api/doc/:index", handler.HandleDocumentAction)
|
ui.HandleUIMethod(api.POST, pathPrefix+"doc/:index", handler.HandleDocumentAction)
|
||||||
ui.HandleUIMethod(api.GET, "/api/indices/_cat", handler.HandleGetIndicesAction)
|
ui.HandleUIMethod(api.GET, pathPrefix+"indices/_cat", handler.HandleGetIndicesAction)
|
||||||
|
|
||||||
|
ui.HandleUIMethod(api.POST, pathPrefix+"rebuild/_create", handler.ReindexAction)
|
||||||
}
|
}
|
||||||
|
|
1
main.go
1
main.go
|
@ -70,6 +70,7 @@ func main() {
|
||||||
|
|
||||||
}, func() {
|
}, func() {
|
||||||
orm.RegisterSchema(model.Dict{})
|
orm.RegisterSchema(model.Dict{})
|
||||||
|
orm.RegisterSchema(model.InfiniReindex{})
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type InfiniReindex struct {
|
||||||
|
ID string `json:"id" elastic_meta:"_id"`
|
||||||
|
Name string `json:"name" elastic_mapping:"name:{type:text}"`
|
||||||
|
Desc string `json:"desc" elastic_mapping:"desc:{type:text}"`
|
||||||
|
TaskId string `json:"task_id" elastic_mapping:"task_id:{type:keyword}"`
|
||||||
|
Source struct {
|
||||||
|
Index string `json:"index"`
|
||||||
|
MaxDocs int `json:"max_docs"`
|
||||||
|
Query map[string]interface{} `json:"query"`
|
||||||
|
Sort string `json:"sort"`
|
||||||
|
Source string `json:"_source"`
|
||||||
|
} `json:"source" elastic_mapping:"source:{type:object}"`
|
||||||
|
Dest struct {
|
||||||
|
Index string `json:"index"`
|
||||||
|
Pipeline string `json:"pipeline"`
|
||||||
|
} `json:"dest" elastic_mapping:"dest:{type:object}"`
|
||||||
|
|
||||||
|
CreatedAt time.Time `json:"created_at" elastic_mapping:"created_at:{type:date}"`
|
||||||
|
Status string `json:"status" elastic_mapping:"status:{type:keyword}"`
|
||||||
|
}
|
5
ui.go
5
ui.go
|
@ -2,9 +2,10 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
public "infini.sh/search-center/.public"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
public "infini.sh/search-center/.public"
|
||||||
|
|
||||||
log "github.com/cihub/seelog"
|
log "github.com/cihub/seelog"
|
||||||
"infini.sh/framework/core/api"
|
"infini.sh/framework/core/api"
|
||||||
"infini.sh/framework/core/ui"
|
"infini.sh/framework/core/ui"
|
||||||
|
@ -21,7 +22,7 @@ type UI struct {
|
||||||
|
|
||||||
func (h UI) InitUI() {
|
func (h UI) InitUI() {
|
||||||
|
|
||||||
vfs.RegisterFS(public.StaticFS{StaticFolder: h.Config.UILocalPath, TrimLeftPath: h.Config.UILocalPath , CheckLocalFirst: h.Config.UILocalEnabled, SkipVFS: !h.Config.UIVFSEnabled})
|
vfs.RegisterFS(public.StaticFS{StaticFolder: h.Config.UILocalPath, TrimLeftPath: h.Config.UILocalPath, CheckLocalFirst: h.Config.UILocalEnabled, SkipVFS: !h.Config.UIVFSEnabled})
|
||||||
|
|
||||||
ui.HandleUI("/", vfs.FileServer(vfs.VFS()))
|
ui.HandleUI("/", vfs.FileServer(vfs.VFS()))
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ export default {
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api/': {
|
'/_search-center/': {
|
||||||
target: 'http://localhost:2900',
|
target: 'http://localhost:2900',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
// pathRewrite: { '^/server': '' },
|
// pathRewrite: { '^/server': '' },
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
export const queryData = {
|
||||||
|
"errmsg": "",
|
||||||
|
"errno": "0",
|
||||||
|
"payload": {
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"_index": "infini-test",
|
||||||
|
"address": "hunan changsha",
|
||||||
|
"created_at": "2020-12-23T03:57:57.620Z",
|
||||||
|
"email": "liugq@qq.com",
|
||||||
|
"hobbies": "[\"basketball\",\"pingpan\"]",
|
||||||
|
"id": "jc6_jXYBKoaaPbVfj_8W",
|
||||||
|
"name": "liugq国家"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_index": "infini-test",
|
||||||
|
"address": "hunan changsha",
|
||||||
|
"created_at": "2020-12-23T03:57:57.620Z",
|
||||||
|
"email": "786027438@qq.com",
|
||||||
|
"hobbies": "[\"test5\"]",
|
||||||
|
"id": "bvhm18dath2d6oa9046g",
|
||||||
|
"name": "hello4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_index": "infini-test",
|
||||||
|
"address": "hunan changsha",
|
||||||
|
"created_at": "2020-12-23T03:57:57.620Z",
|
||||||
|
"email": "786027438@qq.com",
|
||||||
|
"hobbies": "[\"test2\"]",
|
||||||
|
"id": "bvhlv6dath2d6oa9045g",
|
||||||
|
"name": "test 词典"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_index": "infini-test",
|
||||||
|
"address": "hunan changsha",
|
||||||
|
"created_at": "2020-12-23T03:57:57.620Z",
|
||||||
|
"email": "786027438@qq.com",
|
||||||
|
"hobbies": "[\"test1\"]",
|
||||||
|
"id": "bvhltpdath2d6oa90450",
|
||||||
|
"name": "liugqy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_index": "infini-test",
|
||||||
|
"address": "hunan zhuzhou",
|
||||||
|
"created_at": "2020-12-23T03:59:57.620Z",
|
||||||
|
"email": "cincky@qq.com",
|
||||||
|
"hobbies": "[\"basketball\",\"badminton1\"]",
|
||||||
|
"id": "js7EjXYBKoaaPbVfvf-c",
|
||||||
|
"name": "cincky"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_index": "infini-test",
|
||||||
|
"address": "湖北武汉2",
|
||||||
|
"created_at": "2020-12-23T03:57:57.620Z",
|
||||||
|
"email": "786027438@qq.com",
|
||||||
|
"hobbies": [
|
||||||
|
"test3"
|
||||||
|
],
|
||||||
|
"id": "bvi5ellath2e0ukbq5e0",
|
||||||
|
"name": "武汉test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_index": "infini-test",
|
||||||
|
"address": "hunan changsha",
|
||||||
|
"created_at": "2020-12-23T03:57:57.620Z",
|
||||||
|
"email": "786027438@qq.com",
|
||||||
|
"hobbies": [
|
||||||
|
"test3"
|
||||||
|
],
|
||||||
|
"id": "bvia41lath2eneoeeij0",
|
||||||
|
"name": "铁路测试词典"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_index": "infini-test",
|
||||||
|
"address": "beijing",
|
||||||
|
"created_at": "2020-12-23T03:57:57.620Z",
|
||||||
|
"email": "786027438@qq.com",
|
||||||
|
"hobbies": [
|
||||||
|
"basketball1",
|
||||||
|
"badminton"
|
||||||
|
],
|
||||||
|
"id": "bvia4ctath2eneoeeijg",
|
||||||
|
"name": "北京"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_index": "infini-test",
|
||||||
|
"address": "湖北武汉",
|
||||||
|
"created_at": "2020-12-23T03:57:57.620Z",
|
||||||
|
"email": "786027438@qq.com",
|
||||||
|
"hobbies": [
|
||||||
|
"test4"
|
||||||
|
],
|
||||||
|
"id": "bvi5omtath2e0ukbq5eg",
|
||||||
|
"name": "武汉2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_index": "infini-test",
|
||||||
|
"address": "hunan changsha1",
|
||||||
|
"created_at": "2020-12-23T03:57:57.620Z",
|
||||||
|
"email": "786027438@qq.com",
|
||||||
|
"hobbies": [
|
||||||
|
"test3"
|
||||||
|
],
|
||||||
|
"id": "bvhm0d5ath2d6oa90460",
|
||||||
|
"name": "hello2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mappings": {
|
||||||
|
"infini-test": {
|
||||||
|
"mappings": {
|
||||||
|
"dynamic_templates": [
|
||||||
|
{
|
||||||
|
"strings": {
|
||||||
|
"mapping": {
|
||||||
|
"ignore_above": 256,
|
||||||
|
"type": "keyword"
|
||||||
|
},
|
||||||
|
"match_mapping_type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"address": {
|
||||||
|
"fields": {
|
||||||
|
"keyword": {
|
||||||
|
"ignore_above": 256,
|
||||||
|
"type": "keyword"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"age": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"type": "keyword"
|
||||||
|
},
|
||||||
|
"hobbies": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"ignore_above": 256,
|
||||||
|
"type": "keyword"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"total": {
|
||||||
|
"relation": "eq",
|
||||||
|
"value": 11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
import {queryData} from './data/doc';
|
||||||
|
|
||||||
|
function getUUID(len){
|
||||||
|
len = len || 20;
|
||||||
|
let chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
var maxPos = chars.length;
|
||||||
|
var uuid = '';
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
uuid += chars.charAt(Math.floor(Math.random() * maxPos));
|
||||||
|
}
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
'post /_search-center/doc/:index': function(req, res){
|
||||||
|
switch(req.body.action){
|
||||||
|
case 'SAVE':
|
||||||
|
res.send({
|
||||||
|
errno: "0",
|
||||||
|
errmsg: ""
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'ADD':
|
||||||
|
res.send({
|
||||||
|
errno: "0",
|
||||||
|
errmsg: "",
|
||||||
|
payload: {
|
||||||
|
...req.body.payload,
|
||||||
|
id: getUUID(),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'DELETE':
|
||||||
|
res.send({
|
||||||
|
errno: "0"
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
res.send(queryData)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'get /_search-center/indices/_cat': function(req, res){
|
||||||
|
res.send({
|
||||||
|
errno: "0",
|
||||||
|
payload: ["infini-test"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,6 +42,7 @@
|
||||||
"react-dom": "^16.5.1",
|
"react-dom": "^16.5.1",
|
||||||
"react-fittext": "^1.0.0",
|
"react-fittext": "^1.0.0",
|
||||||
"react-highlight-words": "^0.16.0",
|
"react-highlight-words": "^0.16.0",
|
||||||
|
"react-infinite-scroller": "^1.2.4",
|
||||||
"react-json-prettify": "^0.2.0",
|
"react-json-prettify": "^0.2.0",
|
||||||
"react-json-view": "^1.19.1",
|
"react-json-view": "^1.19.1",
|
||||||
"react-router-dom": "^4.3.1",
|
"react-router-dom": "^4.3.1",
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
import { Button, Dropdown, List, Spin, message, Icon } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import InfiniteScroll from 'react-infinite-scroller';
|
||||||
|
import styles from './DropdownSelect.less';
|
||||||
|
|
||||||
|
class DropdownSelect extends React.Component{
|
||||||
|
state={
|
||||||
|
value: this.props.defaultValue,
|
||||||
|
data: this.props.data || [],
|
||||||
|
loading: false,
|
||||||
|
hasMore: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleItemClick = (item)=>{
|
||||||
|
let preValue = this.state.value;
|
||||||
|
this.setState({
|
||||||
|
value: item,
|
||||||
|
},()=>{
|
||||||
|
let onChange = this.props.onChange;
|
||||||
|
if(preValue != item && onChange && typeof onChange == 'function'){
|
||||||
|
onChange(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount(){
|
||||||
|
let data = [];
|
||||||
|
for(let i = 1; i<=28; i++){
|
||||||
|
data.push('cluster'+i)
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
data: data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fetchData = ()=>{
|
||||||
|
let me = this;
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => {
|
||||||
|
let start = me.state.data.length;
|
||||||
|
let data =[]
|
||||||
|
for(let i = start + 1; i<start+11; i++){
|
||||||
|
data.push('cluster'+i)
|
||||||
|
}
|
||||||
|
resolve(data)
|
||||||
|
}, 2000)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleInfiniteOnLoad = (page) => {
|
||||||
|
let { data } = this.state;
|
||||||
|
this.setState({
|
||||||
|
loading: true,
|
||||||
|
})
|
||||||
|
if (data.length > 50) {
|
||||||
|
message.warning('No more data');
|
||||||
|
this.setState({
|
||||||
|
hasMore: false,
|
||||||
|
loading: false,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.fetchData().then((newdata)=>{
|
||||||
|
data = data.concat(newdata);
|
||||||
|
this.setState({
|
||||||
|
data,
|
||||||
|
loading: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render(){
|
||||||
|
let me = this;
|
||||||
|
const menu = (<div className={styles.dropmenu}>
|
||||||
|
<div className={styles.infiniteContainer}>
|
||||||
|
<InfiniteScroll
|
||||||
|
initialLoad={false}
|
||||||
|
loadMore={this.handleInfiniteOnLoad}
|
||||||
|
hasMore={!this.state.loading && this.state.hasMore}
|
||||||
|
useWindow={false}
|
||||||
|
>
|
||||||
|
<List
|
||||||
|
grid={{
|
||||||
|
gutter: 8,
|
||||||
|
column: 4,
|
||||||
|
}}
|
||||||
|
dataSource={this.state.data}
|
||||||
|
renderItem={item => (
|
||||||
|
<List.Item key={item}>
|
||||||
|
<Button onClick={()=>{this.handleItemClick(item)}} className={styles.btnitem}>{item}</Button>
|
||||||
|
</List.Item>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{this.state.loading && this.state.hasMore && (
|
||||||
|
<div className={styles.loadingContainer}>
|
||||||
|
<Spin />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</List>
|
||||||
|
</InfiniteScroll>
|
||||||
|
</div>
|
||||||
|
{!this.state.loading && this.state.hasMore && (
|
||||||
|
<div style={{textAlign:'center', marginTop: 10, color:'#ccc'}}>
|
||||||
|
pull load more
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>);
|
||||||
|
return(
|
||||||
|
<Dropdown overlay={menu} placement="bottomLeft">
|
||||||
|
<Button className={styles['btn-ds']}>{this.state.value} <Icon style={{float:'right', marginTop:3}} type="caret-down"/></Button>
|
||||||
|
</Dropdown>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DropdownSelect;
|
|
@ -0,0 +1,42 @@
|
||||||
|
.btn-ds, .btn-ds:hover{
|
||||||
|
min-width: 150px;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid #333;
|
||||||
|
text-align: left;
|
||||||
|
transition: all .3s cubic-bezier(.645,.045,.355,1);
|
||||||
|
border-radius: 0;
|
||||||
|
margin-left: 15px;
|
||||||
|
position: relative;
|
||||||
|
bottom: 8px;
|
||||||
|
span{
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropmenu{
|
||||||
|
box-shadow: 0 0 15px 0 rgba(0, 0, 0, .15);
|
||||||
|
padding: 20px;
|
||||||
|
width: 500px;
|
||||||
|
background: #fff;
|
||||||
|
.item{
|
||||||
|
display: block;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.btnitem{
|
||||||
|
border-radius: 0px;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.infiniteContainer {
|
||||||
|
overflow: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
.loadingContainer {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 40px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import Link from 'umi/link';
|
||||||
import Debounce from 'lodash-decorators/debounce';
|
import Debounce from 'lodash-decorators/debounce';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import RightContent from './RightContent';
|
import RightContent from './RightContent';
|
||||||
|
import DropdownSelect from './DropdownSelect'
|
||||||
|
|
||||||
export default class GlobalHeader extends PureComponent {
|
export default class GlobalHeader extends PureComponent {
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
@ -36,6 +37,9 @@ export default class GlobalHeader extends PureComponent {
|
||||||
type={collapsed ? 'menu-unfold' : 'menu-fold'}
|
type={collapsed ? 'menu-unfold' : 'menu-fold'}
|
||||||
onClick={this.toggle}
|
onClick={this.toggle}
|
||||||
/>
|
/>
|
||||||
|
<DropdownSelect defaultValue="Select cluster"
|
||||||
|
onChange={(item)=>{}}
|
||||||
|
data={['cluster1', 'cluster2','cluster3', 'cluster4','cluster5', 'cluster6']}/>
|
||||||
<RightContent {...this.props} />
|
<RightContent {...this.props} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {Input, Menu, Dropdown} from 'antd';
|
||||||
|
|
||||||
|
class InputSelect extends React.Component{
|
||||||
|
componentDidMount(){
|
||||||
|
}
|
||||||
|
constructor(props){
|
||||||
|
// console.log('new: '+ props.id)
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
value: props.defaultValue || props.value,
|
||||||
|
originData: props.data || [],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick = ({ key }) => {
|
||||||
|
this.setState({
|
||||||
|
value: key,
|
||||||
|
})
|
||||||
|
this.triggerChange(key)
|
||||||
|
}
|
||||||
|
triggerChange = (val)=>{
|
||||||
|
let {onChange} = this.props;
|
||||||
|
if(onChange && typeof onChange == 'function'){
|
||||||
|
onChange(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleChange = (ev) => {
|
||||||
|
let val = ev.target.value;
|
||||||
|
let filterData = this.state.originData.slice();
|
||||||
|
if(val != ""){
|
||||||
|
filterData = filterData.filter(v=>v.value.includes(val))
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
value: val,
|
||||||
|
data: filterData
|
||||||
|
})
|
||||||
|
this.triggerChange(val);
|
||||||
|
}
|
||||||
|
render(){
|
||||||
|
let {id, data, onChange, value, ...restProps} = this.props;
|
||||||
|
let filterData = this.state.data || data || [];
|
||||||
|
return (
|
||||||
|
<Dropdown overlay={
|
||||||
|
<Menu onClick={this.onClick} style={{maxHeight:'350px', overflow:"scroll"}}>
|
||||||
|
{filterData.map(op =>(
|
||||||
|
<Menu.Item key={op.value}>{op.label}</Menu.Item>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
|
} trigger={['focus']}>
|
||||||
|
<Input id={id} {...restProps} value={this.state.value} autoComplete="off" onChange={this.handleChange}/>
|
||||||
|
</Dropdown>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InputSelect;
|
|
@ -3,10 +3,11 @@ import { formatMessage, FormattedMessage } from 'umi/locale';
|
||||||
import router from 'umi/router';
|
import router from 'umi/router';
|
||||||
import { connect } from 'dva';
|
import { connect } from 'dva';
|
||||||
import { Col, Form, Row,Select, Input, Card,Icon, Table, InputNumber, Popconfirm,
|
import { Col, Form, Row,Select, Input, Card,Icon, Table, InputNumber, Popconfirm,
|
||||||
Divider,Button,Tooltip, Cascader, Modal, DatePicker, Dropdown,Menu, message } from 'antd';
|
Divider,Button,Tooltip, Modal, DatePicker, message } from 'antd';
|
||||||
import Editor, {monaco} from '@monaco-editor/react';
|
import Editor, {monaco} from '@monaco-editor/react';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import {createDependencyProposals} from './autocomplete';
|
import {createDependencyProposals} from './autocomplete';
|
||||||
|
import InputSelect from '@/components/infini/InputSelect';
|
||||||
|
|
||||||
function findParentIdentifier(textUntilPosition){
|
function findParentIdentifier(textUntilPosition){
|
||||||
let chars = textUntilPosition;
|
let chars = textUntilPosition;
|
||||||
|
@ -364,54 +365,6 @@ class EditableCell extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InputSelect extends React.Component{
|
|
||||||
state = {
|
|
||||||
value: this.props.defaultValue
|
|
||||||
}
|
|
||||||
onClick = ({ key }) => {
|
|
||||||
this.inputEl.setState({
|
|
||||||
value: key
|
|
||||||
})
|
|
||||||
this.setState({
|
|
||||||
value: key,
|
|
||||||
})
|
|
||||||
this.triggerChange(key)
|
|
||||||
}
|
|
||||||
triggerChange = (val)=>{
|
|
||||||
let {onChange} = this.props;
|
|
||||||
if(onChange && typeof onChange == 'function'){
|
|
||||||
onChange(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handleChange = (ev) => {
|
|
||||||
let val = ev.target.value;
|
|
||||||
let filterData = this.props.data.slice();
|
|
||||||
if(val != ""){
|
|
||||||
filterData = filterData.filter(v=>v.value.includes(val))
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
value: val,
|
|
||||||
data: filterData
|
|
||||||
})
|
|
||||||
this.triggerChange(val);
|
|
||||||
}
|
|
||||||
render(){
|
|
||||||
let {data, onChange, ...restProps} = this.props;
|
|
||||||
let filterData = this.state.data || data;
|
|
||||||
return (
|
|
||||||
<Dropdown overlay={
|
|
||||||
<Menu onClick={this.onClick} style={{maxHeight:'350px', overflow:"scroll"}}>
|
|
||||||
{filterData.map(op =>(
|
|
||||||
<Menu.Item key={op.value}>{op.label}</Menu.Item>
|
|
||||||
))}
|
|
||||||
</Menu>
|
|
||||||
} trigger={['focus']}>
|
|
||||||
<Input ref={el=>{this.inputEl=el}} {...restProps} onChange={this.handleChange}/>
|
|
||||||
</Dropdown>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@connect(({document})=>({
|
@connect(({document})=>({
|
||||||
document
|
document
|
||||||
}))
|
}))
|
||||||
|
@ -440,14 +393,20 @@ class Doucment extends React.Component {
|
||||||
componentDidMount(){
|
componentDidMount(){
|
||||||
const {location, dispatch } = this.props;
|
const {location, dispatch } = this.props;
|
||||||
//console.log(match, location);
|
//console.log(match, location);
|
||||||
let index = location.query.index || 'infini-test';
|
let index = location.query.index;
|
||||||
let cluster = location.query.cluster || 'single-es';
|
let cluster = location.query.cluster || 'single-es';
|
||||||
|
if(!cluster){
|
||||||
|
return
|
||||||
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'document/fetchIndices',
|
type: 'document/fetchIndices',
|
||||||
payload: {
|
payload: {
|
||||||
cluster,
|
cluster,
|
||||||
}
|
}
|
||||||
}).then(()=>{
|
}).then(()=>{
|
||||||
|
if(!index){
|
||||||
|
return
|
||||||
|
}
|
||||||
this.fetchData({
|
this.fetchData({
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
pageIndex: 1,
|
pageIndex: 1,
|
||||||
|
@ -559,7 +518,7 @@ class Doucment extends React.Component {
|
||||||
})
|
})
|
||||||
const clusters = ["single-es"];
|
const clusters = ["single-es"];
|
||||||
let {cluster, index}= this.props.document;
|
let {cluster, index}= this.props.document;
|
||||||
cluster = cluster || this.props.location.query.cluster;
|
cluster = cluster || this.props.location.query.cluster || 'single-es';
|
||||||
index = index || this.props.location.query.index;
|
index = index || this.props.location.query.index;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -620,14 +579,13 @@ class Doucment extends React.Component {
|
||||||
<div style={{fontSize: 12, paddingLeft: 20}}>
|
<div style={{fontSize: 12, paddingLeft: 20}}>
|
||||||
<div style={{fontSize: 16, paddingBottom: 10, color: '#1890FF'}}>query example:</div>
|
<div style={{fontSize: 16, paddingBottom: 10, color: '#1890FF'}}>query example:</div>
|
||||||
<div style={{background:'rgb(245, 247, 250)', padding: 10}}>
|
<div style={{background:'rgb(245, 247, 250)', padding: 10}}>
|
||||||
<code dangerouslySetInnerHTML={{ __html: `{<br/> "bool":{<br/>
|
<pre className="language-json">{JSON.stringify({
|
||||||
"must": {<br/>
|
must: {
|
||||||
"match":{ <br/>
|
match: {
|
||||||
"FIELD": "VALUE"<br/>
|
FIELD: "VALUE"
|
||||||
}<br/>
|
}
|
||||||
}<br/>
|
}
|
||||||
}<br/>}` }}>
|
}, null, 2)}</pre>
|
||||||
</code>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
@ -1,20 +1,43 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'dva';
|
import { connect } from 'dva';
|
||||||
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
|
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
|
||||||
import {Steps, Card, Form, Select, Input,Button, Divider,message,Spin, Row, Col,Result} from 'antd';
|
import {Steps, Card, Form, Select, Input,Button, Divider,message, InputNumber} from 'antd';
|
||||||
|
import InputSelect from '@/components/infini/InputSelect';
|
||||||
|
|
||||||
const {Step} = Steps;
|
const {Step} = Steps;
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
const {TextArea} = Input;
|
const {TextArea} = Input;
|
||||||
|
|
||||||
@Form.create()
|
@Form.create()
|
||||||
@connect()
|
@connect(({document}) => ({
|
||||||
|
document
|
||||||
|
}))
|
||||||
class Rebuild extends Component {
|
class Rebuild extends Component {
|
||||||
state = {
|
state = {
|
||||||
currentStep: 0,
|
currentStep: 0,
|
||||||
configData: {},
|
configData: {
|
||||||
|
source:{},
|
||||||
|
dest:{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
renderSteps(currentStep){
|
componentDidMount(){
|
||||||
|
const {dispatch} = this.props;
|
||||||
|
dispatch({
|
||||||
|
type:'document/fetchIndices',
|
||||||
|
payload:{
|
||||||
|
cluster: 'sinlge-es'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
renderSteps = (currentStep) => {
|
||||||
|
let {clusterIndices} = this.props.document;
|
||||||
|
clusterIndices = clusterIndices || [];
|
||||||
|
let indices = clusterIndices.map((item)=>{
|
||||||
|
return {
|
||||||
|
label: item,
|
||||||
|
value: item,
|
||||||
|
}
|
||||||
|
});
|
||||||
var stepDom = '';
|
var stepDom = '';
|
||||||
const { getFieldDecorator } = this.props.form;
|
const { getFieldDecorator } = this.props.form;
|
||||||
const formItemLayout = {
|
const formItemLayout = {
|
||||||
|
@ -28,6 +51,9 @@ class Rebuild extends Component {
|
||||||
sm: { span: 16 },
|
sm: { span: 16 },
|
||||||
md:{span:20},
|
md:{span:20},
|
||||||
},
|
},
|
||||||
|
style: {
|
||||||
|
marginBottom: 10,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const tailFormItemLayout = {
|
const tailFormItemLayout = {
|
||||||
wrapperCol: {
|
wrapperCol: {
|
||||||
|
@ -49,35 +75,23 @@ class Rebuild extends Component {
|
||||||
case 0:
|
case 0:
|
||||||
stepDom = (
|
stepDom = (
|
||||||
<div style={{marginTop:20}}>
|
<div style={{marginTop:20}}>
|
||||||
<Form.Item {...formItemLayout} label="选择源索引">
|
<Form.Item {...formItemLayout} label="Task Name">
|
||||||
{getFieldDecorator('source_index', {
|
{getFieldDecorator('name', {
|
||||||
initialValue: this.state.configData.source_index,
|
initialValue: this.state.configData.name,
|
||||||
rules: [{ required: true, message: '请选择要重建的索引' }],
|
rules: [{ required: true, message: 'please input a task name' }],
|
||||||
})(
|
})(
|
||||||
<Select
|
<Input autoComplete="off" style={{width: 200}}/>
|
||||||
showSearch
|
|
||||||
style={{ width: 200 }}
|
|
||||||
optionFilterProp="children"
|
|
||||||
filterOption={(input, option) =>
|
|
||||||
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Option value="logs">logs</Option>
|
|
||||||
<Option value="blogs">blogs</Option>
|
|
||||||
<Option value="filebeat">filebeat</Option>
|
|
||||||
</Select>,
|
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item {...formItemLayout} label="过滤条件">
|
<Form.Item {...formItemLayout} label="Task Description">
|
||||||
{getFieldDecorator('creterial', {
|
{getFieldDecorator('desc', {
|
||||||
initialValue: this.state.configData.creterial,
|
initialValue: this.state.configData.creterial,
|
||||||
rules: [
|
rules: [
|
||||||
{required: true, },
|
|
||||||
],
|
],
|
||||||
})(
|
})(
|
||||||
<TextArea
|
<TextArea
|
||||||
style={{ width: '80%' }}
|
style={{ width: '80%' }}
|
||||||
rows={8}
|
rows={6}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
@ -87,28 +101,82 @@ class Rebuild extends Component {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
stepDom = (
|
stepDom = (
|
||||||
<div style={{marginTop:20}}>
|
<div style={{marginTop:20}}>
|
||||||
<Form.Item {...formItemLayout} label="目标索引名">
|
<Form.Item {...formItemLayout} label="选择源索引">
|
||||||
{getFieldDecorator('target_index', {
|
{getFieldDecorator('source_index', {
|
||||||
initialValue: this.state.configData.target_index,
|
initialValue: this.state.configData.source.index,
|
||||||
rules: [{ required: true, message: '请输入目标索引名称' }],
|
rules: [{ required: true, message: '请选择要重建的索引' }],
|
||||||
|
})(
|
||||||
|
<InputSelect data={indices} style={{width: 200}}/>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item {...formItemLayout} label="Query">
|
||||||
|
{getFieldDecorator('source_query', {
|
||||||
|
initialValue: this.state.configData.source.query,
|
||||||
|
rules: [
|
||||||
|
{required: true, },
|
||||||
|
],
|
||||||
})(
|
})(
|
||||||
<Input style={{width:200}} />
|
<TextArea
|
||||||
|
style={{ width: '80%' }}
|
||||||
|
rows={6}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item {...formItemLayout} label="目标索引设置">
|
<Form.Item {...formItemLayout} label="max_docs">
|
||||||
{getFieldDecorator('target_setting', {
|
{getFieldDecorator('source_max_docs', {
|
||||||
initialValue: this.state.configData.target_setting,
|
initialValue: this.state.configData.source_max_docs,
|
||||||
|
rules: [
|
||||||
|
],
|
||||||
|
})(
|
||||||
|
<InputNumber min={1} style={{width:200}}/>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item {...formItemLayout} label="_source">
|
||||||
|
{getFieldDecorator('source__source', {
|
||||||
|
initialValue: this.state.configData.source__source,
|
||||||
|
rules: [
|
||||||
|
],
|
||||||
|
})(
|
||||||
|
<Input style={{width:'50%'}}/>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item {...formItemLayout} label="sort">
|
||||||
|
{getFieldDecorator('source_sort', {
|
||||||
|
initialValue: this.state.configData.source_sort,
|
||||||
|
rules: [
|
||||||
|
],
|
||||||
|
})(
|
||||||
|
<Input style={{width:'50%'}}/>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item {...tailFormItemLayout}>
|
||||||
|
{this.renderFooter(currentStep)}
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
stepDom = (
|
||||||
|
<div style={{marginTop:20}}>
|
||||||
|
<span style={{height:1}}/>
|
||||||
|
<Form.Item {...formItemLayout} label="目标索引名">
|
||||||
|
{getFieldDecorator('dest_index', {
|
||||||
|
initialValue: this.state.configData.dest.index || '',
|
||||||
|
rules: [{ required: true, message: '请输入目标索引名称' }],
|
||||||
|
})(
|
||||||
|
<InputSelect data={indices} style={{width: 200}}/>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item {...formItemLayout} label="Pipeline">
|
||||||
|
{getFieldDecorator('dest_pipeline', {
|
||||||
|
initialValue: this.state.configData.dest.source,
|
||||||
rules: [
|
rules: [
|
||||||
{required: true, },
|
|
||||||
],
|
],
|
||||||
})(
|
})(
|
||||||
<TextArea
|
<Input style={{width:200}}/>
|
||||||
style={{ width: '80%' }}
|
|
||||||
rows={8}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item {...tailFormItemLayout}>
|
<Form.Item {...tailFormItemLayout}>
|
||||||
|
@ -117,58 +185,52 @@ class Rebuild extends Component {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
break;
|
break;
|
||||||
case 2:
|
|
||||||
stepDom = (
|
|
||||||
<div>
|
|
||||||
<Spin tip="数据正在重建,请稍等...">
|
|
||||||
<div style={{width:'100%', height: 200}}></div>
|
|
||||||
</Spin>
|
|
||||||
<div style={{textAlign:'center',}}>
|
|
||||||
{this.renderFooter(currentStep)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
stepDom = (<Result
|
|
||||||
status="success"
|
|
||||||
title="数据重建成功"
|
|
||||||
subTitle=""
|
|
||||||
extra={[
|
|
||||||
// <Button type="primary" key="console">
|
|
||||||
// </Button>,
|
|
||||||
<Button key="continue">继续重建</Button>,
|
|
||||||
]}
|
|
||||||
/>)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return stepDom;
|
return stepDom;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNext(currentStep){
|
handleNext(currentStep){
|
||||||
const { form } = this.props;
|
const { form, dispatch } = this.props;
|
||||||
const { configData: oldValue } = this.state;
|
const { configData: oldValue } = this.state;
|
||||||
var formValues = {};
|
var formValues = {};
|
||||||
form.validateFields((err, fieldsValue) => {
|
form.validateFields((err, fieldsValue) => {
|
||||||
if (err) return;
|
if (err) return;
|
||||||
switch(currentStep){
|
let newValue = {};
|
||||||
case 0:
|
if(fieldsValue['source_query']){
|
||||||
break;
|
fieldsValue['source_query'] = JSON.parse(fieldsValue['source_query'])
|
||||||
case 1:
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
formValues = fieldsValue;
|
for(let key in fieldsValue){
|
||||||
});
|
if(key.startsWith('source_')){
|
||||||
this.setState({
|
!newValue.source && (newValue.source ={})
|
||||||
configData: {
|
newValue.source[key.slice(7)] = fieldsValue[key]
|
||||||
...oldValue,
|
}else if(key.startsWith('dest_')){
|
||||||
...formValues,
|
!newValue.dest && (newValue.dest ={})
|
||||||
},
|
newValue.dest[key.slice(5)] = fieldsValue[key]
|
||||||
currentStep: currentStep+1
|
}else{
|
||||||
},()=>{
|
newValue[key] = fieldsValue[key];
|
||||||
message.info(JSON.stringify(this.state));
|
}
|
||||||
|
}
|
||||||
|
if(currentStep == 2){
|
||||||
|
currentStep = 1;
|
||||||
|
dispatch({
|
||||||
|
type: 'rebuild/addTask',
|
||||||
|
payload: {
|
||||||
|
...oldValue,
|
||||||
|
...newValue,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
configData: {
|
||||||
|
...oldValue,
|
||||||
|
...newValue,
|
||||||
|
},
|
||||||
|
currentStep: currentStep+1
|
||||||
|
},()=>{
|
||||||
|
message.info(JSON.stringify(this.state));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
backward(currentStep){
|
backward(currentStep){
|
||||||
if(currentStep > 0){
|
if(currentStep > 0){
|
||||||
|
@ -179,7 +241,7 @@ class Rebuild extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
renderFooter = currentStep => {
|
renderFooter = currentStep => {
|
||||||
if (currentStep === 1 || currentStep ==2) {
|
if (currentStep === 1) {
|
||||||
return [
|
return [
|
||||||
<Button key="back" onClick={()=>this.backward(currentStep)}>
|
<Button key="back" onClick={()=>this.backward(currentStep)}>
|
||||||
上一步
|
上一步
|
||||||
|
@ -192,7 +254,7 @@ class Rebuild extends Component {
|
||||||
</Button>,
|
</Button>,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if (currentStep === 3) {
|
if (currentStep === 2) {
|
||||||
return [
|
return [
|
||||||
<Button key="back" style={{ float: 'left' }} onClick={()=>this.backward(currentStep)}>
|
<Button key="back" style={{ float: 'left' }} onClick={()=>this.backward(currentStep)}>
|
||||||
上一步
|
上一步
|
||||||
|
@ -200,7 +262,7 @@ class Rebuild extends Component {
|
||||||
<Button key="cancel" style={{margin:'auto 2em'}} onClick={() => {}}>
|
<Button key="cancel" style={{margin:'auto 2em'}} onClick={() => {}}>
|
||||||
取消
|
取消
|
||||||
</Button>,
|
</Button>,
|
||||||
<Button key="submit" type="primary" onClick={() =>{}}>
|
<Button key="submit" type="primary" onClick={() =>this.handleNext(currentStep)}>
|
||||||
完成
|
完成
|
||||||
</Button>,
|
</Button>,
|
||||||
];
|
];
|
||||||
|
@ -219,10 +281,9 @@ class Rebuild extends Component {
|
||||||
<PageHeaderWrapper >
|
<PageHeaderWrapper >
|
||||||
<Card>
|
<Card>
|
||||||
<Steps current={this.state.currentStep}>
|
<Steps current={this.state.currentStep}>
|
||||||
|
<Step title="基本信息" />
|
||||||
<Step title="源索引信息" />
|
<Step title="源索引信息" />
|
||||||
<Step title="目标索引信息" />
|
<Step title="目标索引信息" />
|
||||||
<Step title="数据重建中" subTitle="剩余 00:00:08" />
|
|
||||||
<Step title="重建结果" />
|
|
||||||
</Steps>
|
</Steps>
|
||||||
<Divider/>
|
<Divider/>
|
||||||
{this.renderSteps(this.state.currentStep)}
|
{this.renderSteps(this.state.currentStep)}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import {reindex} from '@/services/rebuild';
|
||||||
|
import { message } from 'antd';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
namespace: 'rebuild',
|
||||||
|
state: {},
|
||||||
|
effects:{
|
||||||
|
*addTask({payload}, {call, put}){
|
||||||
|
let resp = yield call(reindex, payload);
|
||||||
|
console.log(resp);
|
||||||
|
if(resp.errno != "0"){
|
||||||
|
message.warn("rebuild failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reducers: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export const pathPrefix = '/_search-center';
|
|
@ -1,7 +1,8 @@
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
|
import {pathPrefix} from './common';
|
||||||
|
|
||||||
export async function getDocList(params) {
|
export async function getDocList(params) {
|
||||||
return request(`/api/doc/${params.index}`, {
|
return request(`${pathPrefix}/doc/${params.index}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: {
|
body: {
|
||||||
action: 'SEARCH',
|
action: 'SEARCH',
|
||||||
|
@ -11,7 +12,7 @@ export async function getDocList(params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function saveDoc(params) {
|
export async function saveDoc(params) {
|
||||||
return request(`/api/doc/${params.index}`, {
|
return request(`${pathPrefix}/doc/${params.index}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: {
|
body: {
|
||||||
payload: params.data,
|
payload: params.data,
|
||||||
|
@ -22,7 +23,7 @@ export async function saveDoc(params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteDoc(params) {
|
export async function deleteDoc(params) {
|
||||||
return request(`/api/doc/${params.index}`, {
|
return request(`${pathPrefix}/doc/${params.index}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: {
|
body: {
|
||||||
index: params.index,
|
index: params.index,
|
||||||
|
@ -33,7 +34,7 @@ export async function deleteDoc(params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addDoc(params) {
|
export async function addDoc(params) {
|
||||||
return request(`/api/doc/${params.index}`, {
|
return request(`${pathPrefix}/doc/${params.index}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: {
|
body: {
|
||||||
payload: params.data,
|
payload: params.data,
|
||||||
|
@ -44,7 +45,7 @@ export async function addDoc(params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getIndices(params) {
|
export async function getIndices(params) {
|
||||||
return request(`/api/indices/_cat`, {
|
return request(`${pathPrefix}/indices/_cat`, {
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
import {pathPrefix} from './common';
|
||||||
|
|
||||||
|
export async function reindex(payload){
|
||||||
|
let url = `${pathPrefix}/rebuild/_create`;
|
||||||
|
return request(url,{
|
||||||
|
method: 'POST',
|
||||||
|
body: payload,
|
||||||
|
expirys: 0,
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
|
import {pathPrefix} from './common';
|
||||||
|
|
||||||
export async function getDictList(payload){
|
export async function getDictList(payload){
|
||||||
let url = `/api/dict/_search?from=${payload.from}&size=${payload.size}`;
|
let url = `${pathPrefix}/dict/_search?from=${payload.from}&size=${payload.size}`;
|
||||||
payload.name && (url+= `&name=${payload.name}`);
|
payload.name && (url+= `&name=${payload.name}`);
|
||||||
payload.tags && (url+=`&tags=${payload.tags}`);
|
payload.tags && (url+=`&tags=${payload.tags}`);
|
||||||
return request(url,{
|
return request(url,{
|
||||||
|
@ -12,7 +13,7 @@ export async function getDictList(payload){
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addDict(payload){
|
export async function addDict(payload){
|
||||||
return request('/api/dict/_create',{
|
return request(`${pathPrefix}/dict/_create`,{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: payload,
|
body: payload,
|
||||||
expirys: 0,
|
expirys: 0,
|
||||||
|
@ -20,14 +21,14 @@ export async function addDict(payload){
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteDict(payload){
|
export async function deleteDict(payload){
|
||||||
return request(`/api/dict/${payload.id}`,{
|
return request(`${pathPrefix}/dict/${payload.id}`,{
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
expirys: 0,
|
expirys: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateDict(payload){
|
export async function updateDict(payload){
|
||||||
return request('/api/dict/_update',{
|
return request(`${pathPrefix}/dict/_update`,{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: payload,
|
body: payload,
|
||||||
expirys: 0,
|
expirys: 0,
|
||||||
|
|
Loading…
Reference in New Issue