perf:explore 编辑功能(operator function 待完成)
This commit is contained in:
@@ -1580,7 +1580,9 @@
|
||||
}
|
||||
},
|
||||
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);
|
||||
},
|
||||
getAlertRuleChartData(chartInfo) {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<div class="metric-editor-popper" :style="{left:popperPos.left+'px'}">
|
||||
<div class="metric-popper-main" >
|
||||
<el-scrollbar style="height: 100%" class="ps-scroll-small" ref="scroll">
|
||||
<div v-for="(value, key, index) in showSuggestions" >
|
||||
<div v-html="key" class="popper-group"></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 v-for="(key, index) in orders" >
|
||||
<div v-html="key" class="popper-group" v-show="showSuggestions[key]"></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>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
@@ -18,7 +18,7 @@
|
||||
<script>
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import Quill from 'quill'
|
||||
import {del} from "../../../../http";
|
||||
import suggestions from "./suggestions";
|
||||
export default {
|
||||
name: "editor",
|
||||
props: {
|
||||
@@ -32,7 +32,10 @@
|
||||
id:'editor-'+this.guid(),
|
||||
cursorIndex:0,
|
||||
pivotalCursorIndex:0,//用于记录输入特殊符号后当前光标的位置,方便选择后覆盖
|
||||
newExpressionIndex:0,
|
||||
editRange:{start:0,end:0},
|
||||
noStyleSuggestions:{},//存储最原始的item数据
|
||||
orders:['history','operators','functions','metrics','labels','values'],
|
||||
showSuggestions:{},//存储显示的item数据,包含mark样式
|
||||
storedSuggestions:[],//存储每个item的dom
|
||||
toggleSelectIndex:-1,
|
||||
@@ -46,6 +49,7 @@
|
||||
placeholder: 'Insert text here ...'
|
||||
},
|
||||
labelValues:{},
|
||||
tempStoreMetric:{},
|
||||
}
|
||||
},
|
||||
created(){
|
||||
@@ -54,59 +58,194 @@
|
||||
methods:{
|
||||
userChange:function(char,operation,newContent,oldContent){
|
||||
this.dealSpecilChar(char,operation);
|
||||
if(this.pivotalCursorIndex!=0){
|
||||
console.log('pivotalCursorIndex',this.pivotalCursorIndex,'cursorIndex',this.cursorIndex)
|
||||
newContent=newContent.substring(this.pivotalCursorIndex,this.cursorIndex);
|
||||
this.changeSuggestions('type')
|
||||
|
||||
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);
|
||||
},
|
||||
dealSpecilChar:function(char,operation){
|
||||
if(/^[\{\(\[]$/g.test(char)){
|
||||
if(/^[\{\(\[\,]$/g.test(char)){
|
||||
if(operation=='insert'){
|
||||
if(char == '{'){
|
||||
this.insertTextAtIndex('}',this.cursorIndex)
|
||||
this.quill.setSelection(this.cursorIndex)
|
||||
if(char == '{'||char==','){
|
||||
if(char == '{'){
|
||||
this.addDoubleChar('}')
|
||||
}
|
||||
this.changeSuggestions('label')
|
||||
}else if(char == '('){
|
||||
this.insertTextAtIndex(')',this.cursorIndex)
|
||||
this.quill.setSelection(this.cursorIndex)
|
||||
this.addDoubleChar(')')
|
||||
}else if(char == '['){
|
||||
this.insertTextAtIndex(']',this.cursorIndex)
|
||||
this.quill.setSelection(this.cursorIndex)
|
||||
this.addDoubleChar(']')
|
||||
}
|
||||
}else{
|
||||
this.quill.deleteText(this.cursorIndex,1,'api')
|
||||
this.delDoubleChar(char);
|
||||
}
|
||||
}else if(/^[=]/g.test(char)){
|
||||
}else if(/^[=\"]/g.test(char)){
|
||||
if(operation=='insert'){
|
||||
let labelValuesReg=/\{((\w*?=.*?,{0,1})+?)\}/
|
||||
if(labelValuesReg.test(this.content)){
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
if(char == '"'){
|
||||
this.addDoubleChar('"');
|
||||
}
|
||||
}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){
|
||||
if(type == 'label'){
|
||||
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(){
|
||||
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 timeRange=this.getDefaultTimeRange();
|
||||
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.showSuggestions=this.deepClone(this.noStyleSuggestions);
|
||||
console.log('change labels',this.showSuggestions)
|
||||
this.storeSuggestions();
|
||||
}else{
|
||||
this.noStyleSuggestions={};
|
||||
@@ -163,12 +303,25 @@
|
||||
this.handleLabelClick(item)
|
||||
}else if(type == 'values'){
|
||||
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){
|
||||
this.clearContent();
|
||||
this.deleteTextInRange(this.editRange.start,this.cursorIndex)
|
||||
this.$nextTick(()=>{
|
||||
this.insertTextAtIndex(item.insertText);
|
||||
this.insertTextAtIndex(item.insertText,this.editRange.start==0?this.editRange.start-1:this.editRange.start);
|
||||
})
|
||||
this.moveCursorToEnd();
|
||||
},
|
||||
@@ -183,7 +336,14 @@
|
||||
})
|
||||
},
|
||||
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){//上下键选择
|
||||
if(!this.storedSuggestions||this.storedSuggestions.length<1){
|
||||
@@ -283,6 +443,7 @@
|
||||
return new Promise(function(resolve,reject){
|
||||
$temp.$nextTick(()=>{
|
||||
let range=$temp.quill.getSelection();
|
||||
console.log('range',range)
|
||||
if(range&&range.length == 0){
|
||||
$temp.cursorIndex=range.index;
|
||||
console.log('current cursor-->',$temp.cursorIndex)
|
||||
@@ -371,14 +532,25 @@
|
||||
deepClone:function(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(){
|
||||
this.$get('/prom/api/v1/label/__name__/values').then(response=>{
|
||||
if(response.status == 'success'){
|
||||
let metrics=response.data.map(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.registerKeydown();
|
||||
},
|
||||
watch:{
|
||||
content:function(n,o){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
},
|
||||
];
|
||||
const funcs=[
|
||||
...operators,
|
||||
{
|
||||
insertText: 'abs',
|
||||
label: 'abs',
|
||||
@@ -360,6 +359,13 @@
|
||||
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>
|
||||
|
||||
Reference in New Issue
Block a user