add code editor in doc page
This commit is contained in:
parent
a74511ad4d
commit
46bee258e2
|
@ -17,6 +17,7 @@ type docReqBody struct {
|
|||
PageSize int `json:"pageSize"`
|
||||
Filter string `json:"filter"`
|
||||
Cluster string `json:"cluster"`
|
||||
Keyword string `json:"keyword"`
|
||||
}
|
||||
|
||||
func (handler APIHandler) HandleDocumentAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
|
||||
|
@ -93,10 +94,14 @@ func (handler APIHandler) HandleDocumentAction(w http.ResponseWriter, req *http.
|
|||
}
|
||||
from := (pageIndex - 1) * pageSize
|
||||
filter := `{"match_all": {}}`
|
||||
if reqBody.Keyword != "" {
|
||||
filter = fmt.Sprintf(`{"query_string":{"query":"%s"}}`, reqBody.Keyword)
|
||||
}
|
||||
if reqBody.Filter != "" {
|
||||
filter = reqBody.Filter
|
||||
}
|
||||
query := fmt.Sprintf(`{"from":%d, "size": %d, "query": %s}`, from, pageSize, filter)
|
||||
fmt.Println(query)
|
||||
var reqBytes = []byte(query)
|
||||
resp, err := client.SearchWithRawQueryDSL(indexName, reqBytes)
|
||||
if err != nil {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"@antv/data-set": "^0.9.6",
|
||||
"@antv/g2-brush": "^0.0.2",
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"@monaco-editor/react": "^3.7.4",
|
||||
"@svgdotjs/svg.js": "^3.0.16",
|
||||
"antd": "^3.26.18",
|
||||
"antd-table-infinity": "^1.1.6",
|
||||
|
|
|
@ -1,7 +1,84 @@
|
|||
import React, { Component } from 'react';
|
||||
import React, { Component, createRef } from 'react';
|
||||
import router from 'umi/router';
|
||||
import { connect } from 'dva';
|
||||
import { Col, Form, Row,Select, Input, Card,Icon, Table, InputNumber, Popconfirm,
|
||||
Divider,Button,Tooltip, Cascader } from 'antd';
|
||||
Divider,Button,Tooltip, Cascader, Modal } from 'antd';
|
||||
import Editor, {monaco} from '@monaco-editor/react';
|
||||
|
||||
import {createDependencyProposals} from './autocomplete';
|
||||
|
||||
function findParentIdentifier(textUntilPosition){
|
||||
let chars = textUntilPosition;
|
||||
let length = chars.length;
|
||||
let stack = [];
|
||||
let targetIdx = -1;
|
||||
for(let i = length-1; i>-1; i--){
|
||||
if(chars[i] == '}'){
|
||||
stack.push('}');
|
||||
}else if(chars[i] == '{'){
|
||||
if(stack.length == 0){
|
||||
targetIdx = i;
|
||||
break;
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
let foundColon = false;
|
||||
for(let i = targetIdx; i > -1; i--){
|
||||
if(chars[i] == ":"){
|
||||
targetIdx = i;
|
||||
foundColon = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!foundColon){
|
||||
return ""
|
||||
}
|
||||
let identifer = [];
|
||||
let startFound = false;
|
||||
for(let i = targetIdx; i > -1; i--){
|
||||
if((chars[i]>='a' && chars[i] <= 'z') || chars[i] == '_'){
|
||||
identifer.push(chars[i]);
|
||||
startFound = true;
|
||||
}else if(startFound){
|
||||
break;
|
||||
}
|
||||
}
|
||||
return identifer.reverse().join('');
|
||||
}
|
||||
|
||||
monaco.init().then((mi)=>{
|
||||
mi.languages.registerCompletionItemProvider('json', {
|
||||
provideCompletionItems: function(model, position) {
|
||||
// find out if we are completing a property in the 'dependencies' object.
|
||||
var textUntilPosition = model.getValueInRange({startLineNumber: 1, startColumn: 1, endLineNumber: position.lineNumber, endColumn: position.column});
|
||||
|
||||
if(textUntilPosition.indexOf('{') < 0){
|
||||
return { suggestions: [] };
|
||||
}
|
||||
|
||||
let key = findParentIdentifier(textUntilPosition);
|
||||
//console.log(key);
|
||||
// var match = textUntilPosition.match(/"match"\s*:\s*\{\s*("[^"]*"\s*:\s*"[^"]*"\s*,\s*)*([^"]*)?$/);
|
||||
// if (!match) {
|
||||
// return { suggestions: [] };
|
||||
// }
|
||||
var word = model.getWordUntilPosition(position);
|
||||
|
||||
var range = {
|
||||
startLineNumber: position.lineNumber,
|
||||
endLineNumber: position.lineNumber,
|
||||
startColumn: word.startColumn,
|
||||
endColumn: word.endColumn
|
||||
};
|
||||
return {
|
||||
suggestions: createDependencyProposals(key, range, mi)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
const EditableContext = React.createContext();
|
||||
|
@ -130,7 +207,7 @@ class EditableCell extends React.Component {
|
|||
dispatch({
|
||||
type: 'document/addDocItem',
|
||||
payload: {
|
||||
index: doclist.index,
|
||||
index: doclist._index,
|
||||
data: row,
|
||||
}
|
||||
})
|
||||
|
@ -244,22 +321,37 @@ class EditableCell extends React.Component {
|
|||
@Form.create()
|
||||
class Doucment extends React.Component {
|
||||
state={
|
||||
bodyDisplay: 'none',
|
||||
bodyDisplay: 'none',
|
||||
}
|
||||
|
||||
// constructor(props){
|
||||
// super(props);
|
||||
// this.filterGetter = createRef();
|
||||
// }
|
||||
|
||||
fetchData = (params) => {
|
||||
const {dispatch} = this.props;
|
||||
dispatch({
|
||||
return dispatch({
|
||||
type: 'document/fetchDocList',
|
||||
payload: params,
|
||||
})
|
||||
}
|
||||
|
||||
handleEditorDidMount = (_valueGetter) =>{
|
||||
this.filterGetter = _valueGetter;
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
const {location } = this.props;
|
||||
//console.log(match, location);
|
||||
let index = location.query.index || 'infini-test';
|
||||
let cluster = location.query.cluster || 'single-es';
|
||||
this.indexEl.setState({
|
||||
value: [cluster, index]
|
||||
})
|
||||
this.fetchData({
|
||||
pageSize: 10,
|
||||
pageIndex: 1,
|
||||
index: 'infini-test',
|
||||
index,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -268,6 +360,21 @@ class Doucment extends React.Component {
|
|||
if(!document.data || document.data.length == 0 || document.isAddNew){
|
||||
return;
|
||||
}
|
||||
let {indices} = document;
|
||||
let _index = indices[0];
|
||||
if(indices && indices.length > 1){
|
||||
console.log(this.indexSelEl);
|
||||
let vals = this.indexSelEl.rcSelect.state.value;
|
||||
if(vals.length == 0){
|
||||
Modal.error({
|
||||
title: '系统提示',
|
||||
content: '请选择新建文档目标索引',
|
||||
});
|
||||
return
|
||||
}else{
|
||||
_index = vals[0];
|
||||
}
|
||||
}
|
||||
let keys = Object.keys(document.data[0])
|
||||
let newDoc = {};
|
||||
for(let key of keys){
|
||||
|
@ -278,36 +385,45 @@ class Doucment extends React.Component {
|
|||
payload: {
|
||||
docItem: newDoc,
|
||||
extra: {
|
||||
isAddNew: true
|
||||
isAddNew: true,
|
||||
_index
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
handleSearchClick = (value)=>{
|
||||
const [cluster, index] = this.indexEl.state.value;
|
||||
let targetIndex = index;
|
||||
if(value != ""){
|
||||
targetIndex = value;
|
||||
let [cluster, index] = this.indexEl.state.value;
|
||||
let rewriteIndex = this.reindexEl.state.value;
|
||||
if(typeof rewriteIndex !== 'undefined' && rewriteIndex !=""){
|
||||
index = rewriteIndex;
|
||||
}
|
||||
console.log(targetIndex);
|
||||
|
||||
this.fetchData({
|
||||
cluster,
|
||||
index: targetIndex,
|
||||
index: index,
|
||||
pageSize: 10,
|
||||
pageIndex: 1,
|
||||
filter: this.filterEl.state.value,
|
||||
//filter: this.filterEl.state.value,
|
||||
filter: this.filterGetter(),
|
||||
keyword: value,
|
||||
}).then(()=>{
|
||||
if(this.hashChanged){
|
||||
router.push(`/data/doc?index=${index}`);
|
||||
this.hashChanged = !this.hashChanged;
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
renderNew = ()=>{
|
||||
const {indices} = this.props.document;
|
||||
if((indices && indices.length > 1)){
|
||||
return;
|
||||
}
|
||||
// if((indices && indices.length > 1)){
|
||||
// return;
|
||||
// }
|
||||
return (
|
||||
<div>
|
||||
{(indices && indices.length > 1) ? (<Select style={{width: 200, marginRight:5}} placeholder="please select a index">
|
||||
{(indices && indices.length > 1) ? (<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>)
|
||||
})}
|
||||
|
@ -328,25 +444,30 @@ class Doucment extends React.Component {
|
|||
{
|
||||
value: 'infini-test',
|
||||
label: 'infini-test',
|
||||
},
|
||||
{
|
||||
value: 'infini-test1',
|
||||
label: 'infini-test1',
|
||||
}
|
||||
]}];
|
||||
return (
|
||||
<div>
|
||||
<Card>
|
||||
<Row gutter={[16, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
|
||||
<Col span={20}>
|
||||
<Col span={20} style={{paddingLeft:0}}>
|
||||
<Input.Group compact>
|
||||
<Cascader
|
||||
options={options}
|
||||
ref={el=>{this.indexEl=el}}
|
||||
style={{width: '20%'}}
|
||||
onChange={(value, selectedOptions)=>{console.log(value)}}
|
||||
onChange={(values, selectedOptions)=>{this.reindexEl.setState({value: values[1]}); this.hashChanged = true;}}
|
||||
placeholder="Please select index"
|
||||
showSearch={{filter: (inputValue, path)=>path.some(option => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1) }}
|
||||
/>
|
||||
<Input ref={el=>{this.reindexEl=el}} placeholder="rewrite index or index pattern" style={{width: '20%'}}/>
|
||||
<Input.Search
|
||||
style={{width:"80%"}}
|
||||
placeholder="input rewrite index or index pattern"
|
||||
style={{width:"50%"}}
|
||||
placeholder="input search keyword"
|
||||
enterButton="execute"
|
||||
onSearch={this.handleSearchClick}
|
||||
/>
|
||||
|
@ -369,8 +490,22 @@ class Doucment extends React.Component {
|
|||
</Col>
|
||||
</Row>
|
||||
<Row style={{display: this.state.bodyDisplay}} gutter={[16, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
|
||||
<Col span={20}>
|
||||
<Input.TextArea ref={el=>{this.filterEl=el}} placeholder="input query filter (elasticsearch query DSL)" rows={8}/>
|
||||
<Col span={20} style={{border:'1px solid #e8e8e8'}}>
|
||||
{/* <Input.TextArea ref={el=>{this.filterEl=el}} placeholder="input query filter (elasticsearch query DSL)" rows={8}/> */}
|
||||
<Editor
|
||||
height="200px"
|
||||
language="json"
|
||||
theme="light"
|
||||
// value={`{"match":{"name": "cincky"}}`}
|
||||
options={{
|
||||
minimap: {
|
||||
enabled: false,
|
||||
},
|
||||
tabSize: 2,
|
||||
wordBasedSuggestions: true,
|
||||
}}
|
||||
editorDidMount={this.handleEditorDidMount}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
|
||||
function registerKeyProposals(key){
|
||||
let proposals = {
|
||||
'bool': [{
|
||||
label: 'filter',
|
||||
documentation: "filter",
|
||||
insertText: '"filter": [\n\t{}\n]',
|
||||
},{
|
||||
label: 'minimum_should_match',
|
||||
insertText: '"minimum_should_match": 1',
|
||||
},{
|
||||
label: 'must',
|
||||
insertText: '"must": [\n\t{}\n]',
|
||||
},{
|
||||
label: 'must_not',
|
||||
insertText: '"must_not": [\n\t{}\n]',
|
||||
},{
|
||||
label: 'should',
|
||||
insertText: '"should": [\n\t{}\n]',
|
||||
}],
|
||||
'multi_match':[{
|
||||
label: 'analyzer',
|
||||
insertText: '"analyzer": ""',
|
||||
},{
|
||||
label: 'boost',
|
||||
insertText: '"boost": 1',
|
||||
},{
|
||||
label: 'fuzziness',
|
||||
insertText: '"fuzziness": 1',
|
||||
},{
|
||||
label: 'minimum_should_match',
|
||||
insertText: '"minimum_should_match": 1',
|
||||
},{
|
||||
label: 'operator',
|
||||
insertText: '"operator": "and"',
|
||||
},{
|
||||
label: 'type',
|
||||
insertText: '"type": "best_fields"',
|
||||
}]
|
||||
};
|
||||
if(proposals[key]){
|
||||
return proposals[key];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function createDependencyProposals(key, range, mi) {
|
||||
if(['', 'must', 'must_not', 'should'].includes(key)){
|
||||
return queryProposals.map(p=>{
|
||||
return {
|
||||
kind: mi.languages.CompletionItemKind.Property,
|
||||
...p,
|
||||
insertTextRules: mi.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
range: range
|
||||
}
|
||||
})
|
||||
}
|
||||
return registerKeyProposals(key).map(p=>{
|
||||
return {
|
||||
kind: mi.languages.CompletionItemKind.Property,
|
||||
...p,
|
||||
insertTextRules: mi.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
range: range
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
let queryProposals = [{
|
||||
label: 'bool',
|
||||
documentation: "bool query",
|
||||
insertText: '"bool": {}',
|
||||
},{
|
||||
label: 'exists',
|
||||
documentation: "exists query",
|
||||
insertText: '"exists": {}',
|
||||
},{
|
||||
label: 'fuzzy',
|
||||
documentation: "fuzzy query",
|
||||
insertText: '"fuzzy": {\n\t"${1:FIELD}": {}\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'match',
|
||||
documentation: "match query",
|
||||
insertText: '"match": {\n\t"${1:FIELD}": "${2:TEXT}"\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'match_all',
|
||||
documentation: "match_all query",
|
||||
insertText: '"match_all": {}',
|
||||
|
||||
},{
|
||||
label: 'match_phrase',
|
||||
documentation: "match_phrease query",
|
||||
insertText: '"match_phrase": {\n\t"${1:FIELD}": "${2:PHRASE}"\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'match_phrase_prefix',
|
||||
documentation: "match_phrease query",
|
||||
insertText: '"match_phrase_prefix": {\n\t"${1:FIELD}": "${2:PREFIX}"\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'multi_match',
|
||||
documentation: "multi_match query",
|
||||
insertText: '"multi_match": {\n\t"query": "${1:}",\n\t"fields": [${2:}]\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'nested',
|
||||
documentation: "nested query",
|
||||
insertText: '"nested": {\n\t"path": "${1:path_to_nested_doc}",\n\t"query": {}\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'prefix',
|
||||
documentation: "prefix query",
|
||||
insertText: '"prefix": {\n\t"${1:FIELD}": {\n\t\t"value": "${2:}"\n\t}\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'query_string',
|
||||
documentation: "query_string query",
|
||||
insertText: '"query_string": {\n\t"default_field": "${1:FIELD}",\n\t"query": "${2:this AND that OR thus}"\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'range',
|
||||
documentation: "range query",
|
||||
insertText: '"range": {\n\t"${1:FIELD}":{\n\t\t"gte": 0,\n\t\t"lte": 10\n\t}\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'regexp',
|
||||
documentation: "regexp query",
|
||||
insertText: '"regexp": {\n\t"${1:FIELD}": "${2:REGEXP}"\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'term',
|
||||
documentation: "term query",
|
||||
insertText: '"term": {\n\t"${1:FIELD}": {\n\t\t"value": "${2:}"\n\t}\n}',
|
||||
insertTextRules: 1,
|
||||
},{
|
||||
label: 'terms',
|
||||
documentation: "terms query",
|
||||
insertText: '"terms": {\n\t"${1:FIELD}": [\n\t\t"VALUE1",\n\t\t"VALUE2"\n\t]\n}',
|
||||
insertTextRules: 1,
|
||||
},]
|
Loading…
Reference in New Issue