perf:explore 编辑功能(operator function 待完成)
This commit is contained in:
@@ -1580,7 +1580,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
getAlertListChartData:function(chartInfo,filterType){
|
getAlertListChartData:function(chartInfo,filterType){
|
||||||
this.$set(chartInfo, "param", {endpointId: this.additionalInfo.id});
|
if(this.additionalInfo){
|
||||||
|
this.$set(chartInfo, "param", {endpointId: this.additionalInfo.id});
|
||||||
|
}
|
||||||
this.$refs['editChart'+chartInfo.id][0].getAlertList(filterType);
|
this.$refs['editChart'+chartInfo.id][0].getAlertList(filterType);
|
||||||
},
|
},
|
||||||
getAlertRuleChartData(chartInfo) {
|
getAlertRuleChartData(chartInfo) {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<div class="metric-editor-popper" :style="{left:popperPos.left+'px'}">
|
<div class="metric-editor-popper" :style="{left:popperPos.left+'px'}">
|
||||||
<div class="metric-popper-main" >
|
<div class="metric-popper-main" >
|
||||||
<el-scrollbar style="height: 100%" class="ps-scroll-small" ref="scroll">
|
<el-scrollbar style="height: 100%" class="ps-scroll-small" ref="scroll">
|
||||||
<div v-for="(value, key, index) in showSuggestions" >
|
<div v-for="(key, index) in orders" >
|
||||||
<div v-html="key" class="popper-group"></div>
|
<div v-html="key" class="popper-group" v-show="showSuggestions[key]"></div>
|
||||||
<div class="popper-item" v-for="(item,i) in value" v-html="item.label" :key="item.insertText" :type="key" :value="item.insertText" @click.stop="handleItemClick(key,item,$event)"></div>
|
<div class="popper-item" v-for="(item,i) in showSuggestions[key]" v-html="item.label" :key="item.insertText" :type="key" :value="item.insertText" @click.stop="handleItemClick(key,item,$event)"></div>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import 'quill/dist/quill.snow.css'
|
import 'quill/dist/quill.snow.css'
|
||||||
import Quill from 'quill'
|
import Quill from 'quill'
|
||||||
import {del} from "../../../../http";
|
import suggestions from "./suggestions";
|
||||||
export default {
|
export default {
|
||||||
name: "editor",
|
name: "editor",
|
||||||
props: {
|
props: {
|
||||||
@@ -32,7 +32,10 @@
|
|||||||
id:'editor-'+this.guid(),
|
id:'editor-'+this.guid(),
|
||||||
cursorIndex:0,
|
cursorIndex:0,
|
||||||
pivotalCursorIndex:0,//用于记录输入特殊符号后当前光标的位置,方便选择后覆盖
|
pivotalCursorIndex:0,//用于记录输入特殊符号后当前光标的位置,方便选择后覆盖
|
||||||
|
newExpressionIndex:0,
|
||||||
|
editRange:{start:0,end:0},
|
||||||
noStyleSuggestions:{},//存储最原始的item数据
|
noStyleSuggestions:{},//存储最原始的item数据
|
||||||
|
orders:['history','operators','functions','metrics','labels','values'],
|
||||||
showSuggestions:{},//存储显示的item数据,包含mark样式
|
showSuggestions:{},//存储显示的item数据,包含mark样式
|
||||||
storedSuggestions:[],//存储每个item的dom
|
storedSuggestions:[],//存储每个item的dom
|
||||||
toggleSelectIndex:-1,
|
toggleSelectIndex:-1,
|
||||||
@@ -46,6 +49,7 @@
|
|||||||
placeholder: 'Insert text here ...'
|
placeholder: 'Insert text here ...'
|
||||||
},
|
},
|
||||||
labelValues:{},
|
labelValues:{},
|
||||||
|
tempStoreMetric:{},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created(){
|
created(){
|
||||||
@@ -54,59 +58,194 @@
|
|||||||
methods:{
|
methods:{
|
||||||
userChange:function(char,operation,newContent,oldContent){
|
userChange:function(char,operation,newContent,oldContent){
|
||||||
this.dealSpecilChar(char,operation);
|
this.dealSpecilChar(char,operation);
|
||||||
if(this.pivotalCursorIndex!=0){
|
this.changeSuggestions('type')
|
||||||
console.log('pivotalCursorIndex',this.pivotalCursorIndex,'cursorIndex',this.cursorIndex)
|
|
||||||
newContent=newContent.substring(this.pivotalCursorIndex,this.cursorIndex);
|
if(this.pivotalCursorIndex>this.editRange.start && this.pivotalCursorIndex < this.editRange.end){
|
||||||
|
if(this.pivotalCursorIndex!=0){
|
||||||
|
console.log('pivotalCursorIndex',this.pivotalCursorIndex,'cursorIndex',this.cursorIndex)
|
||||||
|
newContent=newContent.substring(this.pivotalCursorIndex,this.cursorIndex);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
newContent=newContent.substring(this.editRange.start,this.editRange.end)
|
||||||
}
|
}
|
||||||
this.filterItems(newContent);
|
this.filterItems(newContent);
|
||||||
},
|
},
|
||||||
dealSpecilChar:function(char,operation){
|
dealSpecilChar:function(char,operation){
|
||||||
if(/^[\{\(\[]$/g.test(char)){
|
if(/^[\{\(\[\,]$/g.test(char)){
|
||||||
if(operation=='insert'){
|
if(operation=='insert'){
|
||||||
if(char == '{'){
|
if(char == '{'||char==','){
|
||||||
this.insertTextAtIndex('}',this.cursorIndex)
|
if(char == '{'){
|
||||||
this.quill.setSelection(this.cursorIndex)
|
this.addDoubleChar('}')
|
||||||
|
}
|
||||||
this.changeSuggestions('label')
|
this.changeSuggestions('label')
|
||||||
}else if(char == '('){
|
}else if(char == '('){
|
||||||
this.insertTextAtIndex(')',this.cursorIndex)
|
this.addDoubleChar(')')
|
||||||
this.quill.setSelection(this.cursorIndex)
|
|
||||||
}else if(char == '['){
|
}else if(char == '['){
|
||||||
this.insertTextAtIndex(']',this.cursorIndex)
|
this.addDoubleChar(']')
|
||||||
this.quill.setSelection(this.cursorIndex)
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
this.quill.deleteText(this.cursorIndex,1,'api')
|
this.delDoubleChar(char);
|
||||||
}
|
}
|
||||||
}else if(/^[=]/g.test(char)){
|
}else if(/^[=\"]/g.test(char)){
|
||||||
if(operation=='insert'){
|
if(operation=='insert'){
|
||||||
let labelValuesReg=/\{((\w*?=.*?,{0,1})+?)\}/
|
if(char == '"'){
|
||||||
if(labelValuesReg.test(this.content)){
|
this.addDoubleChar('"');
|
||||||
let labelValues=labelValuesReg.exec(this.content)[0]
|
|
||||||
if(labelValues){
|
|
||||||
let unCompleteInputReg=/\w*?=[^"|\s]/
|
|
||||||
if(unCompleteInputReg.test(labelValues)){
|
|
||||||
let unCompleteInput=unCompleteInputReg.exec(labelValues)[0];
|
|
||||||
unCompleteInput=unCompleteInput.substring(0,unCompleteInput.length-2)
|
|
||||||
let values=this.labelValues.get(unCompleteInput);
|
|
||||||
console.log('values',values)
|
|
||||||
|
|
||||||
this.noStyleSuggestions={values:values}
|
|
||||||
this.showSuggestions=this.deepClone(this.noStyleSuggestions);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}else{
|
this.changeSuggestions('values')
|
||||||
|
|
||||||
|
}else{
|
||||||
|
if(char == '"'){
|
||||||
|
this.delDoubleChar(char);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
addDoubleChar:function(char){
|
||||||
|
this.insertTextAtIndex(char,this.cursorIndex);
|
||||||
|
this.quill.setSelection(this.cursorIndex)
|
||||||
|
},
|
||||||
|
delDoubleChar:function(leftChar){
|
||||||
|
let char=this.content.charAt(this.cursorIndex);
|
||||||
|
let temp=leftChar+char;
|
||||||
|
|
||||||
|
if(/(\{\})|(\(\))|(\[\])|(\"\")/.test(temp)){
|
||||||
|
this.quill.deleteText(this.cursorIndex,1,'api');
|
||||||
|
}
|
||||||
|
if(leftChar == '{'){
|
||||||
|
this.pivotalCursorIndex=0;
|
||||||
|
}
|
||||||
|
},
|
||||||
changeSuggestions:function(type){
|
changeSuggestions:function(type){
|
||||||
if(type == 'label'){
|
if(type == 'label'){
|
||||||
this.queryLabels();
|
this.queryLabels();
|
||||||
|
}else if(type == 'values'){
|
||||||
|
this.queryValues();
|
||||||
|
}else if(type == 'type'){
|
||||||
|
this.packageTypeInfo();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
packageTypeInfo:function(){
|
||||||
|
let metricReg=/[a-zA-Z_]\w*?\b\{.*?\}/g
|
||||||
|
let functionReg=/[a-zA-Z_]\w*?\(.*?\)/g
|
||||||
|
if(functionReg.test(this.content)){
|
||||||
|
let tempIndex=this.cursorIndex;
|
||||||
|
let tempStart,tempChar=this.content.charAt(tempIndex-1);
|
||||||
|
|
||||||
|
//向前查找,找到边界
|
||||||
|
while(tempIndex>0&&/[a-zA-Z_]/.test(tempChar)){
|
||||||
|
tempIndex--;
|
||||||
|
tempChar=this.content.charAt(tempIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editRange.start=tempIndex+1;
|
||||||
|
this.editRange.end=this.cursorIndex;
|
||||||
|
}else{
|
||||||
|
if(metricReg.test(this.content)){
|
||||||
|
let match=this.globalMatch(metricReg,this.content)
|
||||||
|
if(match&&match.length>0){
|
||||||
|
let isInnerExpression=false;
|
||||||
|
let editExpression=null;
|
||||||
|
match.forEach(item=>{
|
||||||
|
let content=item[0];
|
||||||
|
let index=item.index;
|
||||||
|
let length=content.length;
|
||||||
|
if(index < this.cursorIndex && index+length>this.cursorIndex){ //判断是否在一个完整子表达式中
|
||||||
|
isInnerExpression=true;
|
||||||
|
editExpression=item;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log('match',match,'isInnerExpress',isInnerExpression)
|
||||||
|
if(isInnerExpression&&editExpression){
|
||||||
|
let expression=editExpression[0];
|
||||||
|
let labelValuesReg=/\{((\w*?=.*?,{0,1})+?)\}/
|
||||||
|
if(labelValuesReg.test(expression)){
|
||||||
|
let match=labelValuesReg.exec(expression);
|
||||||
|
if(editExpression.index+match.index>this.cursorIndex){
|
||||||
|
this.queryTypeInfos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.editRange.start=editExpression.index;
|
||||||
|
this.editRange.end=editExpression.index+expression.length;
|
||||||
|
}else{
|
||||||
|
let tempIndex=this.cursorIndex;
|
||||||
|
let tempStart,tempChar=this.content.charAt(tempIndex-1);
|
||||||
|
|
||||||
|
//向前查找,找到边界
|
||||||
|
while(tempIndex>0&&/[a-zA-Z_]/.test(tempChar)){
|
||||||
|
tempIndex--;
|
||||||
|
tempChar=this.content.charAt(tempIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editRange.start=tempIndex+1;
|
||||||
|
this.editRange.end=this.cursorIndex;
|
||||||
|
|
||||||
|
console.log('multi expression',this.editRange)
|
||||||
|
|
||||||
|
this.queryTypeInfos();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
console.log('mo match metric')
|
||||||
|
this.editRange.start=0;
|
||||||
|
this.editRange.end=this.cursorIndex;
|
||||||
|
this.queryTypeInfos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
queryTypeInfos:function(){
|
||||||
|
this.noStyleSuggestions={};
|
||||||
|
this.$set(this.noStyleSuggestions,'metrics',this.tempStoreMetric)
|
||||||
|
this.$set(this.noStyleSuggestions,'operators',suggestions.getOperators())
|
||||||
|
this.$set(this.noStyleSuggestions,'functions',suggestions.getFunctions())
|
||||||
|
this.showSuggestions=this.deepClone(this.noStyleSuggestions)
|
||||||
|
},
|
||||||
|
queryValues:function(){
|
||||||
|
let labelValuesReg=/\{((\w*?=.*?,{0,1})+?)\}/
|
||||||
|
if(labelValuesReg.test(this.content)){
|
||||||
|
let match=labelValuesReg.exec(this.content);
|
||||||
|
let labelValues=match[0]
|
||||||
|
let index=match.index;
|
||||||
|
if(labelValues){
|
||||||
|
let tempCounter=this.cursorIndex;
|
||||||
|
let equalIndex=-1;
|
||||||
|
let boundaryIndex=-1;
|
||||||
|
while(tempCounter>=index){
|
||||||
|
let char=this.content.charAt(tempCounter);
|
||||||
|
if(char=='='){
|
||||||
|
equalIndex=tempCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(char==','||char == '{'){
|
||||||
|
boundaryIndex=tempCounter+1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempCounter--;
|
||||||
|
}
|
||||||
|
let label=this.content.substring(boundaryIndex,equalIndex);
|
||||||
|
console.log('label',this.content.substring(boundaryIndex,equalIndex))
|
||||||
|
|
||||||
|
let values=this.labelValues.get(label);
|
||||||
|
|
||||||
|
this.noStyleSuggestions={values:values}
|
||||||
|
this.showSuggestions=this.deepClone(this.noStyleSuggestions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
queryLabels:function(){
|
queryLabels:function(){
|
||||||
|
let labels=/\{.*\}/;
|
||||||
|
if(labels.test(this.content)){
|
||||||
|
let match=labels.exec(this.content);
|
||||||
|
let index=match.index;
|
||||||
|
let matchContent=match[0];
|
||||||
|
if(this.cursorIndex<index || this.cursorIndex>index + matchContent.length){
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.queryTypeInfos();
|
||||||
|
return;
|
||||||
|
}
|
||||||
let metric=/([a-zA-Z_]\w*)\b(?=\{)/.exec(this.content)[0];
|
let metric=/([a-zA-Z_]\w*)\b(?=\{)/.exec(this.content)[0];
|
||||||
let timeRange=this.getDefaultTimeRange();
|
let timeRange=this.getDefaultTimeRange();
|
||||||
this.$get('/prom/api/v1/series?match[]={__name__="'+metric+'"}&start='+timeRange[0]+"&end="+timeRange[1]).then(response=>{
|
this.$get('/prom/api/v1/series?match[]={__name__="'+metric+'"}&start='+timeRange[0]+"&end="+timeRange[1]).then(response=>{
|
||||||
@@ -141,6 +280,7 @@
|
|||||||
|
|
||||||
this.noStyleSuggestions={labels:labels}
|
this.noStyleSuggestions={labels:labels}
|
||||||
this.showSuggestions=this.deepClone(this.noStyleSuggestions);
|
this.showSuggestions=this.deepClone(this.noStyleSuggestions);
|
||||||
|
console.log('change labels',this.showSuggestions)
|
||||||
this.storeSuggestions();
|
this.storeSuggestions();
|
||||||
}else{
|
}else{
|
||||||
this.noStyleSuggestions={};
|
this.noStyleSuggestions={};
|
||||||
@@ -163,12 +303,25 @@
|
|||||||
this.handleLabelClick(item)
|
this.handleLabelClick(item)
|
||||||
}else if(type == 'values'){
|
}else if(type == 'values'){
|
||||||
this.handleValueClick(item);
|
this.handleValueClick(item);
|
||||||
|
}else if(type == 'operators'){
|
||||||
|
this.handleOperatorClick(item);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
handleOperatorClick:function(item){
|
||||||
|
this.deleteTextInRange(this.editRange.start,this.cursorIndex)
|
||||||
|
this.insertTextAtIndex(item.insertText,this.editRange.start == 0?this.editRange.start-1:this.editRange.start);
|
||||||
|
this.quill.setSelection(this.cursorIndex+item.insertText.length);
|
||||||
|
this.storeCursor().then(()=>{
|
||||||
|
this.insertTextAtIndex('(',this.cursorIndex,'user')
|
||||||
|
this.quill.setSelection(this.cursorIndex+1)
|
||||||
|
this.editRange.start=this.cursorIndex;
|
||||||
|
this.editRange.end=this.cursorIndex;
|
||||||
|
})
|
||||||
|
},
|
||||||
handleMetricClick:function(item){
|
handleMetricClick:function(item){
|
||||||
this.clearContent();
|
this.deleteTextInRange(this.editRange.start,this.cursorIndex)
|
||||||
this.$nextTick(()=>{
|
this.$nextTick(()=>{
|
||||||
this.insertTextAtIndex(item.insertText);
|
this.insertTextAtIndex(item.insertText,this.editRange.start==0?this.editRange.start-1:this.editRange.start);
|
||||||
})
|
})
|
||||||
this.moveCursorToEnd();
|
this.moveCursorToEnd();
|
||||||
},
|
},
|
||||||
@@ -183,7 +336,14 @@
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleValueClick:function(item){
|
handleValueClick:function(item){
|
||||||
|
let preChar=this.content.substring(this.pivotalCursorIndex-1,this.pivotalCursorIndex);
|
||||||
|
this.quill.setSelection(this.pivotalCursorIndex,this.cursorIndex-this.pivotalCursorIndex,'api');
|
||||||
|
this.deleteTextInRange(this.pivotalCursorIndex,this.cursorIndex-this.pivotalCursorIndex)
|
||||||
|
if(preChar == '='){
|
||||||
|
this.insertTextAtIndex('"'+item.insertText+'"',this.pivotalCursorIndex)
|
||||||
|
}else{
|
||||||
|
this.insertTextAtIndex(item.insertText,this.pivotalCursorIndex)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
toggleSelect:function(event){//上下键选择
|
toggleSelect:function(event){//上下键选择
|
||||||
if(!this.storedSuggestions||this.storedSuggestions.length<1){
|
if(!this.storedSuggestions||this.storedSuggestions.length<1){
|
||||||
@@ -283,6 +443,7 @@
|
|||||||
return new Promise(function(resolve,reject){
|
return new Promise(function(resolve,reject){
|
||||||
$temp.$nextTick(()=>{
|
$temp.$nextTick(()=>{
|
||||||
let range=$temp.quill.getSelection();
|
let range=$temp.quill.getSelection();
|
||||||
|
console.log('range',range)
|
||||||
if(range&&range.length == 0){
|
if(range&&range.length == 0){
|
||||||
$temp.cursorIndex=range.index;
|
$temp.cursorIndex=range.index;
|
||||||
console.log('current cursor-->',$temp.cursorIndex)
|
console.log('current cursor-->',$temp.cursorIndex)
|
||||||
@@ -371,14 +532,25 @@
|
|||||||
deepClone:function(source){
|
deepClone:function(source){
|
||||||
return JSON.parse(JSON.stringify(source))
|
return JSON.parse(JSON.stringify(source))
|
||||||
},
|
},
|
||||||
|
globalMatch:function(pattern,content){
|
||||||
|
let result=[];
|
||||||
|
let temp;
|
||||||
|
pattern.lastIndex=0;
|
||||||
|
while ((temp = pattern.exec(content)) != null) {
|
||||||
|
result.push(temp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
queryMetrics:function(){
|
queryMetrics:function(){
|
||||||
this.$get('/prom/api/v1/label/__name__/values').then(response=>{
|
this.$get('/prom/api/v1/label/__name__/values').then(response=>{
|
||||||
if(response.status == 'success'){
|
if(response.status == 'success'){
|
||||||
let metrics=response.data.map(item=>{
|
let metrics=response.data.map(item=>{
|
||||||
return {label:item,insertText:item};
|
return {label:item,insertText:item};
|
||||||
})
|
})
|
||||||
this.$set(this.noStyleSuggestions,'metrics',metrics)
|
|
||||||
this.showSuggestions=this.deepClone(this.noStyleSuggestions)
|
this.tempStoreMetric=this.deepClone(metrics);
|
||||||
|
this.queryTypeInfos();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -428,6 +600,11 @@
|
|||||||
})
|
})
|
||||||
this.storeSuggestions();
|
this.storeSuggestions();
|
||||||
this.registerKeydown();
|
this.registerKeydown();
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
content:function(n,o){
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -57,7 +57,6 @@
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
const funcs=[
|
const funcs=[
|
||||||
...operators,
|
|
||||||
{
|
{
|
||||||
insertText: 'abs',
|
insertText: 'abs',
|
||||||
label: 'abs',
|
label: 'abs',
|
||||||
@@ -360,6 +359,13 @@
|
|||||||
documentation: 'The population standard variance of the values in the specified interval.',
|
documentation: 'The population standard variance of the values in the specified interval.',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
export default {
|
export default {
|
||||||
}
|
getOperators:function(){
|
||||||
|
return JSON.parse(JSON.stringify(operators));
|
||||||
|
},
|
||||||
|
|
||||||
|
getFunctions:function(){
|
||||||
|
return JSON.parse(JSON.stringify(funcs))
|
||||||
|
},
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user