add discover table view and fixed bugs
This commit is contained in:
parent
947b0bfa04
commit
e1cd6d0cf7
|
@ -21,92 +21,91 @@ type docReqBody struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler APIHandler) HandleAddDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) HandleAddDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
targetClusterID := ps.ByName("id")
|
||||||
|
client := elastic.GetClient(targetClusterID)
|
||||||
reqBody := map[string]interface{}{}
|
reqBody := map[string]interface{}{}
|
||||||
resResult := newResponseBody()
|
resBody := newResponseBody()
|
||||||
err := handler.DecodeJSON(req, &reqBody)
|
err := handler.DecodeJSON(req, &reqBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resResult["status"] = false
|
resBody["error"] = err.Error()
|
||||||
resResult["error"] = err.Error()
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
indexName := ps.ByName("index")
|
indexName := ps.ByName("index")
|
||||||
id := ps.ByName("id")
|
docID := ps.ByName("docId")
|
||||||
if strings.Trim(id, "/") == "" {
|
if strings.Trim(docID, "/") == "" {
|
||||||
id = util.GetUUID()
|
docID = util.GetUUID()
|
||||||
}
|
}
|
||||||
docType := handler.GetParameter(req, "_type")
|
docType := handler.GetParameter(req, "_type")
|
||||||
_, err = client.Index(indexName, docType, id, reqBody)
|
insertRes, err := client.Index(indexName, docType, docID, reqBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resResult["status"] = false
|
resBody["error"] = err
|
||||||
resResult["error"] = err
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
reqBody["id"] = id
|
reqBody["_id"] = docID
|
||||||
resResult["payload"] = reqBody
|
resBody["result"] = insertRes.Result
|
||||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler APIHandler) HandleUpdateDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) HandleUpdateDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
targetClusterID := ps.ByName("id")
|
||||||
|
client := elastic.GetClient(targetClusterID)
|
||||||
|
resBody := newResponseBody()
|
||||||
|
if client == nil {
|
||||||
|
resBody["error"] = "can not found target cluster"
|
||||||
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
|
return
|
||||||
|
}
|
||||||
reqBody := map[string]interface{}{}
|
reqBody := map[string]interface{}{}
|
||||||
resResult := newResponseBody()
|
|
||||||
err := handler.DecodeJSON(req, &reqBody)
|
err := handler.DecodeJSON(req, &reqBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resResult["status"] = false
|
resBody["error"] = err
|
||||||
resResult["error"] = err
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
indexName := ps.ByName("index")
|
indexName := ps.ByName("index")
|
||||||
id := ps.ByName("id")
|
docID := ps.ByName("docId")
|
||||||
typ := handler.GetParameter(req, "_type")
|
typ := handler.GetParameter(req, "_type")
|
||||||
resp, err := client.Get(indexName,typ, id)
|
insertRes, err := client.Index(indexName, typ, docID, reqBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resResult["status"] = false
|
resBody["error"] = err.Error()
|
||||||
resResult["error"] = err.Error()
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
source := resp.Source
|
resBody["_source"] = reqBody
|
||||||
for k, v := range reqBody {
|
resBody["_id"] = docID
|
||||||
if k == "id" {
|
resBody["result"] = insertRes.Result
|
||||||
continue
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
}
|
|
||||||
source[k] = v
|
|
||||||
}
|
|
||||||
_, err = client.Index(indexName, typ, id, source)
|
|
||||||
if err != nil {
|
|
||||||
resResult["status"] = false
|
|
||||||
resResult["error"] = err.Error()
|
|
||||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resResult["payload"] = reqBody
|
|
||||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler APIHandler) HandleDeleteDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) HandleDeleteDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
targetClusterID := ps.ByName("id")
|
||||||
resResult := newResponseBody()
|
client := elastic.GetClient(targetClusterID)
|
||||||
indexName := ps.ByName("index")
|
resBody := newResponseBody()
|
||||||
id := ps.ByName("id")
|
if client == nil {
|
||||||
typ := handler.GetParameter(req, "_type")
|
resBody["error"] = "can not found target cluster"
|
||||||
_, err := client.Delete(indexName, typ, id)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
if err != nil {
|
|
||||||
resResult["error"] = err.Error()
|
|
||||||
resResult["status"] = false
|
|
||||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resResult["payload"] = true
|
|
||||||
handler.WriteJSON(w, resResult, http.StatusOK)
|
indexName := ps.ByName("index")
|
||||||
|
docID := ps.ByName("docId")
|
||||||
|
typ := handler.GetParameter(req, "_type")
|
||||||
|
delRes, err := client.Delete(indexName, typ, docID, "wait_for")
|
||||||
|
if err != nil {
|
||||||
|
resBody["error"] = err.Error()
|
||||||
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resBody["result"] = delRes.Result
|
||||||
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler APIHandler) HandleSearchDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) HandleSearchDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
targetClusterID := ps.ByName("id")
|
||||||
|
client := elastic.GetClient(targetClusterID)
|
||||||
reqBody := docReqBody{}
|
reqBody := docReqBody{}
|
||||||
resResult := newResponseBody()
|
resResult := newResponseBody()
|
||||||
err := handler.DecodeJSON(req, &reqBody)
|
err := handler.DecodeJSON(req, &reqBody)
|
||||||
|
|
|
@ -2,13 +2,13 @@ package index_management
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
httprouter "infini.sh/framework/core/api/router"
|
httprouter "infini.sh/framework/core/api/router"
|
||||||
"infini.sh/framework/core/elastic"
|
"infini.sh/framework/core/elastic"
|
||||||
"infini.sh/framework/core/orm"
|
"infini.sh/framework/core/orm"
|
||||||
"infini.sh/framework/core/util"
|
"infini.sh/framework/core/util"
|
||||||
"infini.sh/framework/modules/elastic/common"
|
"infini.sh/framework/modules/elastic/common"
|
||||||
"net/http"
|
"net/http"
|
||||||
log "github.com/cihub/seelog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (handler APIHandler) ElasticsearchOverviewAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) ElasticsearchOverviewAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
|
@ -49,6 +49,7 @@ func (handler APIHandler) ElasticsearchOverviewAction(w http.ResponseWriter, req
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
resBody := util.MapStr{
|
resBody := util.MapStr{
|
||||||
"total_node": totalNode,
|
"total_node": totalNode,
|
||||||
"total_store_size_in_bytes": totalStoreSize,
|
"total_store_size_in_bytes": totalStoreSize,
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
package index_management
|
package index_management
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
httprouter "infini.sh/framework/core/api/router"
|
httprouter "infini.sh/framework/core/api/router"
|
||||||
"infini.sh/framework/core/elastic"
|
"infini.sh/framework/core/elastic"
|
||||||
|
"infini.sh/framework/core/util"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (handler APIHandler) HandleGetMappingsAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) HandleGetMappingsAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
targetClusterID := ps.ByName("id")
|
||||||
|
client := elastic.GetClient(targetClusterID)
|
||||||
indexName := ps.ByName("index")
|
indexName := ps.ByName("index")
|
||||||
resBody := newResponseBody()
|
resBody := newResponseBody()
|
||||||
var copyAll = false
|
var copyAll = false
|
||||||
|
@ -20,114 +20,102 @@ func (handler APIHandler) HandleGetMappingsAction(w http.ResponseWriter, req *ht
|
||||||
_, _, idxs, err := client.GetMapping(copyAll, indexName)
|
_, _, idxs, err := client.GetMapping(copyAll, indexName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
resBody["status"] = false
|
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if copyAll {
|
//if copyAll {
|
||||||
for key, _ := range *idxs {
|
// for key, _ := range *idxs {
|
||||||
if strings.HasPrefix(key, ".") || strings.HasPrefix(key, "infini-") {
|
// if strings.HasPrefix(key, ".") || strings.HasPrefix(key, "infini-") {
|
||||||
delete(*idxs, key)
|
// delete(*idxs, key)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
resBody["payload"] = idxs
|
handler.WriteJSON(w, idxs, http.StatusOK)
|
||||||
|
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler APIHandler) HandleGetIndicesAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) HandleGetIndicesAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
targetClusterID := ps.ByName("id")
|
||||||
|
client := elastic.GetClient(targetClusterID)
|
||||||
catIndices, err := client.GetIndices("")
|
catIndices, err := client.GetIndices("")
|
||||||
for key, _ := range *catIndices {
|
resBody := util.MapStr{}
|
||||||
if strings.HasPrefix(key,".") || strings.HasPrefix(key, "infini-"){
|
|
||||||
delete(*catIndices, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resBody := newResponseBody()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resBody["payload"] = catIndices
|
handler.WriteJSON(w, catIndices, http.StatusOK)
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler APIHandler) HandleGetSettingsAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) HandleGetSettingsAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
targetClusterID := ps.ByName("id")
|
||||||
|
client := elastic.GetClient(targetClusterID)
|
||||||
indexName := ps.ByName("index")
|
indexName := ps.ByName("index")
|
||||||
resBody := newResponseBody()
|
resBody := newResponseBody()
|
||||||
indexes, err := client.GetIndexSettings(indexName)
|
indexes, err := client.GetIndexSettings(indexName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resBody["payload"] = indexes
|
handler.WriteJSON(w, indexes, http.StatusOK)
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler APIHandler) HandleUpdateSettingsAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) HandleUpdateSettingsAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
targetClusterID := ps.ByName("id")
|
||||||
|
client := elastic.GetClient(targetClusterID)
|
||||||
indexName := ps.ByName("index")
|
indexName := ps.ByName("index")
|
||||||
settings := map[string]interface{}{}
|
settings := map[string]interface{}{}
|
||||||
resBody := newResponseBody()
|
resBody := newResponseBody()
|
||||||
err := handler.DecodeJSON(req, &settings)
|
err := handler.DecodeJSON(req, &settings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = client.UpdateIndexSettings(indexName, settings)
|
err = client.UpdateIndexSettings(indexName, settings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resBody["payload"] = true
|
resBody["result"] = "updated"
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler APIHandler) HandleDeleteIndexAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) HandleDeleteIndexAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
targetClusterID := ps.ByName("id")
|
||||||
|
client := elastic.GetClient(targetClusterID)
|
||||||
indexName := ps.ByName("index")
|
indexName := ps.ByName("index")
|
||||||
resBody := newResponseBody()
|
resBody := newResponseBody()
|
||||||
err := client.DeleteIndex(indexName)
|
err := client.DeleteIndex(indexName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resBody["payload"] = true
|
resBody["result"] = "deleted"
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler APIHandler) HandleCreateIndexAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
func (handler APIHandler) HandleCreateIndexAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||||
client := elastic.GetClient(handler.Config.Elasticsearch)
|
targetClusterID := ps.ByName("id")
|
||||||
|
client := elastic.GetClient(targetClusterID)
|
||||||
indexName := ps.ByName("index")
|
indexName := ps.ByName("index")
|
||||||
resBody := newResponseBody()
|
resBody := newResponseBody()
|
||||||
config := map[string]interface{}{}
|
config := map[string]interface{}{}
|
||||||
err := handler.DecodeJSON(req, &config)
|
err := handler.DecodeJSON(req, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = client.CreateIndex(indexName, config)
|
err = client.CreateIndex(indexName, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resBody["payload"] = true
|
resBody["result"] = "created"
|
||||||
handler.WriteJSON(w, resBody, http.StatusOK)
|
handler.WriteJSON(w, resBody, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
22
api/init.go
22
api/init.go
|
@ -16,6 +16,7 @@ func Init(cfg *config.AppConfig) {
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
}
|
}
|
||||||
var pathPrefix = "/_search-center/"
|
var pathPrefix = "/_search-center/"
|
||||||
|
var esPrefix = "/elasticsearch/:id/"
|
||||||
//ui.HandleUIMethod(api.POST, "/api/get_indices",index_management.API1)
|
//ui.HandleUIMethod(api.POST, "/api/get_indices",index_management.API1)
|
||||||
ui.HandleUIMethod(api.GET, path.Join(pathPrefix, "elasticsearch/overview"), handler.ElasticsearchOverviewAction)
|
ui.HandleUIMethod(api.GET, path.Join(pathPrefix, "elasticsearch/overview"), handler.ElasticsearchOverviewAction)
|
||||||
|
|
||||||
|
@ -24,20 +25,21 @@ func Init(cfg *config.AppConfig) {
|
||||||
//ui.HandleUIMethod(api.GET, "/api/dict/:id",handler.GetDictItemAction)
|
//ui.HandleUIMethod(api.GET, "/api/dict/:id",handler.GetDictItemAction)
|
||||||
ui.HandleUIMethod(api.DELETE, path.Join(pathPrefix, "dict/:id"), handler.DeleteDictItemAction)
|
ui.HandleUIMethod(api.DELETE, path.Join(pathPrefix, "dict/:id"), handler.DeleteDictItemAction)
|
||||||
ui.HandleUIMethod(api.PUT, path.Join(pathPrefix, "dict/:id"), handler.UpdateDictItemAction)
|
ui.HandleUIMethod(api.PUT, path.Join(pathPrefix, "dict/:id"), handler.UpdateDictItemAction)
|
||||||
ui.HandleUIMethod(api.POST, path.Join(pathPrefix, "doc/:index/_search"), handler.HandleSearchDocumentAction)
|
ui.HandleUIMethod(api.POST, path.Join(esPrefix, "doc/:index/_search"), handler.HandleSearchDocumentAction)
|
||||||
ui.HandleUIMethod(api.POST, path.Join(pathPrefix, "doc/:index/_create"), handler.HandleAddDocumentAction)
|
ui.HandleUIMethod(api.POST, path.Join(esPrefix, "doc/:index"), handler.HandleAddDocumentAction)
|
||||||
ui.HandleUIMethod(api.PUT, path.Join(pathPrefix, "doc/:index/:id"), handler.HandleUpdateDocumentAction)
|
ui.HandleUIMethod(api.PUT, path.Join(esPrefix, "doc/:index/:docId"), handler.HandleUpdateDocumentAction)
|
||||||
ui.HandleUIMethod(api.DELETE, path.Join(pathPrefix, "doc/:index/:id"), handler.HandleDeleteDocumentAction)
|
ui.HandleUIMethod(api.DELETE, path.Join(esPrefix, "doc/:index/:docId"), handler.HandleDeleteDocumentAction)
|
||||||
|
|
||||||
ui.HandleUIMethod(api.POST, path.Join(pathPrefix, "rebuild/*id"), handler.HandleReindexAction)
|
ui.HandleUIMethod(api.POST, path.Join(pathPrefix, "rebuild/*id"), handler.HandleReindexAction)
|
||||||
ui.HandleUIMethod(api.GET, path.Join(pathPrefix, "rebuild/_search"), handler.HandleGetRebuildListAction)
|
ui.HandleUIMethod(api.GET, path.Join(pathPrefix, "rebuild/_search"), handler.HandleGetRebuildListAction)
|
||||||
ui.HandleUIMethod(api.DELETE, path.Join(pathPrefix, "rebuild/:id"), handler.HandleDeleteRebuildAction)
|
ui.HandleUIMethod(api.DELETE, path.Join(pathPrefix, "rebuild/:id"), handler.HandleDeleteRebuildAction)
|
||||||
ui.HandleUIMethod(api.GET, path.Join(pathPrefix, "_cat/indices"), handler.HandleGetIndicesAction)
|
|
||||||
ui.HandleUIMethod(api.GET, path.Join(pathPrefix, "index/:index/_mappings"), handler.HandleGetMappingsAction)
|
ui.HandleUIMethod(api.GET, path.Join(esPrefix, "_cat/indices"), handler.HandleGetIndicesAction)
|
||||||
ui.HandleUIMethod(api.GET, path.Join(pathPrefix, "index/:index/_settings"), handler.HandleGetSettingsAction)
|
ui.HandleUIMethod(api.GET, path.Join(esPrefix, "index/:index/_mappings"), handler.HandleGetMappingsAction)
|
||||||
ui.HandleUIMethod(api.PUT, path.Join(pathPrefix, "index/:index/_settings"), handler.HandleUpdateSettingsAction)
|
ui.HandleUIMethod(api.GET, path.Join(esPrefix, "index/:index/_settings"), handler.HandleGetSettingsAction)
|
||||||
ui.HandleUIMethod(api.DELETE, path.Join(pathPrefix, "index/:index"), handler.HandleDeleteIndexAction)
|
ui.HandleUIMethod(api.PUT, path.Join(esPrefix, "index/:index/_settings"), handler.HandleUpdateSettingsAction)
|
||||||
ui.HandleUIMethod(api.POST, path.Join(pathPrefix, "index/:index"), handler.HandleCreateIndexAction)
|
ui.HandleUIMethod(api.DELETE, path.Join(esPrefix, "index/:index"), handler.HandleDeleteIndexAction)
|
||||||
|
ui.HandleUIMethod(api.POST, path.Join(esPrefix, "index/:index"), handler.HandleCreateIndexAction)
|
||||||
|
|
||||||
//new api
|
//new api
|
||||||
ui.HandleUIMethod(api.GET, path.Join(pathPrefix, "alerting/overview"), alerting.GetAlertOverview)
|
ui.HandleUIMethod(api.GET, path.Join(pathPrefix, "alerting/overview"), alerting.GetAlertOverview)
|
||||||
|
|
|
@ -139,25 +139,6 @@ export default [
|
||||||
name: 'data',
|
name: 'data',
|
||||||
icon: 'database',
|
icon: 'database',
|
||||||
routes: [
|
routes: [
|
||||||
// {
|
|
||||||
// path: '/data/pipes',
|
|
||||||
// name: 'pipes',
|
|
||||||
// component: './DataManagement/Pipes',
|
|
||||||
// routes: [
|
|
||||||
// {
|
|
||||||
// path: '/data/pipes',
|
|
||||||
// redirect: '/data/pipes/logstash',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: '/data/pipes/logstash',
|
|
||||||
// component: './DataManagement/LogstashConfig',
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: '/data/pipes/ingestpipeline',
|
|
||||||
// component: './DataManagement/IngestPipeline',
|
|
||||||
// },
|
|
||||||
// ]
|
|
||||||
// },
|
|
||||||
// {
|
// {
|
||||||
// path: '/data/overview',
|
// path: '/data/overview',
|
||||||
// name: 'overview',
|
// name: 'overview',
|
||||||
|
@ -165,14 +146,16 @@ export default [
|
||||||
// routes:[
|
// routes:[
|
||||||
// { path: '/', redirect: '/' },
|
// { path: '/', redirect: '/' },
|
||||||
// ],
|
// ],
|
||||||
// }, {
|
// },
|
||||||
// path: '/data/index',
|
{
|
||||||
// name: 'index',
|
path: '/data/index',
|
||||||
// component: './DataManagement/Index',
|
name: 'index',
|
||||||
// routes:[
|
component: './DataManagement/Index',
|
||||||
// { path: '/', redirect: '/' },
|
routes:[
|
||||||
// ],
|
{ path: '/', redirect: '/' },
|
||||||
// },{
|
],
|
||||||
|
},
|
||||||
|
// {
|
||||||
// path: '/data/document',
|
// path: '/data/document',
|
||||||
// name: 'document',
|
// name: 'document',
|
||||||
// component: './DataManagement/Document',
|
// component: './DataManagement/Document',
|
||||||
|
@ -269,9 +252,9 @@ export default [
|
||||||
// {
|
// {
|
||||||
// path: '/search/alias',
|
// path: '/search/alias',
|
||||||
// redirect: '/search/alias/index',
|
// redirect: '/search/alias/index',
|
||||||
// routes:[
|
// // routes:[
|
||||||
// { path: '/', redirect: '/' },
|
// // { path: '/', redirect: '/' },
|
||||||
// ],
|
// // ],
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
// path: '/search/alias/index',
|
// path: '/search/alias/index',
|
||||||
|
@ -296,9 +279,9 @@ export default [
|
||||||
// {
|
// {
|
||||||
// path: '/search/dict',
|
// path: '/search/dict',
|
||||||
// redirect: '/search/dict/professional',
|
// redirect: '/search/dict/professional',
|
||||||
// routes:[
|
// // routes:[
|
||||||
// { path: '/', redirect: '/' },
|
// // { path: '/', redirect: '/' },
|
||||||
// ],
|
// // ],
|
||||||
// },
|
// },
|
||||||
// {
|
// {
|
||||||
// path: '/search/dict/professional',
|
// path: '/search/dict/professional',
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
"@babel/runtime": "^7.1.2",
|
"@babel/runtime": "^7.1.2",
|
||||||
"@elastic/charts": "^25.0.1",
|
"@elastic/charts": "^25.0.1",
|
||||||
"@elastic/datemath": "^5.0.3",
|
"@elastic/datemath": "^5.0.3",
|
||||||
"@elastic/eui": "^34.4.0",
|
"@elastic/eui": "34.4.0",
|
||||||
"@elastic/numeral": "^2.5.1",
|
"@elastic/numeral": "^2.5.1",
|
||||||
"@hapi/boom": "^9.1.3",
|
"@hapi/boom": "^9.1.3",
|
||||||
"@monaco-editor/react": "^3.7.4",
|
"@monaco-editor/react": "^4.2.2",
|
||||||
"@svgdotjs/svg.js": "^3.0.16",
|
"@svgdotjs/svg.js": "^3.0.16",
|
||||||
"antd": "^3.26.18",
|
"antd": "^3.26.18",
|
||||||
"antd-table-infinity": "^1.1.6",
|
"antd-table-infinity": "^1.1.6",
|
||||||
|
|
|
@ -57,7 +57,7 @@ interface SavedObjectBody {
|
||||||
type FormatFieldFn = (hit: Record<string, any>, fieldName: string) => any;
|
type FormatFieldFn = (hit: Record<string, any>, fieldName: string) => any;
|
||||||
|
|
||||||
export class IndexPattern implements IIndexPattern {
|
export class IndexPattern implements IIndexPattern {
|
||||||
public id?: string;
|
public id: string;
|
||||||
public title: string = '';
|
public title: string = '';
|
||||||
public viewName: string = '';
|
public viewName: string = '';
|
||||||
public fieldFormatMap: Record<string, any>;
|
public fieldFormatMap: Record<string, any>;
|
||||||
|
|
|
@ -174,7 +174,7 @@ export interface FieldSpec {
|
||||||
export type IndexPatternFieldMap = Record<string, FieldSpec>;
|
export type IndexPatternFieldMap = Record<string, FieldSpec>;
|
||||||
|
|
||||||
export interface IndexPatternSpec {
|
export interface IndexPatternSpec {
|
||||||
id?: string;
|
id: string;
|
||||||
version?: string;
|
version?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
intervalName?: string;
|
intervalName?: string;
|
||||||
|
|
|
@ -15,12 +15,14 @@ interface TableProps {
|
||||||
onChangeSortOrder?: (sortOrder: SortOrder[]) => void;
|
onChangeSortOrder?: (sortOrder: SortOrder[]) => void;
|
||||||
onMoveColumn?: (name: string, index: number) => void;
|
onMoveColumn?: (name: string, index: number) => void;
|
||||||
onRemoveColumn?: (name: string) => void;
|
onRemoveColumn?: (name: string) => void;
|
||||||
|
onAddColumn?: (name: string) => void;
|
||||||
|
document: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageCount = 50;
|
const pageCount = 50;
|
||||||
|
|
||||||
const Table: React.FC<TableProps> = ({ columns, hits, sortOrder, indexPattern, onFilter, onMoveColumn,
|
const Table: React.FC<TableProps> = ({ columns, hits, sortOrder, indexPattern, onFilter, onMoveColumn, onAddColumn,
|
||||||
onRemoveColumn, onChangeSortOrder }) => {
|
onRemoveColumn, onChangeSortOrder, document }) => {
|
||||||
const [scrollState, setScrollState] = useState({limit: pageCount, hasMore: true});
|
const [scrollState, setScrollState] = useState({limit: pageCount, hasMore: true});
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
setScrollState({
|
setScrollState({
|
||||||
|
@ -46,7 +48,7 @@ const Table: React.FC<TableProps> = ({ columns, hits, sortOrder, indexPattern, o
|
||||||
<div>
|
<div>
|
||||||
{hits.length ? (
|
{hits.length ? (
|
||||||
<div>
|
<div>
|
||||||
<table className="kbn-table table" data-test-subj="docTable">
|
<table className="kbn-table table">
|
||||||
<thead>
|
<thead>
|
||||||
<TableHeader columns={columns}
|
<TableHeader columns={columns}
|
||||||
defaultSortOrder={''}
|
defaultSortOrder={''}
|
||||||
|
@ -66,9 +68,10 @@ const Table: React.FC<TableProps> = ({ columns, hits, sortOrder, indexPattern, o
|
||||||
hideTimeColumn={false}
|
hideTimeColumn={false}
|
||||||
indexPattern={indexPattern}
|
indexPattern={indexPattern}
|
||||||
isShortDots={false}
|
isShortDots={false}
|
||||||
onAddColumn={()=>{}}
|
onAddColumn={onAddColumn}
|
||||||
onRemoveColumn={()=>{}}
|
onRemoveColumn={onRemoveColumn}
|
||||||
row={row}
|
row={row}
|
||||||
|
document={document}
|
||||||
/>
|
/>
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
import {EuiIcon} from '@elastic/eui';
|
import {EuiIcon} from '@elastic/eui';
|
||||||
import { DocViewer } from '../../doc_viewer/doc_viewer';
|
import { DocViewer } from '../../doc_viewer/doc_viewer';
|
||||||
|
import {Drawer, Button, Menu,Dropdown, Icon, Popconfirm, message,Descriptions, Popover, Input} from 'antd';
|
||||||
|
import Editor from "@monaco-editor/react";
|
||||||
|
import {useState, useRef} from 'react';
|
||||||
|
|
||||||
|
function generateNewID(id: string) {
|
||||||
|
return id.slice(0, 14) + Math.random().toString(36).substr(2, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
columns: string[];
|
columns: string[];
|
||||||
|
@ -8,6 +17,7 @@ interface Props {
|
||||||
onFilter: (field: any, values: any, operation: any) => void;
|
onFilter: (field: any, values: any, operation: any) => void;
|
||||||
onAddColumn?: (name: string) => void;
|
onAddColumn?: (name: string) => void;
|
||||||
onRemoveColumn?: (name: string) => void;
|
onRemoveColumn?: (name: string) => void;
|
||||||
|
document: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Detail({
|
export function Detail({
|
||||||
|
@ -17,7 +27,59 @@ export function Detail({
|
||||||
onFilter,
|
onFilter,
|
||||||
onAddColumn,
|
onAddColumn,
|
||||||
onRemoveColumn,
|
onRemoveColumn,
|
||||||
|
document,
|
||||||
}:Props){
|
}:Props){
|
||||||
|
const [editorVisible, setEditorVisble] = useState(false);
|
||||||
|
const editorRef = useRef(null);
|
||||||
|
|
||||||
|
function handleEditorDidMount(editor, monaco) {
|
||||||
|
editorRef.current = editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
const editDocumentClick = ()=>{
|
||||||
|
setEditorVisble(true)
|
||||||
|
}
|
||||||
|
const editCancelClick = ()=>{
|
||||||
|
setEditorVisble(false)
|
||||||
|
}
|
||||||
|
const saveDocumentClick = async (docID?: string)=>{
|
||||||
|
const value = editorRef.current?.getValue();
|
||||||
|
let source = {}
|
||||||
|
try {
|
||||||
|
source = JSON.parse(value)
|
||||||
|
} catch (error) {
|
||||||
|
message.error('wrong json format')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const res = await document.saveDocument({
|
||||||
|
_index: row._index,
|
||||||
|
_id: docID || row._id,
|
||||||
|
_type: row._type,
|
||||||
|
_source: source
|
||||||
|
})
|
||||||
|
if(!res.error) setEditorVisble(false)
|
||||||
|
}
|
||||||
|
const deleteDocumentClick = ()=>{
|
||||||
|
document.deleteDocument({
|
||||||
|
_index: row._index,
|
||||||
|
_id: row._id,
|
||||||
|
_type: row._type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const menu = (
|
||||||
|
<Menu>
|
||||||
|
<Menu.Item key="Edit" onClick={editDocumentClick}>
|
||||||
|
<a> Edit </a>
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item key="Delete">
|
||||||
|
<Popconfirm title="sure to delete" onConfirm={()=>{
|
||||||
|
deleteDocumentClick();
|
||||||
|
}}><a> Delete </a></Popconfirm>
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<td colSpan={ columns.length + 2 }>
|
<td colSpan={ columns.length + 2 }>
|
||||||
<div className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--justifyContentSpaceBetween">
|
<div className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--justifyContentSpaceBetween">
|
||||||
|
@ -34,9 +96,49 @@ export function Detail({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="euiFlexItem euiFlexItem--flexGrowZero euiText euiText--small">
|
<div className="euiFlexItem euiFlexItem--flexGrowZero euiText euiText--small">
|
||||||
<div className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow">
|
<div className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow">
|
||||||
|
<Drawer title="Edit document" visible={editorVisible} width="640" destroyOnClose={true}
|
||||||
|
onClose={()=>{setEditorVisble(false)}}>
|
||||||
|
<Descriptions>
|
||||||
|
<Descriptions.Item label="_index">{row._index}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="_id">{row._id}</Descriptions.Item>
|
||||||
|
</Descriptions>
|
||||||
|
<Editor
|
||||||
|
height="70vh"
|
||||||
|
theme="vs-light"
|
||||||
|
language="json"
|
||||||
|
options={{
|
||||||
|
minimap: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
tabSize: 2,
|
||||||
|
wordBasedSuggestions: true,
|
||||||
|
}}
|
||||||
|
value={JSON.stringify(row._source, null, 2)}
|
||||||
|
onMount={handleEditorDidMount}
|
||||||
|
/>
|
||||||
|
<div style={{display:'flex', height: '10vh', alignItems:'center', justifyContent:'center'}}>
|
||||||
|
<div style={{marginLeft:'auto'}} >
|
||||||
|
<Button onClick={editCancelClick} style={{marginRight:5}}>Cancel</Button>
|
||||||
|
{/* <Button type="primary" onClick={()=>{}} style={{marginRight:5}}>Save as New</Button> */}
|
||||||
|
<SaveAsNewButton docID={row._id} saveDocumentClick={saveDocumentClick}/>
|
||||||
|
<Button type="primary" onClick={()=>{saveDocumentClick()}} >Save</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Drawer>
|
||||||
<div className="euiFlexItem euiFlexItem--flexGrowZero euiText euiText--small">
|
<div className="euiFlexItem euiFlexItem--flexGrowZero euiText euiText--small">
|
||||||
|
{/* <a
|
||||||
|
className="euiLink"
|
||||||
|
onClick={()=>{setEditorVisble(true)}}
|
||||||
|
>Edit document</a> */}
|
||||||
|
<Dropdown overlay={menu} >
|
||||||
|
<a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
|
||||||
|
Operation <Icon type="down" />
|
||||||
|
</a>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
{/* <div className="euiFlexItem euiFlexItem--flexGrowZero euiText euiText--small">
|
||||||
<a
|
<a
|
||||||
className="euiLink"
|
className="euiLink"
|
||||||
>View surrounding documents</a>
|
>View surrounding documents</a>
|
||||||
|
@ -45,9 +147,9 @@ export function Detail({
|
||||||
<a
|
<a
|
||||||
className="euiLink"
|
className="euiLink"
|
||||||
>View single document</a>
|
>View single document</a>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</div> */}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-test-subj="docViewer">
|
<div data-test-subj="docViewer">
|
||||||
<DocViewer
|
<DocViewer
|
||||||
|
@ -62,5 +164,29 @@ export function Detail({
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const SaveAsNewButton = ({docID, saveDocumentClick}:any)=>{
|
||||||
|
const newID = generateNewID(docID);
|
||||||
|
const [newDocID, setNewDocID] = useState(newID)
|
||||||
|
const content = (<div style={{width: 200}}>
|
||||||
|
<div><Input value={newDocID} onChange={(e)=>{
|
||||||
|
setNewDocID(e.target.value)
|
||||||
|
}} /></div>
|
||||||
|
<div style={{marginTop:10}}><Button onClick={()=>{
|
||||||
|
saveDocumentClick(newDocID)
|
||||||
|
}}>确定</Button></div>
|
||||||
|
</div>)
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
content={content}
|
||||||
|
title="Please input new ID"
|
||||||
|
trigger="click"
|
||||||
|
// visible={this.state.visible}
|
||||||
|
// onVisibleChange={this.handleVisibleChange}
|
||||||
|
>
|
||||||
|
<Button style={{marginRight:5}} type="primary">Save as new</Button>
|
||||||
|
</Popover>
|
||||||
)
|
)
|
||||||
}
|
}
|
|
@ -13,6 +13,7 @@ interface Props {
|
||||||
onAddColumn?: (name: string) => void;
|
onAddColumn?: (name: string) => void;
|
||||||
onRemoveColumn?: (name: string) => void;
|
onRemoveColumn?: (name: string) => void;
|
||||||
row: any;
|
row: any;
|
||||||
|
document: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TableRow({
|
export function TableRow({
|
||||||
|
@ -24,6 +25,7 @@ export function TableRow({
|
||||||
onAddColumn,
|
onAddColumn,
|
||||||
onRemoveColumn,
|
onRemoveColumn,
|
||||||
row,
|
row,
|
||||||
|
document
|
||||||
}:Props){
|
}:Props){
|
||||||
const mapping = indexPattern.fields.getByName;
|
const mapping = indexPattern.fields.getByName;
|
||||||
const [open,setOpen] = useState(false);
|
const [open,setOpen] = useState(false);
|
||||||
|
@ -60,6 +62,7 @@ export function TableRow({
|
||||||
<Detail columns={columns}
|
<Detail columns={columns}
|
||||||
indexPattern={indexPattern}
|
indexPattern={indexPattern}
|
||||||
row={row}
|
row={row}
|
||||||
|
document={document}
|
||||||
onFilter={onFilter}
|
onFilter={onFilter}
|
||||||
onAddColumn={onAddColumn}
|
onAddColumn={onAddColumn}
|
||||||
onRemoveColumn={onRemoveColumn}/>
|
onRemoveColumn={onRemoveColumn}/>
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
@import '../../../../../core/public/variables.scss';
|
@import '../../../../../core/public/variables.scss';
|
||||||
.kbnDocViewerTable {
|
.kbnDocViewerTable {
|
||||||
margin-top: $euiSizeS;
|
margin-top: $euiSizeS;
|
||||||
|
font-size: 12px;
|
||||||
|
.kbnDocViewer__buttons{
|
||||||
|
padding-top: 0px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.kbnDocViewer {
|
.kbnDocViewer {
|
||||||
|
|
|
@ -51,8 +51,8 @@ export class DocViewerTab extends React.Component<Props, State> {
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: Props, nextState: State) {
|
shouldComponentUpdate(nextProps: Props, nextState: State) {
|
||||||
return (
|
return (
|
||||||
nextProps.renderProps.hit._id !== this.props.renderProps.hit._id ||
|
nextProps.renderProps.hit !== this.props.renderProps.hit ||
|
||||||
nextProps.id !== this.props.id ||
|
nextProps.id !== this.props.id || nextProps.renderProps.columns !== this.props.renderProps.columns ||
|
||||||
nextState.hasError
|
nextState.hasError
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ export function DocViewTableRow({
|
||||||
<DocViewTableRowBtnCollapse onClick={onToggleCollapse} isCollapsed={isCollapsed} />
|
<DocViewTableRowBtnCollapse onClick={onToggleCollapse} isCollapsed={isCollapsed} />
|
||||||
)}
|
)}
|
||||||
{displayUnderscoreWarning && <DocViewTableRowIconUnderscore />}
|
{displayUnderscoreWarning && <DocViewTableRowIconUnderscore />}
|
||||||
{displayNoMappingWarning && <DocViewTableRowIconNoMapping />}
|
{/* {displayNoMappingWarning && <DocViewTableRowIconNoMapping />} */}
|
||||||
<div
|
<div
|
||||||
className={valueClassName}
|
className={valueClassName}
|
||||||
data-test-subj={`tableDocViewRow-${field}-value`}
|
data-test-subj={`tableDocViewRow-${field}-value`}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { i18n } from '@kbn/i18n';
|
|
||||||
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
|
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -26,9 +25,7 @@ export interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DocViewTableRowBtnCollapse({ onClick, isCollapsed }: Props) {
|
export function DocViewTableRowBtnCollapse({ onClick, isCollapsed }: Props) {
|
||||||
const label = i18n.translate('discover.docViews.table.toggleFieldDetails', {
|
const label = 'Toggle field details';
|
||||||
defaultMessage: 'Toggle field details',
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<EuiToolTip content={label}>
|
<EuiToolTip content={label}>
|
||||||
<EuiButtonIcon
|
<EuiButtonIcon
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from '@kbn/i18n/react';
|
|
||||||
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
|
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
|
@ -28,23 +26,15 @@ export interface Props {
|
||||||
|
|
||||||
export function DocViewTableRowBtnFilterAdd({ onClick, disabled = false }: Props) {
|
export function DocViewTableRowBtnFilterAdd({ onClick, disabled = false }: Props) {
|
||||||
const tooltipContent = disabled ? (
|
const tooltipContent = disabled ? (
|
||||||
<FormattedMessage
|
"Unindexed fields can not be searched"
|
||||||
id="discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip"
|
|
||||||
defaultMessage="Unindexed fields can not be searched"
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage
|
"Filter for value"
|
||||||
id="discover.docViews.table.filterForValueButtonTooltip"
|
|
||||||
defaultMessage="Filter for value"
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EuiToolTip content={tooltipContent}>
|
<EuiToolTip content={tooltipContent}>
|
||||||
<EuiButtonIcon
|
<EuiButtonIcon
|
||||||
aria-label={i18n.translate('discover.docViews.table.filterForValueButtonAriaLabel', {
|
aria-label='Filter for value'
|
||||||
defaultMessage: 'Filter for value',
|
|
||||||
})}
|
|
||||||
className="kbnDocViewer__actionButton"
|
className="kbnDocViewer__actionButton"
|
||||||
data-test-subj="addInclusiveFilterButton"
|
data-test-subj="addInclusiveFilterButton"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from '@kbn/i18n/react';
|
|
||||||
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
|
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
|
@ -34,29 +32,18 @@ export function DocViewTableRowBtnFilterExists({
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const tooltipContent = disabled ? (
|
const tooltipContent = disabled ? (
|
||||||
scripted ? (
|
scripted ? (
|
||||||
<FormattedMessage
|
"Unable to filter for presence of scripted fields"
|
||||||
id="discover.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip"
|
|
||||||
defaultMessage="Unable to filter for presence of scripted fields"
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage
|
"Unable to filter for presence of meta fields"
|
||||||
id="discover.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip"
|
|
||||||
defaultMessage="Unable to filter for presence of meta fields"
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage
|
"Filter for field present"
|
||||||
id="discover.docViews.table.filterForFieldPresentButtonTooltip"
|
|
||||||
defaultMessage="Filter for field present"
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EuiToolTip content={tooltipContent}>
|
<EuiToolTip content={tooltipContent}>
|
||||||
<EuiButtonIcon
|
<EuiButtonIcon
|
||||||
aria-label={i18n.translate('discover.docViews.table.filterForFieldPresentButtonAriaLabel', {
|
aria-label='Filter for field present'
|
||||||
defaultMessage: 'Filter for field present',
|
|
||||||
})}
|
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className="kbnDocViewer__actionButton"
|
className="kbnDocViewer__actionButton"
|
||||||
data-test-subj="addExistsFilterButton"
|
data-test-subj="addExistsFilterButton"
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from '@kbn/i18n/react';
|
|
||||||
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
|
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
|
@ -28,23 +26,15 @@ export interface Props {
|
||||||
|
|
||||||
export function DocViewTableRowBtnFilterRemove({ onClick, disabled = false }: Props) {
|
export function DocViewTableRowBtnFilterRemove({ onClick, disabled = false }: Props) {
|
||||||
const tooltipContent = disabled ? (
|
const tooltipContent = disabled ? (
|
||||||
<FormattedMessage
|
"Unindexed fields can not be searched"
|
||||||
id="discover.docViews.table.unindexedFieldsCanNotBeSearchedTooltip"
|
|
||||||
defaultMessage="Unindexed fields can not be searched"
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage
|
"Filter out value"
|
||||||
id="discover.docViews.table.filterOutValueButtonTooltip"
|
|
||||||
defaultMessage="Filter out value"
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EuiToolTip content={tooltipContent}>
|
<EuiToolTip content={tooltipContent}>
|
||||||
<EuiButtonIcon
|
<EuiButtonIcon
|
||||||
aria-label={i18n.translate('discover.docViews.table.filterOutValueButtonAriaLabel', {
|
aria-label= 'Filter out value'
|
||||||
defaultMessage: 'Filter out value',
|
|
||||||
})}
|
|
||||||
className="kbnDocViewer__actionButton"
|
className="kbnDocViewer__actionButton"
|
||||||
data-test-subj="removeInclusiveFilterButton"
|
data-test-subj="removeInclusiveFilterButton"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from '@kbn/i18n/react';
|
|
||||||
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
|
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
|
@ -31,9 +29,7 @@ export function DocViewTableRowBtnToggleColumn({ onClick, active, disabled = fal
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
return (
|
return (
|
||||||
<EuiButtonIcon
|
<EuiButtonIcon
|
||||||
aria-label={i18n.translate('discover.docViews.table.toggleColumnInTableButtonAriaLabel', {
|
aria-label= 'Toggle column in table'
|
||||||
defaultMessage: 'Toggle column in table',
|
|
||||||
})}
|
|
||||||
className="kbnDocViewer__actionButton"
|
className="kbnDocViewer__actionButton"
|
||||||
data-test-subj="toggleColumnButton"
|
data-test-subj="toggleColumnButton"
|
||||||
disabled
|
disabled
|
||||||
|
@ -44,17 +40,10 @@ export function DocViewTableRowBtnToggleColumn({ onClick, active, disabled = fal
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<EuiToolTip
|
<EuiToolTip
|
||||||
content={
|
content="Toggle column in table"
|
||||||
<FormattedMessage
|
|
||||||
id="discover.docViews.table.toggleColumnInTableButtonTooltip"
|
|
||||||
defaultMessage="Toggle column in table"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<EuiButtonIcon
|
<EuiButtonIcon
|
||||||
aria-label={i18n.translate('discover.docViews.table.toggleColumnInTableButtonAriaLabel', {
|
aria-label= 'Toggle column in table'
|
||||||
defaultMessage: 'Toggle column in table',
|
|
||||||
})}
|
|
||||||
aria-pressed={active}
|
aria-pressed={active}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className="kbnDocViewer__actionButton"
|
className="kbnDocViewer__actionButton"
|
||||||
|
|
|
@ -18,19 +18,11 @@
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { EuiIconTip } from '@elastic/eui';
|
import { EuiIconTip } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
|
||||||
|
|
||||||
export function DocViewTableRowIconNoMapping() {
|
export function DocViewTableRowIconNoMapping() {
|
||||||
const ariaLabel = i18n.translate('discover.docViews.table.noCachedMappingForThisFieldAriaLabel', {
|
const ariaLabel = 'Warning';
|
||||||
defaultMessage: 'Warning',
|
const tooltipContent =
|
||||||
});
|
'No cached mapping for this field. Refresh field list from the Management > Index Patterns page';
|
||||||
const tooltipContent = i18n.translate(
|
|
||||||
'discover.docViews.table.noCachedMappingForThisFieldTooltip',
|
|
||||||
{
|
|
||||||
defaultMessage:
|
|
||||||
'No cached mapping for this field. Refresh field list from the Management > Index Patterns page',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<EuiIconTip
|
<EuiIconTip
|
||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
|
|
|
@ -18,22 +18,10 @@
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { EuiIconTip } from '@elastic/eui';
|
import { EuiIconTip } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
|
||||||
|
|
||||||
export function DocViewTableRowIconUnderscore() {
|
export function DocViewTableRowIconUnderscore() {
|
||||||
const ariaLabel = i18n.translate(
|
const ariaLabel = 'Warning';
|
||||||
'discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedAriaLabel',
|
const tooltipContent = 'Field names beginning with _ are not supported';
|
||||||
{
|
|
||||||
defaultMessage: 'Warning',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const tooltipContent = i18n.translate(
|
|
||||||
'discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedTooltip',
|
|
||||||
{
|
|
||||||
defaultMessage: 'Field names beginning with {underscoreSign} are not supported',
|
|
||||||
values: { underscoreSign: '_' },
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EuiIconTip
|
<EuiIconTip
|
||||||
|
|
|
@ -26,6 +26,7 @@ import { createGetterSetter } from '../../kibana_utils/common/';
|
||||||
import { search } from '../../data/public';
|
import { search } from '../../data/public';
|
||||||
import { DocViewsRegistry } from './application/doc_views/doc_views_registry';
|
import { DocViewsRegistry } from './application/doc_views/doc_views_registry';
|
||||||
import { JsonCodeBlock } from './application/components/json_code_block/json_code_block';
|
import { JsonCodeBlock } from './application/components/json_code_block/json_code_block';
|
||||||
|
import { DocViewTable } from './application/components/table/table';
|
||||||
|
|
||||||
let angularModule: any = null;
|
let angularModule: any = null;
|
||||||
let services: DiscoverServices | null = null;
|
let services: DiscoverServices | null = null;
|
||||||
|
@ -74,11 +75,11 @@ export const [getDocViewsRegistry, setDocViewsRegistry] = createGetterSetter<Doc
|
||||||
|
|
||||||
const docViewsRegistry = new DocViewsRegistry();
|
const docViewsRegistry = new DocViewsRegistry();
|
||||||
setDocViewsRegistry(docViewsRegistry);
|
setDocViewsRegistry(docViewsRegistry);
|
||||||
// docViewsRegistry.addDocView({
|
docViewsRegistry.addDocView({
|
||||||
// title: 'Table',
|
title: 'Table',
|
||||||
// order: 10,
|
order: 10,
|
||||||
// component: DocViewTable,
|
component: DocViewTable,
|
||||||
// });
|
});
|
||||||
docViewsRegistry.addDocView({
|
docViewsRegistry.addDocView({
|
||||||
title: 'JSON',
|
title: 'JSON',
|
||||||
order: 20,
|
order: 20,
|
||||||
|
|
|
@ -46,6 +46,7 @@ import clusterBg from '@/assets/cluster_bg.png';
|
||||||
|
|
||||||
export interface EditIndexPatternProps extends RouteComponentProps {
|
export interface EditIndexPatternProps extends RouteComponentProps {
|
||||||
indexPattern: IndexPattern;
|
indexPattern: IndexPattern;
|
||||||
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mappingAPILink = 'Mapping API';
|
const mappingAPILink = 'Mapping API';
|
||||||
|
@ -65,7 +66,7 @@ const confirmModalOptionsDelete = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EditIndexPattern = withRouter(
|
export const EditIndexPattern = withRouter(
|
||||||
({ indexPattern, history, location }: EditIndexPatternProps) => {
|
({ indexPattern, history, location, id }: EditIndexPatternProps) => {
|
||||||
const {
|
const {
|
||||||
uiSettings,
|
uiSettings,
|
||||||
indexPatternManagementStart,
|
indexPatternManagementStart,
|
||||||
|
@ -131,8 +132,8 @@ export const EditIndexPattern = withRouter(
|
||||||
uiSettings.set('defaultIndex', otherPatterns[0].id);
|
uiSettings.set('defaultIndex', otherPatterns[0].id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (indexPattern.id) {
|
if (indexPattern.id || id) {
|
||||||
Promise.resolve(data.indexPatterns.delete(indexPattern.id)).then(function () {
|
Promise.resolve(data.indexPatterns.delete(indexPattern.id || id)).then(function () {
|
||||||
history.push('');
|
history.push('');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ const EditIndexPatternCont: React.FC<RouteComponentProps<{ id: string }>> = ({ .
|
||||||
}, [data.indexPatterns, props.match.params.id, ]); //setBreadcrumbs
|
}, [data.indexPatterns, props.match.params.id, ]); //setBreadcrumbs
|
||||||
|
|
||||||
if (indexPattern) {
|
if (indexPattern) {
|
||||||
return <EditIndexPattern indexPattern={indexPattern} />;
|
return <EditIndexPattern indexPattern={indexPattern} id={indexPattern.id} />;
|
||||||
} else {
|
} else {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { EuiFlexGroup, EuiToolTip, EuiFlexItem, EuiTitle, EuiButtonIcon } from '@elastic/eui';
|
import { EuiFlexGroup, EuiToolTip, EuiFlexItem, EuiTitle, EuiButtonIcon } from '@elastic/eui';
|
||||||
import { IIndexPattern } from 'src/plugins/data/public';
|
import { IIndexPattern } from 'src/plugins/data/public';
|
||||||
|
import {Popconfirm} from 'antd';
|
||||||
|
|
||||||
interface IndexHeaderProps {
|
interface IndexHeaderProps {
|
||||||
indexPattern: IIndexPattern;
|
indexPattern: IIndexPattern;
|
||||||
|
@ -88,13 +89,15 @@ export function IndexHeader({
|
||||||
{deleteIndexPatternClick && (
|
{deleteIndexPatternClick && (
|
||||||
<EuiFlexItem>
|
<EuiFlexItem>
|
||||||
<EuiToolTip content={removeTooltip}>
|
<EuiToolTip content={removeTooltip}>
|
||||||
<EuiButtonIcon
|
<Popconfirm title="确定要删除?" onConfirm={deleteIndexPatternClick}>
|
||||||
color="danger"
|
<EuiButtonIcon
|
||||||
onClick={deleteIndexPatternClick}
|
color="danger"
|
||||||
iconType="trash"
|
// onClick={deleteIndexPatternClick}
|
||||||
aria-label={removeAriaLabel}
|
iconType="trash"
|
||||||
data-test-subj="deleteIndexPatternButton"
|
aria-label={removeAriaLabel}
|
||||||
/>
|
data-test-subj="deleteIndexPatternButton"
|
||||||
|
/>
|
||||||
|
</Popconfirm>
|
||||||
</EuiToolTip>
|
</EuiToolTip>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import {List} from 'antd';
|
import {List, ConfigProvider, Button} from 'antd';
|
||||||
import {AlertItem, AlertRecord} from './AlertItem';
|
import {AlertItem, AlertRecord} from './AlertItem';
|
||||||
import './alertlist.scss';
|
import './alertlist.scss';
|
||||||
import {Legend, LegendItem} from './Legend';
|
import {Legend, LegendItem} from './Legend';
|
||||||
|
import {router} from 'umi';
|
||||||
|
|
||||||
|
|
||||||
interface AlertListProps {
|
interface AlertListProps {
|
||||||
dataSource: AlertRecord[];
|
dataSource: AlertRecord[];
|
||||||
|
@ -9,6 +11,7 @@ interface AlertListProps {
|
||||||
title: string;
|
title: string;
|
||||||
onItemClick: (item: AlertRecord)=>void;
|
onItemClick: (item: AlertRecord)=>void;
|
||||||
legendItems?: LegendItem[];
|
legendItems?: LegendItem[];
|
||||||
|
onEmptyClick?: ()=>void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AlertList = ({
|
export const AlertList = ({
|
||||||
|
@ -16,38 +19,54 @@ export const AlertList = ({
|
||||||
pagination,
|
pagination,
|
||||||
title,
|
title,
|
||||||
onItemClick,
|
onItemClick,
|
||||||
legendItems
|
legendItems,
|
||||||
|
onEmptyClick,
|
||||||
}: AlertListProps)=>{
|
}: AlertListProps)=>{
|
||||||
|
if(typeof onEmptyClick !== 'function'){
|
||||||
|
onEmptyClick = ()=>{
|
||||||
|
router.push('/alerting/monitor/create-monitor');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const AlertRenderEmpty = ()=>{
|
||||||
|
return <div>
|
||||||
|
<Button type="primary" onClick={onEmptyClick}>创建监控项</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className="alert-list">
|
<div className="alert-list-layout">
|
||||||
<div className="header">
|
<div className="title">
|
||||||
<div className="title">
|
{title}
|
||||||
{title}
|
<span className="total">({pagination?.total})</span>
|
||||||
<span className="total">({pagination?.total})</span>
|
</div>
|
||||||
</div>
|
<div className="alert-list">
|
||||||
{
|
<div className="header">
|
||||||
legendItems ? ( <div className="legend">
|
{
|
||||||
<Legend items={legendItems}/>
|
legendItems ? ( <div className="legend">
|
||||||
</div>):null
|
<Legend items={legendItems}/>
|
||||||
}
|
</div>):null
|
||||||
|
}
|
||||||
</div>
|
|
||||||
<List
|
</div>
|
||||||
itemLayout="vertical"
|
<ConfigProvider renderEmpty={AlertRenderEmpty}>
|
||||||
size="large"
|
<List
|
||||||
pagination={{
|
itemLayout="vertical"
|
||||||
onChange: page => {
|
size="large"
|
||||||
console.log(page);
|
pagination={{
|
||||||
},
|
onChange: page => {
|
||||||
pageSize: 20,
|
console.log(page);
|
||||||
...pagination,
|
},
|
||||||
}}
|
pageSize: 20,
|
||||||
dataSource={dataSource}
|
...pagination,
|
||||||
renderItem={item => (
|
}}
|
||||||
<AlertItem item={item} onClick={onItemClick} />
|
dataSource={dataSource}
|
||||||
)}
|
renderItem={item => (
|
||||||
/>
|
<AlertItem item={item} onClick={onItemClick} />
|
||||||
</div>
|
)}
|
||||||
|
/>
|
||||||
|
</ConfigProvider>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,22 @@
|
||||||
padding: 10px 5px;
|
padding: 10px 5px;
|
||||||
.header{
|
.header{
|
||||||
display: flex;
|
display: flex;
|
||||||
.title{
|
|
||||||
color: #333;
|
|
||||||
font-weight:600;
|
|
||||||
padding-bottom: 6px;
|
|
||||||
.total{
|
|
||||||
color: #999;
|
|
||||||
margin-left: 15px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.legend{
|
.legend{
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alert-list-layout{
|
||||||
|
.title{
|
||||||
|
color: #333;
|
||||||
|
font-weight:600;
|
||||||
|
font-size: 16px;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
.total{
|
||||||
|
color: #999;
|
||||||
|
margin-left: 15px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -76,22 +76,26 @@ export const AlertOverview = (props: any)=>{
|
||||||
return (
|
return (
|
||||||
<div className="alert-overview">
|
<div className="alert-overview">
|
||||||
<div className="left">
|
<div className="left">
|
||||||
<AlertList dataSource={alerts.data as any}
|
<div>
|
||||||
title={formatMessage({id:'alert.overview.alertlist.title'})}
|
<AlertList dataSource={alerts.data}
|
||||||
onItemClick={onItemClick}
|
title={formatMessage({id:'alert.overview.alertlist.title'})}
|
||||||
pagination={{
|
onItemClick={onItemClick}
|
||||||
pageSize,
|
pagination={{
|
||||||
total: alerts.total,
|
pageSize,
|
||||||
onChange: onAlertPageChange,
|
total: alerts.total,
|
||||||
}}/>
|
onChange: onAlertPageChange,
|
||||||
|
}}/>
|
||||||
|
</div>
|
||||||
|
<div style={{marginTop:10}}>
|
||||||
<AlertList dataSource={historyAlerts.data}
|
<AlertList dataSource={historyAlerts.data}
|
||||||
title={formatMessage({id:'alert.overview.alertlist-history.title'})}
|
title={formatMessage({id:'alert.overview.alertlist-history.title'})}
|
||||||
onItemClick={onItemClick}
|
onItemClick={onItemClick}
|
||||||
pagination={{
|
pagination={{
|
||||||
pageSize,
|
pageSize,
|
||||||
total: historyAlerts.total,
|
total: historyAlerts.total,
|
||||||
onChange: onAlertHistoryPageChange,
|
onChange: onAlertHistoryPageChange,
|
||||||
}}/>
|
}}/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="right">
|
{/* <div className="right">
|
||||||
<div>提示</div>
|
<div>提示</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, {useEffect, useState, useMemo} from "react";
|
import React, {useEffect, useState, useMemo} from "react";
|
||||||
import {Spin, Card} from 'antd';
|
import {Spin, Card, Empty, Button} from 'antd';
|
||||||
import {Fetch} from '../../../../components/kibana/core/public/http/fetch';
|
import {Fetch} from '../../../../components/kibana/core/public/http/fetch';
|
||||||
import './overview.scss';
|
import './overview.scss';
|
||||||
import {
|
import {
|
||||||
|
@ -148,7 +148,49 @@ export default (props)=>{
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="charts">
|
||||||
|
<div style={{height:'150px'}} className="chart">
|
||||||
|
<Chart>
|
||||||
|
<Settings theme={theme} />
|
||||||
|
<Axis id="bottom" position={Position.Bottom} title="Last 3 months" showOverlappingTicks tickFormat={timeFormatter(niceTimeFormatByDay(data.metrics.last_tree_month.day))} />
|
||||||
|
<Axis
|
||||||
|
id="left"
|
||||||
|
title="Alert number"
|
||||||
|
position={Position.Left}
|
||||||
|
/>
|
||||||
|
<LineSeries
|
||||||
|
id="lines"
|
||||||
|
xScaleType={ScaleType.Time}
|
||||||
|
yScaleType={ScaleType.Linear}
|
||||||
|
xAccessor={0}
|
||||||
|
yAccessors={[1]}
|
||||||
|
data={data.metrics.last_tree_month?.data || []}
|
||||||
|
/>
|
||||||
|
</Chart>
|
||||||
|
</div>
|
||||||
|
<div style={{height:'150px', marginTop: 10}} className="chart">
|
||||||
|
<Chart>
|
||||||
|
<Settings showLegend showLegendExtra legendPosition={Position.Right} theme={theme} />
|
||||||
|
<Axis id="bottom" position={Position.Bottom} title="Top 10 cluster" showOverlappingTicks />
|
||||||
|
<Axis id="left2" title="Alert number" position={Position.Left} tickFormat={(d) => Number(d).toFixed(0)} />
|
||||||
|
|
||||||
|
<BarSeries
|
||||||
|
id="bars"
|
||||||
|
xScaleType={ScaleType.Linear}
|
||||||
|
yScaleType={ScaleType.Linear}
|
||||||
|
xAccessor="x"
|
||||||
|
yAccessors={['y']}
|
||||||
|
stackAccessors={['x']}
|
||||||
|
splitSeriesAccessors={['g']}
|
||||||
|
data={data.metrics.top_ten_cluster?.data || []}
|
||||||
|
/>
|
||||||
|
</Chart>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="alertlist-item">
|
||||||
|
{alerts.data.length == 0 && historyAlerts.data.length == 0 && <Empty description=''>
|
||||||
|
<Button>创建监控项</Button>
|
||||||
|
</Empty>}
|
||||||
<AlertList dataSource={alerts.data}
|
<AlertList dataSource={alerts.data}
|
||||||
title={formatMessage({id:'alert.overview.alertlist.title'})}
|
title={formatMessage({id:'alert.overview.alertlist.title'})}
|
||||||
legendItems={pickLegendItems(['ACTIVE','ERROR','ACKNOWLEDGED'])}
|
legendItems={pickLegendItems(['ACTIVE','ERROR','ACKNOWLEDGED'])}
|
||||||
|
@ -159,7 +201,7 @@ export default (props)=>{
|
||||||
onChange: onAlertPageChange,
|
onChange: onAlertPageChange,
|
||||||
}}/>
|
}}/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{marginTop:10}}>
|
{historyAlerts.data.length > 0 && <div className="alertlist-item">
|
||||||
<AlertList dataSource={historyAlerts.data}
|
<AlertList dataSource={historyAlerts.data}
|
||||||
title={formatMessage({id:'alert.overview.alertlist-history.title'})}
|
title={formatMessage({id:'alert.overview.alertlist-history.title'})}
|
||||||
onItemClick={onItemClick}
|
onItemClick={onItemClick}
|
||||||
|
@ -169,47 +211,11 @@ export default (props)=>{
|
||||||
total: historyAlerts.total,
|
total: historyAlerts.total,
|
||||||
onChange: onAlertHistoryPageChange,
|
onChange: onAlertHistoryPageChange,
|
||||||
}}/>
|
}}/>
|
||||||
</div>
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="right">
|
<div className="right">
|
||||||
<div style={{height:'150px'}}>
|
|
||||||
<Chart>
|
|
||||||
<Settings theme={theme} />
|
|
||||||
<Axis id="bottom" position={Position.Bottom} title="Last 3 months" showOverlappingTicks tickFormat={timeFormatter(niceTimeFormatByDay(data.metrics.last_tree_month.day))} />
|
|
||||||
<Axis
|
|
||||||
id="left"
|
|
||||||
title="Alert number"
|
|
||||||
position={Position.Left}
|
|
||||||
/>
|
|
||||||
<LineSeries
|
|
||||||
id="lines"
|
|
||||||
xScaleType={ScaleType.Time}
|
|
||||||
yScaleType={ScaleType.Linear}
|
|
||||||
xAccessor={0}
|
|
||||||
yAccessors={[1]}
|
|
||||||
data={data.metrics.last_tree_month?.data || []}
|
|
||||||
/>
|
|
||||||
</Chart>
|
|
||||||
</div>
|
|
||||||
<div style={{height:'150px', marginTop: 10}}>
|
|
||||||
<Chart>
|
|
||||||
<Settings showLegend showLegendExtra legendPosition={Position.Right} theme={theme} />
|
|
||||||
<Axis id="bottom" position={Position.Bottom} title="Top 10 cluster" showOverlappingTicks />
|
|
||||||
<Axis id="left2" title="Alert number" position={Position.Left} tickFormat={(d) => Number(d).toFixed(0)} />
|
|
||||||
|
|
||||||
<BarSeries
|
|
||||||
id="bars"
|
|
||||||
xScaleType={ScaleType.Linear}
|
|
||||||
yScaleType={ScaleType.Linear}
|
|
||||||
xAccessor="x"
|
|
||||||
yAccessors={['y']}
|
|
||||||
stackAccessors={['x']}
|
|
||||||
splitSeriesAccessors={['g']}
|
|
||||||
data={data.metrics.top_ten_cluster?.data || []}
|
|
||||||
/>
|
|
||||||
</Chart>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Spin>
|
</Spin>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
.layout{
|
.layout{
|
||||||
display: flex;
|
// display: flex;
|
||||||
.left{
|
.left{
|
||||||
display: flex;
|
// display: flex;
|
||||||
flex: 1 1 60%;
|
// flex: 1 1 60%;
|
||||||
flex-direction: column;
|
// flex-direction: column;
|
||||||
.state-count{
|
.state-count{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -21,9 +21,19 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
.alertlist-item{
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.charts{
|
||||||
|
display: flex;
|
||||||
|
margin-top: 25px;
|
||||||
|
>.chart{
|
||||||
|
flex: 1 1 50%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.right{
|
.right{
|
||||||
flex: 1 1 40%;
|
flex: 1 1 40%;
|
||||||
|
@ -31,6 +41,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.overview-wrapper {
|
.overview-wrapper {
|
||||||
padding: 10px;
|
padding: 20px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
|
@ -227,7 +227,7 @@ class Overview extends React.Component {
|
||||||
>
|
>
|
||||||
<Card.Meta title='存储空间' className={styles.title} />
|
<Card.Meta title='存储空间' className={styles.title} />
|
||||||
<div>
|
<div>
|
||||||
<span className={styles.total}>{totalStoreSize.size}</span><span className={styles.unit}>{totalStoreSize.unit}</span>
|
<span className={styles.total}>{totalStoreSize.size || '-'}</span><span className={styles.unit}>{totalStoreSize.unit}</span>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
@ -31,7 +31,7 @@ import * as styles from './discover.scss';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { connect } from 'dva';
|
import { connect } from 'dva';
|
||||||
|
|
||||||
import { Card, Spin } from 'antd';
|
import { Card, Spin, message } from 'antd';
|
||||||
// import DiscoverGrid from './Components/discover_grid';
|
// import DiscoverGrid from './Components/discover_grid';
|
||||||
import {flattenHitWrapper} from '../../components/kibana/data/common/index_patterns/index_patterns';
|
import {flattenHitWrapper} from '../../components/kibana/data/common/index_patterns/index_patterns';
|
||||||
import {getStateColumnActions} from '../../components/kibana/discover/public/application/angular/doc_table/actions/columns';
|
import {getStateColumnActions} from '../../components/kibana/discover/public/application/angular/doc_table/actions/columns';
|
||||||
|
@ -56,8 +56,6 @@ const SidebarMemoized = React.memo(DiscoverSidebar);
|
||||||
const {filterManager, queryStringManager, timefilter, storage, getEsQuery, getSearchParams,
|
const {filterManager, queryStringManager, timefilter, storage, getEsQuery, getSearchParams,
|
||||||
intervalOptions, getTimeBuckets, fetchESRequest, services} = getContext();
|
intervalOptions, getTimeBuckets, fetchESRequest, services} = getContext();
|
||||||
|
|
||||||
//const histogramData = buildPointSeriesData(chartTable, dimensions);
|
|
||||||
|
|
||||||
const SearchBar = createSearchBar();
|
const SearchBar = createSearchBar();
|
||||||
|
|
||||||
|
|
||||||
|
@ -246,7 +244,7 @@ const Discover = (props)=>{
|
||||||
state,
|
state,
|
||||||
useNewFieldsApi:false,
|
useNewFieldsApi:false,
|
||||||
}),
|
}),
|
||||||
[indexPattern, state]
|
[indexPattern,state]
|
||||||
);
|
);
|
||||||
|
|
||||||
const collapseIcon = useRef(null);
|
const collapseIcon = useRef(null);
|
||||||
|
@ -309,6 +307,41 @@ const Discover = (props)=>{
|
||||||
const hits = searchRes.hits.total?.value || searchRes.hits.total;
|
const hits = searchRes.hits.total?.value || searchRes.hits.total;
|
||||||
const resetQuery = ()=>{};
|
const resetQuery = ()=>{};
|
||||||
const showDatePicker = indexPattern.timeFieldName != "";
|
const showDatePicker = indexPattern.timeFieldName != "";
|
||||||
|
|
||||||
|
const saveDocument = useCallback(async ({_index, _id, _type, _source})=>{
|
||||||
|
const {http} = getContext();
|
||||||
|
const res = await http.put(`/elasticsearch/${props.selectedCluster.id}/doc/${_index}/${_id}`, {
|
||||||
|
prependBasePath: false,
|
||||||
|
query: {
|
||||||
|
_type,
|
||||||
|
},
|
||||||
|
body: JSON.stringify(_source),
|
||||||
|
});
|
||||||
|
if(res.error){
|
||||||
|
message.error(res.error)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
message.success('saved successfully');
|
||||||
|
updateQuery()
|
||||||
|
return res
|
||||||
|
},[props.selectedCluster])
|
||||||
|
|
||||||
|
const deleteDocument = useCallback(async ({_index, _id, _type})=>{
|
||||||
|
const {http} = getContext();
|
||||||
|
const res = await http.delete(`/elasticsearch/${props.selectedCluster.id}/doc/${_index}/${_id}`, {
|
||||||
|
prependBasePath: false,
|
||||||
|
query: {
|
||||||
|
_type,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(res.error){
|
||||||
|
message.error(res.error)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
message.success('deleted successfully');
|
||||||
|
updateQuery()
|
||||||
|
return res
|
||||||
|
},[props.selectedCluster])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card bordered={false}>
|
<Card bordered={false}>
|
||||||
|
@ -495,7 +528,9 @@ const Discover = (props)=>{
|
||||||
onFilter={onAddFilter}
|
onFilter={onAddFilter}
|
||||||
onRemoveColumn={onRemoveColumn}
|
onRemoveColumn={onRemoveColumn}
|
||||||
onMoveColumn={onMoveColumn}
|
onMoveColumn={onMoveColumn}
|
||||||
|
onAddColumn={onAddColumn}
|
||||||
onChangeSortOrder={onSort}
|
onChangeSortOrder={onSort}
|
||||||
|
document={{saveDocument, deleteDocument}}
|
||||||
hits={rows}/>
|
hits={rows}/>
|
||||||
</div>
|
</div>
|
||||||
):null}
|
):null}
|
||||||
|
|
|
@ -383,14 +383,10 @@ class EditableCell extends React.Component {
|
||||||
|
|
||||||
getFieldType = (record, key)=>{
|
getFieldType = (record, key)=>{
|
||||||
const {doclist} = this.props;
|
const {doclist} = this.props;
|
||||||
// if(!doclist.mappings[record._index]){
|
|
||||||
// console.log(record, doclist.mappings)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
let properties = null;
|
let properties = null;
|
||||||
let _type = record._type || doclist._type;
|
let _type = record._type || doclist._type;
|
||||||
if(typeof _type !== 'undefined' && _type !== '' && _type !== '_doc'){
|
if(typeof _type !== 'undefined' && _type !== '' && _type !== '_doc'){
|
||||||
properties = doclist.mappings[record._index].mappings[_type].properties;
|
properties = doclist.mappings[record._index].mappings[_type]?.properties || {};
|
||||||
}else{
|
}else{
|
||||||
properties = doclist.mappings[record._index].mappings.properties;
|
properties = doclist.mappings[record._index].mappings.properties;
|
||||||
}
|
}
|
||||||
|
@ -565,9 +561,10 @@ class EditableCell extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@connect(({document,cluster})=>({
|
@connect(({document,global})=>({
|
||||||
document,
|
document,
|
||||||
cluster,
|
clusterID: global.selectedClusterID,
|
||||||
|
cluster: global.selectedCluster,
|
||||||
}))
|
}))
|
||||||
@Form.create()
|
@Form.create()
|
||||||
class Doucment extends React.Component {
|
class Doucment extends React.Component {
|
||||||
|
@ -580,10 +577,13 @@ class Doucment extends React.Component {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fetchData = (params) => {
|
fetchData = (params) => {
|
||||||
const {dispatch} = this.props;
|
const {dispatch, clusterID} = this.props;
|
||||||
return dispatch({
|
return dispatch({
|
||||||
type: 'document/fetchDocList',
|
type: 'document/fetchDocList',
|
||||||
payload: params,
|
payload: {
|
||||||
|
...params,
|
||||||
|
clusterID
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,38 +595,28 @@ class Doucment extends React.Component {
|
||||||
langDisposer.dispose();
|
langDisposer.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentDidMount(){
|
componentDidUpdate(oldProps,newState,snapshot){
|
||||||
// initEditor()
|
if(oldProps.clusterID != this.props.clusterID){
|
||||||
const {location, dispatch } = this.props;
|
this.initData()
|
||||||
//console.log(match, location);
|
|
||||||
let index = location.query.index;
|
|
||||||
let cluster = location.query.cluster || 'single-es';
|
|
||||||
if(!cluster){
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
initData = ()=>{
|
||||||
|
const {dispatch, clusterID} = this.props;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'document/fetchMappings',
|
type: 'document/fetchMappings',
|
||||||
payload: {
|
payload: {
|
||||||
cluster,
|
clusterID,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'document/fetchIndices',
|
type: 'document/fetchIndices',
|
||||||
payload: {
|
payload: {
|
||||||
cluster,
|
clusterID,
|
||||||
}
|
}
|
||||||
}).then(()=>{
|
|
||||||
if(!index){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.fetchData({
|
|
||||||
pageSize: 10,
|
|
||||||
pageIndex: 1,
|
|
||||||
cluster,
|
|
||||||
index,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
componentDidMount(){
|
||||||
|
this.initData()
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNewClick = ()=>{
|
handleNewClick = ()=>{
|
||||||
|
@ -644,7 +634,6 @@ class Doucment extends React.Component {
|
||||||
let _index = indices[0];
|
let _index = indices[0];
|
||||||
let _type = '';
|
let _type = '';
|
||||||
if(indices.length > 0){
|
if(indices.length > 0){
|
||||||
//console.log(this.indexSelEl);
|
|
||||||
let vals = this.indexSelEl.state.value;
|
let vals = this.indexSelEl.state.value;
|
||||||
if(vals.length === 0){
|
if(vals.length === 0){
|
||||||
Modal.error({
|
Modal.error({
|
||||||
|
@ -701,9 +690,8 @@ class Doucment extends React.Component {
|
||||||
handleSearchClick = (e)=>{
|
handleSearchClick = (e)=>{
|
||||||
let value = this.keywordEl.state.value;
|
let value = this.keywordEl.state.value;
|
||||||
let index = this.indexEl.state.value;
|
let index = this.indexEl.state.value;
|
||||||
let cluster = this.clusterEl.rcSelect.state.value[0];
|
|
||||||
let filter = '';
|
let filter = '';
|
||||||
if(!cluster || !index){
|
if(!index){
|
||||||
message.error('please select cluster and index');
|
message.error('please select cluster and index');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -711,7 +699,6 @@ class Doucment extends React.Component {
|
||||||
filter = this.filterGetter();
|
filter = this.filterGetter();
|
||||||
}
|
}
|
||||||
this.fetchData({
|
this.fetchData({
|
||||||
cluster,
|
|
||||||
index,
|
index,
|
||||||
pageSize: this.props.document.pageSize,
|
pageSize: this.props.document.pageSize,
|
||||||
pageIndex: 1,
|
pageIndex: 1,
|
||||||
|
@ -719,10 +706,10 @@ class Doucment extends React.Component {
|
||||||
filter,
|
filter,
|
||||||
keyword: value,
|
keyword: value,
|
||||||
}).then(()=>{
|
}).then(()=>{
|
||||||
if(this.hashChanged){
|
// if(this.hashChanged){
|
||||||
router.push(`/data/document?cluster=${cluster}&index=${index}`);
|
// router.push(`/data/document?cluster=${cluster}&index=${index}`);
|
||||||
this.hashChanged = !this.hashChanged;
|
// this.hashChanged = !this.hashChanged;
|
||||||
}
|
// }
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -741,8 +728,9 @@ class Doucment extends React.Component {
|
||||||
// if((indices && indices.length > 1)){
|
// if((indices && indices.length > 1)){
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
const {major} = this.props.cluster;
|
const {version} = this.props.cluster;
|
||||||
if(indices && indices.length >= 0){
|
const major = version.split('.')?.[0] || '';
|
||||||
|
if(indices && indices.length >= 0 && major !=''){
|
||||||
indices = getESAPI(major).extractIndicesFromMappings(mappings).filter(item=>{
|
indices = getESAPI(major).extractIndicesFromMappings(mappings).filter(item=>{
|
||||||
if(indices.length > 0){
|
if(indices.length > 0){
|
||||||
return indices.indexOf(item.index) > -1;
|
return indices.indexOf(item.index) > -1;
|
||||||
|
@ -769,11 +757,6 @@ class Doucment extends React.Component {
|
||||||
<div>
|
<div>
|
||||||
{(indices && indices.length>0) ? (<Cascader ref={el=>{this.indexSelEl=el}} onChange={(vals)=>{this.handleResultTabKeyChange(vals[0])}} value={[resultKey]} options={indices} style={{width: 200, marginRight:5}} placeholder="please select a index">
|
{(indices && indices.length>0) ? (<Cascader ref={el=>{this.indexSelEl=el}} onChange={(vals)=>{this.handleResultTabKeyChange(vals[0])}} value={[resultKey]} options={indices} style={{width: 200, marginRight:5}} placeholder="please select a index">
|
||||||
</Cascader>) : ''}
|
</Cascader>) : ''}
|
||||||
{/*{(indices) ? (<Select ref={el=>{this.indexSelEl=el}} 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}>{formatMessage({ id: 'form.button.new' })}</Button>
|
<Button type="primary" icon="plus" onClick={this.handleNewClick}>{formatMessage({ id: 'form.button.new' })}</Button>
|
||||||
<span style={{marginLeft:20}}>
|
<span style={{marginLeft:20}}>
|
||||||
{/*Select Viewer: */}
|
{/*Select Viewer: */}
|
||||||
|
@ -806,9 +789,7 @@ class Doucment extends React.Component {
|
||||||
value: index,
|
value: index,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
const clusters = ["single-es"];
|
let {index, indices, tableMode}= this.props.document;
|
||||||
let {cluster, index, indices, tableMode}= this.props.document;
|
|
||||||
cluster = cluster || this.props.location.query.cluster || 'single-es';
|
|
||||||
index = index || this.props.location.query.index;
|
index = index || this.props.location.query.index;
|
||||||
indices = indices || [];
|
indices = indices || [];
|
||||||
|
|
||||||
|
@ -824,12 +805,7 @@ class Doucment extends React.Component {
|
||||||
<Row gutter={[16, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
|
<Row gutter={[16, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
|
||||||
<Col span={20} style={{paddingLeft:0}}>
|
<Col span={20} style={{paddingLeft:0}}>
|
||||||
<Input.Group compact>
|
<Input.Group compact>
|
||||||
<Select ref={el=>this.clusterEl=el} defaultValue={cluster} style={{width: '20%'}}>
|
<InputSelect data={clusterIndices} onChange={()=>{this.hashChanged=true;}} defaultValue={index} ref={el=>{this.indexEl=el}} placeholder="input index or index pattern" style={{width: '40%'}}/>
|
||||||
{
|
|
||||||
clusters.map(op=>(<Select.Option value={op} key={op}>{op}</Select.Option>))
|
|
||||||
}
|
|
||||||
</Select>
|
|
||||||
<InputSelect data={clusterIndices} onChange={()=>{this.hashChanged=true;}} defaultValue={index} ref={el=>{this.indexEl=el}} placeholder="input index or index pattern" style={{width: '25%'}}/>
|
|
||||||
<Input
|
<Input
|
||||||
style={{width:"40%", display: this.state.bodyDisplay === 'none' ? 'inline': 'none'}}
|
style={{width:"40%", display: this.state.bodyDisplay === 'none' ? 'inline': 'none'}}
|
||||||
ref={el=>this.keywordEl=el}
|
ref={el=>this.keywordEl=el}
|
||||||
|
|
|
@ -17,12 +17,14 @@ import {
|
||||||
Menu,
|
Menu,
|
||||||
Table,
|
Table,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
Icon, Popconfirm
|
Icon, Popconfirm,
|
||||||
|
Switch,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import Editor from '@monaco-editor/react';
|
import Editor from '@monaco-editor/react';
|
||||||
|
|
||||||
import styles from '../List/TableList.less';
|
import styles from '../List/TableList.less';
|
||||||
import {transformSettingsForApi} from '@/lib/elasticsearch/edit_settings';
|
import {transformSettingsForApi} from '@/lib/elasticsearch/edit_settings';
|
||||||
|
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
|
||||||
|
|
||||||
const FormItem = Form.Item;
|
const FormItem = Form.Item;
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
|
@ -107,8 +109,9 @@ class CreateForm extends React.Component {
|
||||||
|
|
||||||
|
|
||||||
/* eslint react/no-multi-comp:0 */
|
/* eslint react/no-multi-comp:0 */
|
||||||
@connect(({ index }) => ({
|
@connect(({ index,global }) => ({
|
||||||
index
|
index,
|
||||||
|
clusterID: global.selectedClusterID,
|
||||||
}))
|
}))
|
||||||
@Form.create()
|
@Form.create()
|
||||||
class Index extends PureComponent {
|
class Index extends PureComponent {
|
||||||
|
@ -120,6 +123,7 @@ class Index extends PureComponent {
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
editingIndex:{},
|
editingIndex:{},
|
||||||
indexActiveKey: '1',
|
indexActiveKey: '1',
|
||||||
|
showSystemIndices: false,
|
||||||
};
|
};
|
||||||
columns = [
|
columns = [
|
||||||
{
|
{
|
||||||
|
@ -137,6 +141,9 @@ class Index extends PureComponent {
|
||||||
{
|
{
|
||||||
title: '文档数',
|
title: '文档数',
|
||||||
dataIndex: 'docs_count',
|
dataIndex: 'docs_count',
|
||||||
|
render: (val)=>{
|
||||||
|
return val || 0;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '主分片数',
|
title: '主分片数',
|
||||||
|
@ -165,13 +172,18 @@ class Index extends PureComponent {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.fetchData()
|
this.fetchData()
|
||||||
}
|
}
|
||||||
|
componentDidUpdate(oldProps,newState,snapshot){
|
||||||
|
if(oldProps.clusterID != this.props.clusterID){
|
||||||
|
this.fetchData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fetchData = ()=>{
|
fetchData = ()=>{
|
||||||
const { dispatch } = this.props;
|
const { dispatch, clusterID } = this.props;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'index/fetchIndices',
|
type: 'index/fetchIndices',
|
||||||
payload: {
|
payload: {
|
||||||
cluster: 'single-es'
|
clusterID: clusterID,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -185,11 +197,12 @@ class Index extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDeleteClick = (indexName) => {
|
handleDeleteClick = (indexName) => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch,clusterID } = this.props;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'index/removeIndex',
|
type: 'index/removeIndex',
|
||||||
payload: {
|
payload: {
|
||||||
index: indexName
|
index: indexName,
|
||||||
|
clusterID,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -214,12 +227,13 @@ class Index extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleAdd = fields => {
|
handleAdd = fields => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch, clusterID} = this.props;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'index/addIndex',
|
type: 'index/addIndex',
|
||||||
payload: {
|
payload: {
|
||||||
index: fields.index,
|
index: fields.index,
|
||||||
config: JSON.parse(fields.config)
|
config: JSON.parse(fields.config || '{}'),
|
||||||
|
clusterID
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.handleModalVisible();
|
this.handleModalVisible();
|
||||||
|
@ -229,7 +243,7 @@ class Index extends PureComponent {
|
||||||
this.setState({
|
this.setState({
|
||||||
indexActiveKey: activeKey,
|
indexActiveKey: activeKey,
|
||||||
})
|
})
|
||||||
const {dispatch} = this.props;
|
const {dispatch, clusterID} = this.props;
|
||||||
if(activeKey == '2'){
|
if(activeKey == '2'){
|
||||||
if(this.props.index.mappings[indexName]){
|
if(this.props.index.mappings[indexName]){
|
||||||
return
|
return
|
||||||
|
@ -238,6 +252,7 @@ class Index extends PureComponent {
|
||||||
type: 'index/fetchMappings',
|
type: 'index/fetchMappings',
|
||||||
payload: {
|
payload: {
|
||||||
index: indexName,
|
index: indexName,
|
||||||
|
clusterID,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}else if(activeKey == '4'){
|
}else if(activeKey == '4'){
|
||||||
|
@ -248,6 +263,7 @@ class Index extends PureComponent {
|
||||||
type: 'index/fetchSettings',
|
type: 'index/fetchSettings',
|
||||||
payload: {
|
payload: {
|
||||||
index: indexName,
|
index: indexName,
|
||||||
|
clusterID,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -259,12 +275,13 @@ class Index extends PureComponent {
|
||||||
handleIndexSettingsSaveClick = (indexName)=>{
|
handleIndexSettingsSaveClick = (indexName)=>{
|
||||||
let settings = this.indexSettingsGetter();
|
let settings = this.indexSettingsGetter();
|
||||||
settings = JSON.parse(settings);
|
settings = JSON.parse(settings);
|
||||||
const {dispatch} = this.props;
|
const {dispatch,clusterID} = this.props;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'index/saveSettings',
|
type: 'index/saveSettings',
|
||||||
payload: {
|
payload: {
|
||||||
index: indexName,
|
index: indexName,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
|
clusterID,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -281,6 +298,9 @@ class Index extends PureComponent {
|
||||||
}
|
}
|
||||||
indices.push(clusterIndices[key]);
|
indices.push(clusterIndices[key]);
|
||||||
}
|
}
|
||||||
|
if(!this.state.showSystemIndices){
|
||||||
|
indices = indices.filter(item=>!item.index.startsWith('.'));
|
||||||
|
}
|
||||||
const { modalVisible, updateModalVisible, updateFormValues,editingIndex, drawerVisible } = this.state;
|
const { modalVisible, updateModalVisible, updateFormValues,editingIndex, drawerVisible } = this.state;
|
||||||
const parentMethods = {
|
const parentMethods = {
|
||||||
handleAdd: this.handleAdd,
|
handleAdd: this.handleAdd,
|
||||||
|
@ -301,7 +321,7 @@ class Index extends PureComponent {
|
||||||
const {form: { getFieldDecorator }} = this.props;
|
const {form: { getFieldDecorator }} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<PageHeaderWrapper>
|
||||||
<Card bordered={false}>
|
<Card bordered={false}>
|
||||||
<div className={styles.tableList}>
|
<div className={styles.tableList}>
|
||||||
<div className={styles.tableListForm}>
|
<div className={styles.tableListForm}>
|
||||||
|
@ -332,7 +352,9 @@ class Index extends PureComponent {
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.tableListOperator}>
|
<div className={styles.tableListOperator}>
|
||||||
|
<div style={{marginLeft:'auto'}}>显示系统索引<Switch style={{marginLeft:5}}
|
||||||
|
onChange={(checked)=>{this.setState({showSystemIndices:checked})}}
|
||||||
|
defaultChecked={this.state.showSystemIndices}/></div>
|
||||||
</div>
|
</div>
|
||||||
<Table bordered
|
<Table bordered
|
||||||
dataSource={indices}
|
dataSource={indices}
|
||||||
|
@ -357,17 +379,17 @@ class Index extends PureComponent {
|
||||||
>
|
>
|
||||||
<Tabs activeKey={this.state.indexActiveKey} onChange={(activeKey)=>{this.handleIndexTabChanged(activeKey, editingIndex.index)}}>
|
<Tabs activeKey={this.state.indexActiveKey} onChange={(activeKey)=>{this.handleIndexTabChanged(activeKey, editingIndex.index)}}>
|
||||||
<TabPane tab="概览" key="1">
|
<TabPane tab="概览" key="1">
|
||||||
<Descriptions title="General" column={2}>
|
<Descriptions column={2}>
|
||||||
<Descriptions.Item label="健康">{editingIndex.health}</Descriptions.Item>
|
<Descriptions.Item label="健康">{editingIndex.health}</Descriptions.Item>
|
||||||
<Descriptions.Item label="状态">{editingIndex.status}</Descriptions.Item>
|
<Descriptions.Item label="状态">{editingIndex.status}</Descriptions.Item>
|
||||||
<Descriptions.Item label="主分片数">{editingIndex.shards}</Descriptions.Item>
|
<Descriptions.Item label="主分片数">{editingIndex.shards}</Descriptions.Item>
|
||||||
<Descriptions.Item label="副分片数">{editingIndex.replicas}</Descriptions.Item>
|
<Descriptions.Item label="副分片数">{editingIndex.replicas}</Descriptions.Item>
|
||||||
<Descriptions.Item label="文档数">{editingIndex.docs_count}</Descriptions.Item>
|
<Descriptions.Item label="文档数">{editingIndex.docs_count}</Descriptions.Item>
|
||||||
<Descriptions.Item label="删除文档数">{editingIndex.docs_deleted}</Descriptions.Item>
|
<Descriptions.Item label="删除文档数">{editingIndex.docs_deleted}</Descriptions.Item>
|
||||||
<Descriptions.Item label="存贮大小"></Descriptions.Item>
|
<Descriptions.Item label="存贮大小">{editingIndex.store_size}</Descriptions.Item>
|
||||||
<Descriptions.Item label="主存贮大小"></Descriptions.Item>
|
<Descriptions.Item label="主存贮大小">{editingIndex.pri_store_size}</Descriptions.Item>
|
||||||
<Descriptions.Item label="别名">
|
{/* <Descriptions.Item label="别名">
|
||||||
</Descriptions.Item>
|
</Descriptions.Item> */}
|
||||||
</Descriptions>
|
</Descriptions>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<TabPane tab="Mappings" key="2">
|
<TabPane tab="Mappings" key="2">
|
||||||
|
@ -431,7 +453,7 @@ class Index extends PureComponent {
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</Fragment>
|
</PageHeaderWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {AutocompleteService} from '../../components/kibana/data/public/autocompl
|
||||||
import {FilterManager} from '../../components/kibana/data/public/query/filter_manager/filter_manager';
|
import {FilterManager} from '../../components/kibana/data/public/query/filter_manager/filter_manager';
|
||||||
import {QueryStringManager} from '../../components/kibana/data/public/query/query_string/query_string_manager';
|
import {QueryStringManager} from '../../components/kibana/data/public/query/query_string/query_string_manager';
|
||||||
import {Timefilter, TimeHistory} from '../../components/kibana/data/public/query/timefilter';
|
import {Timefilter, TimeHistory} from '../../components/kibana/data/public/query/timefilter';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect, createContext } from 'react';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import {buildEsQuery} from '../../components/kibana/data/common/es_query/es_query/build_es_query';
|
import {buildEsQuery} from '../../components/kibana/data/common/es_query/es_query/build_es_query';
|
||||||
import {getCalculateAutoTimeExpression} from '../../components/kibana/data/common/search/aggs/utils/calculate_auto_time_expression';
|
import {getCalculateAutoTimeExpression} from '../../components/kibana/data/common/search/aggs/utils/calculate_auto_time_expression';
|
||||||
|
|
|
@ -200,29 +200,28 @@ export default {
|
||||||
message.success("添加文档成功")
|
message.success("添加文档成功")
|
||||||
},
|
},
|
||||||
*fetchIndices({payload}, {call, put}){
|
*fetchIndices({payload}, {call, put}){
|
||||||
let resp = yield call(getIndices)
|
let resp = yield call(getIndices, payload)
|
||||||
if(resp.status === false){
|
if(resp.error){
|
||||||
message.warn("获取数据失败")
|
message.warn("获取数据失败")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
yield put({
|
yield put({
|
||||||
type: 'saveData',
|
type: 'saveData',
|
||||||
payload: {
|
payload: {
|
||||||
clusterIndices: resp.payload,
|
clusterIndices: resp,
|
||||||
cluster: payload.cluster,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
*fetchMappings({payload}, {call, put}){
|
*fetchMappings({payload}, {call, put}){
|
||||||
let resp = yield call(getMappings, payload);
|
let resp = yield call(getMappings, payload);
|
||||||
if(resp.status === false){
|
if(resp.error){
|
||||||
message.warn("get mappings failed")
|
message.warn("get mappings failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
yield put({
|
yield put({
|
||||||
type: 'saveData',
|
type: 'saveData',
|
||||||
payload: {
|
payload: {
|
||||||
mappings: resp.payload,
|
mappings: resp,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,48 +11,48 @@ export default {
|
||||||
},
|
},
|
||||||
effects:{
|
effects:{
|
||||||
*fetchIndices({payload}, {call, put}){
|
*fetchIndices({payload}, {call, put}){
|
||||||
let resp = yield call(getIndices)
|
let resp = yield call(getIndices, payload)
|
||||||
if(resp.status === false){
|
if(resp.error){
|
||||||
message.warn("获取数据失败")
|
message.warn("获取数据失败")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
yield put({
|
yield put({
|
||||||
type: 'saveData',
|
type: 'saveData',
|
||||||
payload: {
|
payload: {
|
||||||
clusterIndices: resp.payload,
|
clusterIndices: resp,
|
||||||
// cluster: payload.cluster,
|
// cluster: payload.cluster,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
*fetchMappings({payload}, {call, put}){
|
*fetchMappings({payload}, {call, put}){
|
||||||
let resp = yield call(getMappings, payload);
|
let resp = yield call(getMappings, payload);
|
||||||
if(resp.status === false){
|
if(resp.error){
|
||||||
message.warn("get mappings failed")
|
message.warn("get mappings failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
yield put({
|
yield put({
|
||||||
type: 'saveData',
|
type: 'saveData',
|
||||||
payload: {
|
payload: {
|
||||||
mappings: resp.payload,
|
mappings: resp,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
*fetchSettings({payload}, {call, put}){
|
*fetchSettings({payload}, {call, put}){
|
||||||
let resp = yield call(getSettings, payload);
|
let resp = yield call(getSettings, payload);
|
||||||
if(resp.status === false){
|
if(resp.error){
|
||||||
message.warn("get settings failed")
|
message.warn("get settings failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
yield put({
|
yield put({
|
||||||
type: 'saveData',
|
type: 'saveData',
|
||||||
payload: {
|
payload: {
|
||||||
settings: resp.payload,
|
settings: resp,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
*saveSettings({payload}, {call, put, select}){
|
*saveSettings({payload}, {call, put, select}){
|
||||||
let resp = yield call(updateSettings, payload);
|
let resp = yield call(updateSettings, payload);
|
||||||
if(resp.status === false){
|
if(resp.error){
|
||||||
message.warn("save settings failed")
|
message.warn("save settings failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ export default {
|
||||||
},
|
},
|
||||||
*removeIndex({payload}, {call, put, select}){
|
*removeIndex({payload}, {call, put, select}){
|
||||||
let resp = yield call(deleteIndex, payload);
|
let resp = yield call(deleteIndex, payload);
|
||||||
if(resp.status === false){
|
if(resp.error){
|
||||||
message.warn("get mappings failed")
|
message.warn("get mappings failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -82,12 +82,15 @@ export default {
|
||||||
},
|
},
|
||||||
*addIndex({payload}, {call, put, select}){
|
*addIndex({payload}, {call, put, select}){
|
||||||
let resp = yield call(createIndex, payload);
|
let resp = yield call(createIndex, payload);
|
||||||
if(resp.status === false){
|
if(resp.error){
|
||||||
message.warn("create index failed")
|
message.warn("create index failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
yield put({
|
yield put({
|
||||||
type: 'fetchIndices'
|
type: 'fetchIndices',
|
||||||
|
payload: {
|
||||||
|
clusterID: payload.clusterID,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
button {
|
button {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
message,
|
message,
|
||||||
Divider,
|
Divider,
|
||||||
Table, AutoComplete, Switch,
|
Table, AutoComplete, Switch,
|
||||||
|
Popconfirm
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
|
|
||||||
import styles from '../../List/TableList.less';
|
import styles from '../../List/TableList.less';
|
||||||
|
@ -18,42 +19,6 @@ import styles from '../../List/TableList.less';
|
||||||
const FormItem = Form.Item;
|
const FormItem = Form.Item;
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
|
|
||||||
const CreateForm = Form.create()(props => {
|
|
||||||
const { modalVisible, form, handleAdd, handleModalVisible } = props;
|
|
||||||
const okHandle = () => {
|
|
||||||
form.validateFields((err, fieldsValue) => {
|
|
||||||
if (err) return;
|
|
||||||
form.resetFields();
|
|
||||||
handleAdd(fieldsValue);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<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 UpdateForm = Form.create()(props => {
|
||||||
const { updateModalVisible, handleUpdateModalVisible, handleUpdate,values,form, indices } = props;
|
const { updateModalVisible, handleUpdateModalVisible, handleUpdate,values,form, indices } = props;
|
||||||
|
|
||||||
|
@ -156,23 +121,28 @@ class AliasManage extends PureComponent {
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{/*<a onClick={() => this.handleUpdateModalVisible(true, record)}>别名设置</a>*/}
|
{/*<a onClick={() => this.handleUpdateModalVisible(true, record)}>别名设置</a>*/}
|
||||||
{/*<Divider type="vertical" />*/}
|
{/*<Divider type="vertical" />*/}
|
||||||
<a onClick={() => {
|
<Popconfirm title="确定要删除?" onConfirm={()=>this.handleDeleteAliasClick(record)}> <a>删除</a></Popconfirm>
|
||||||
let indices = [];
|
|
||||||
for(let index of record.indexes){
|
|
||||||
indices.push(index.index);
|
|
||||||
}
|
|
||||||
let vals = {
|
|
||||||
alias: record.alias,
|
|
||||||
indices,
|
|
||||||
};
|
|
||||||
this.handleDeleteClick(vals);
|
|
||||||
}}>删除</a>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
handleDeleteAliasClick = (record)=>{
|
||||||
|
let indices = [];
|
||||||
|
for(let index of record.indexes){
|
||||||
|
indices.push(index.index);
|
||||||
|
}
|
||||||
|
let vals = {
|
||||||
|
alias: record.alias,
|
||||||
|
indices,
|
||||||
|
};
|
||||||
|
this.handleDeleteClick(vals);
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
this.fetchAliasList();
|
||||||
|
this.fetchIndices();
|
||||||
|
}
|
||||||
|
fetchAliasList = ()=>{
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'alias/fetchAliasList',
|
type: 'alias/fetchAliasList',
|
||||||
|
@ -181,6 +151,21 @@ class AliasManage extends PureComponent {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
fetchIndices = ()=>{
|
||||||
|
const { dispatch } = this.props;
|
||||||
|
dispatch({
|
||||||
|
type: 'alias/fetchIndices',
|
||||||
|
payload: {
|
||||||
|
clusterID: this.props.selectedClusterID,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
componentDidUpdate(oldProps,newState,snapshot){
|
||||||
|
if(oldProps.selectedClusterID != this.props.selectedClusterID){
|
||||||
|
this.fetchAliasList();
|
||||||
|
this.fetchIndices();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleStandardTableChange = (pagination, filtersArg, sorter) => {
|
handleStandardTableChange = (pagination, filtersArg, sorter) => {
|
||||||
|
|
||||||
|
@ -320,6 +305,7 @@ class AliasManage extends PureComponent {
|
||||||
if(this.state.keyword) {
|
if(this.state.keyword) {
|
||||||
aliasList = aliasList.filter(al=>al.alias.includes(this.state.keyword))
|
aliasList = aliasList.filter(al=>al.alias.includes(this.state.keyword))
|
||||||
}
|
}
|
||||||
|
const {indices} = this.props.alias;
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Card bordered={false}>
|
<Card bordered={false}>
|
||||||
|
@ -329,11 +315,6 @@ class AliasManage extends PureComponent {
|
||||||
<Button icon="plus" type="primary" onClick={() => this.handleUpdateModalVisible(true)}>
|
<Button icon="plus" type="primary" onClick={() => this.handleUpdateModalVisible(true)}>
|
||||||
新建
|
新建
|
||||||
</Button>
|
</Button>
|
||||||
{selectedRows.length > 0 && (
|
|
||||||
<span>
|
|
||||||
<Button onClick={() => this.handleDeleteClick()}>删除</Button>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<Table
|
<Table
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -345,8 +326,8 @@ class AliasManage extends PureComponent {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AliasIndexTable rawData={record}
|
<AliasIndexTable rawData={record}
|
||||||
handleDeleteClick={this.handleDeleteClick}
|
handleDeleteClick={this.handleDeleteClick}
|
||||||
handleUpdateModalVisible={this.handleUpdateModalVisible} data={record.indexes}/>
|
handleUpdateModalVisible={this.handleUpdateModalVisible} data={record.indexes}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
@ -360,7 +341,7 @@ class AliasManage extends PureComponent {
|
||||||
{...updateMethods}
|
{...updateMethods}
|
||||||
updateModalVisible={updateModalVisible}
|
updateModalVisible={updateModalVisible}
|
||||||
values={updateFormValues}
|
values={updateFormValues}
|
||||||
indices={['test-custom', 'dict']}
|
indices={indices||[]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -401,12 +382,13 @@ class AliasIndexTable extends React.Component {
|
||||||
alias: this.props.rawData.alias,
|
alias: this.props.rawData.alias,
|
||||||
})}>设置</a>
|
})}>设置</a>
|
||||||
<Divider type="vertical" />
|
<Divider type="vertical" />
|
||||||
<a onClick={() => {
|
<Popconfirm title="确定要删除?" onConfirm={() => {
|
||||||
this.props.handleDeleteClick({
|
this.props.handleDeleteClick({
|
||||||
...record,
|
...record,
|
||||||
alias: this.props.rawData.alias,
|
alias: this.props.rawData.alias,
|
||||||
});
|
});
|
||||||
}}>删除</a>
|
}}><a>删除</a>
|
||||||
|
</Popconfirm>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},]
|
},]
|
||||||
|
@ -429,7 +411,7 @@ class IndexComplete extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handleSearch = v => {
|
handleSearch = v => {
|
||||||
let data = this.props.dataSource.filter(d=>d.includes(v));
|
let data = this.props.dataSource.filter(d=>d.includes(v.replace(/\*$/, '')));
|
||||||
// if(data.length > 0 && v.length >0) {
|
// if(data.length > 0 && v.length >0) {
|
||||||
// data.push(v+'*');
|
// data.push(v+'*');
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import {getAliasList, doAlias } from '@/services/alias';
|
import {getAliasList, doAlias } from '@/services/alias';
|
||||||
|
import {getIndices } from '@/services/indices';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespace: 'alias',
|
namespace: 'alias',
|
||||||
|
@ -19,6 +20,19 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
*fetchIndices({ payload }, { call, put }) {
|
||||||
|
const res = yield call(getIndices, payload);
|
||||||
|
let indices = [];
|
||||||
|
for(let k in res){
|
||||||
|
indices.push(k);
|
||||||
|
}
|
||||||
|
yield put({
|
||||||
|
type: 'saveData',
|
||||||
|
payload: {
|
||||||
|
indices,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
*add({ payload, callback }, { call, put }) {
|
*add({ payload, callback }, { call, put }) {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
|
@ -69,7 +69,6 @@ export default {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp.payload = formatESSearchResult(resp.payload);
|
resp.payload = formatESSearchResult(resp.payload);
|
||||||
console.log(resp.payload);
|
|
||||||
resp.payload.data = resp.payload.data.map((item)=>{
|
resp.payload.data = resp.payload.data.map((item)=>{
|
||||||
item.content = utf8.decode(atob(item.content))
|
item.content = utf8.decode(atob(item.content))
|
||||||
return item;
|
return item;
|
||||||
|
|
|
@ -17,7 +17,6 @@ export default {
|
||||||
*fetchList({ payload }, { call, put , select }) {
|
*fetchList({ payload }, { call, put , select }) {
|
||||||
payload.cluster_id = yield select(state => state.global.selectedClusterID);
|
payload.cluster_id = yield select(state => state.global.selectedClusterID);
|
||||||
const res = yield call(getTemplateList, payload);
|
const res = yield call(getTemplateList, payload);
|
||||||
console.log("fetchList response:",res);
|
|
||||||
if (res.hits) {
|
if (res.hits) {
|
||||||
let newList = [];
|
let newList = [];
|
||||||
let hits = res.hits.hits || [];
|
let hits = res.hits.hits || [];
|
||||||
|
|
|
@ -12,4 +12,6 @@ export function buildQueryArgs(params){
|
||||||
argsStr = argsStr.slice(0, argsStr.length -1)
|
argsStr = argsStr.slice(0, argsStr.length -1)
|
||||||
}
|
}
|
||||||
return argsStr;
|
return argsStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ESPrefix = '/elasticsearch';
|
|
@ -1,12 +1,12 @@
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import {pathPrefix} from './common';
|
import {pathPrefix, ESPrefix} from './common';
|
||||||
|
|
||||||
export async function getDocList(params) {
|
export async function getDocList(params) {
|
||||||
params.from = (params.pageIndex - 1) * params.pageSize;
|
params.from = (params.pageIndex - 1) * params.pageSize;
|
||||||
params.size = params.pageSize;
|
params.size = params.pageSize;
|
||||||
delete params.pageSize;
|
delete params.pageSize;
|
||||||
delete params.pageIndex;
|
delete params.pageIndex;
|
||||||
return request(`${pathPrefix}/doc/${params.index}/_search`, {
|
return request(`${ESPrefix}/${params.clusterID}/doc/${params.index}/_search`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: params,
|
body: params,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,43 +1,43 @@
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import {pathPrefix} from './common';
|
import {pathPrefix, ESPrefix} from './common';
|
||||||
|
|
||||||
export async function getMappings(payload){
|
export async function getMappings(params){
|
||||||
let index = payload.index || '*'
|
let index = params.index || '*'
|
||||||
let url = `${pathPrefix}/index/${index}/_mappings`;
|
let url = `${ESPrefix}/${params.clusterID}/index/${index}/_mappings`;
|
||||||
return request(url,{
|
return request(url,{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
expirys: 0,
|
expirys: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getSettings(payload){
|
export async function getSettings(params){
|
||||||
let index = payload.index || '*'
|
let index = params.index || '*'
|
||||||
let url = `${pathPrefix}/index/${index}/_settings`;
|
let url = `${ESPrefix}/${params.clusterID}/index/${index}/_settings`;
|
||||||
return request(url,{
|
return request(url,{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
expirys: 0,
|
expirys: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateSettings(payload){
|
export async function updateSettings(params){
|
||||||
let index = payload.index
|
let index = params.index
|
||||||
let url = `${pathPrefix}/index/${index}/_settings`;
|
let url = `${ESPrefix}/${params.clusterID}/index/${index}/_settings`;
|
||||||
return request(url,{
|
return request(url,{
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: payload.settings,
|
body: params.settings,
|
||||||
expirys: 0,
|
expirys: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getIndices(params) {
|
export async function getIndices(params) {
|
||||||
return request(`${pathPrefix}/_cat/indices`, {
|
return request(`${ESPrefix}/${params.clusterID}/_cat/indices`, {
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteIndex(params) {
|
export async function deleteIndex(params) {
|
||||||
let index = params.index;
|
let index = params.index;
|
||||||
return request(`${pathPrefix}/index/${index}`, {
|
return request(`${ESPrefix}/${params.clusterID}/index/${index}`, {
|
||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ export async function deleteIndex(params) {
|
||||||
|
|
||||||
export async function createIndex(params) {
|
export async function createIndex(params) {
|
||||||
let index = params.index;
|
let index = params.index;
|
||||||
return request(`${pathPrefix}/index/${index}`, {
|
return request(`${ESPrefix}/${params.clusterID}/index/${index}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: params.config
|
body: params.config
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,9 +2,8 @@ import request from '@/utils/request';
|
||||||
|
|
||||||
|
|
||||||
export async function getTemplateList(payload){
|
export async function getTemplateList(payload){
|
||||||
let url = `/elasticsearch/${payload.cluster_id}/search_template/_search?from=${payload.from}&size=${payload.size}`;
|
let url = `/elasticsearch/${payload.cluster_id}/search_template?from=${payload.from}&size=${payload.size}`;
|
||||||
payload.name && (url+= `&name=${payload.name}`);
|
payload.name && (url+= `&name=${payload.name}`);
|
||||||
console.log("url:",url);
|
|
||||||
return request(url,{
|
return request(url,{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
// body: payload,
|
// body: payload,
|
||||||
|
|
Loading…
Reference in New Issue