346 lignes
Pas d'EOL
14 Kio
JavaScript
346 lignes
Pas d'EOL
14 Kio
JavaScript
new Vue({
|
|
el:'#logsreader',
|
|
created(){
|
|
let params=this.getUrlParam(window.location.href);
|
|
this.token=params.token
|
|
this.userId=params.iduser
|
|
this.bridge=`${this.getURL()}/logsreader`;
|
|
this.getKeyList();
|
|
|
|
},
|
|
data:{
|
|
bridge:'',
|
|
token:'',
|
|
userId:'',
|
|
logsKeys:[],
|
|
logs:{},
|
|
menuActiveKey:'',
|
|
activeLog:'',
|
|
activeLogKey:'',
|
|
error:false,
|
|
menuOpen:false,
|
|
},
|
|
computed:{
|
|
loadedLogs(){
|
|
let logs=[];
|
|
_.forEach(this.logs,(logCollection,logCollectionKey)=>{
|
|
_.forEach(logCollection.files,(value,logKey)=>{
|
|
logs.push({
|
|
logCollectionKey:logCollectionKey,
|
|
fileName:logKey.replace(logCollectionKey+'_',''),
|
|
logKey:logKey,
|
|
content:value.content,
|
|
active:value.active
|
|
});
|
|
});
|
|
});
|
|
return logs;
|
|
}
|
|
},
|
|
watch:{
|
|
menuActiveKey:function(newVal,old){
|
|
if(newVal.length && newVal!==old && !this.logs[this.menuActiveKey].filesNames.length)
|
|
this.getLogsList();
|
|
}
|
|
},
|
|
template: `
|
|
<div @click="menuOpen=false" id="main">
|
|
<div class="errormsg" v-if="error" @click="error=false">{{error}}</div>
|
|
<header>
|
|
<menu>
|
|
<div @click.stop="menuOpen=!menuOpen" class="ico">☰</div>
|
|
<div v-if="menuOpen" class="handler">
|
|
<div class="keylist">
|
|
<div class="mainkl">
|
|
<div v-if="_.isEmpty(logsKeys)">Chargement...</div>
|
|
<div v-else
|
|
@click.stop="menuActiveKey=key"
|
|
:class="['logkey',{'active':key===menuActiveKey}]"
|
|
v-for="(nb,key) in logsKeys"
|
|
:key="'link'+key"
|
|
>
|
|
{{key.toLowerCase()}} ({{nb}})
|
|
</div>
|
|
</div>
|
|
<div v-if="menuActiveKey" class="secondkl">
|
|
<div
|
|
@click="checkOutLog(menuActiveKey,fileName)"
|
|
class="filename"
|
|
v-for="fileName in logs[menuActiveKey].filesNames"
|
|
:key="menuActiveKey+'_'+fileName">{{fileName}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div @click.stop="reloadLogList()" class="reloadkeylist">Actualiser</div>
|
|
</div>
|
|
|
|
</menu>
|
|
<div class="logo">LOGS READER</div>
|
|
</header>
|
|
<section>
|
|
<div class="tabsbtn">
|
|
<div
|
|
v-for="log in loadedLogs"
|
|
@click="showLog(log.logCollectionKey,log.fileName)"
|
|
:class="['tabbtn',{'active':activeLog===log.logKey}]"
|
|
:key="'tab'+log.logKey"
|
|
:title="log.logKey"
|
|
>
|
|
<div class="tb_refico" v-if="logs[log.logCollectionKey].files[log.logCollectionKey+'_'+log.fileName].isRefreshing">🔄</div>
|
|
<div class="tb_name">{{log.logKey}}</div>
|
|
<div @click.stop="closeLog(log.logCollectionKey,log.fileName)" class="tb_close">X</div>
|
|
</div>
|
|
</div>
|
|
<div class="displayer">
|
|
<div
|
|
v-for="log in loadedLogs" :key="'tab'+log.logKey"
|
|
:class="['logdisp',{'active':activeLog===log.logKey}]"
|
|
>
|
|
<div class="ld_header">
|
|
<div>
|
|
<div class="ld_refbtn" @click="download(log.logCollectionKey,log.fileName)">💾 Télécharger le log</div>
|
|
<div><span title="taille de l'extrait">{{convertSizeWithUnit(logs[log.logCollectionKey].files[log.logCollectionKey+'_'+log.fileName].extractSize)}}</span>/<span title="taille totale du log">{{convertSizeWithUnit(logs[log.logCollectionKey].files[log.logCollectionKey+'_'+log.fileName].size)}}</span></div>
|
|
</div>
|
|
<div>
|
|
<div @click="refresh(log.logCollectionKey,log.fileName)" class="ld_refbtn">Actualiser</div>
|
|
<div class="ld_autref">
|
|
<input
|
|
:id="log.logKey+'_autorfcb'"
|
|
@change="autoRefresh(log.logCollectionKey,log.fileName)"
|
|
type="checkbox"
|
|
v-model="logs[log.logCollectionKey].files[log.logCollectionKey+'_'+log.fileName].autoRefresh"
|
|
>
|
|
<label :for="log.logKey+'_autorfcb'">Auto Refresh</label>
|
|
<input
|
|
type="text"
|
|
v-model="logs[log.logCollectionKey].files[log.logCollectionKey+'_'+log.fileName].refreshTimer"
|
|
:readonly="logs[log.logCollectionKey].files[log.logCollectionKey+'_'+log.fileName].autoRefresh?'readonly':false"
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="ld_cont" v-html="log.content" @mouseup="onMouseUp"></div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
`,
|
|
methods:{
|
|
// copier depuis la sélection, shell-cmd like
|
|
onMouseUp(){
|
|
// A ACTIVER QUAND ON SERA EN HTTPS
|
|
|
|
// let sel=document.getSelection().toString()
|
|
// navigator.clipboard.writeText(sel)
|
|
return
|
|
},
|
|
download(key,fileName){
|
|
window.open(this.bridge+`/dllog?key=${key}&logName=${fileName}&iduser=${this.userId}&token=${this.token}`);
|
|
},
|
|
convertSizeWithUnit(size){
|
|
let s=parseInt(size);
|
|
let unit='o';
|
|
if(s>=1000000){
|
|
s/=1000000
|
|
unit='Mo'
|
|
}
|
|
else if(s>=1000){
|
|
s/=1000
|
|
unit='ko'
|
|
}
|
|
return s+unit;
|
|
},
|
|
reloadLogList(){
|
|
_.forEach(this.logs,(logCollection,logCollectionKey)=>{
|
|
_.forEach(logCollection.files,(value,logKey)=>{
|
|
this.closeLog(logCollectionKey,logKey.replace(logCollectionKey+'_',''));
|
|
});
|
|
});
|
|
this.activeLog=''
|
|
this.activeLogKey=''
|
|
this.menuActiveKey=''
|
|
this.getKeyList();
|
|
},
|
|
getUrlParam(url){
|
|
return _.chain(url).split('?').nth(1).split('&').map(_.partial(_.split, _, '=', 2)).fromPairs().value()
|
|
},
|
|
getKeyList(){
|
|
this.ajax(this.bridge+'/keyslist')
|
|
.then((rep)=>{
|
|
if(rep.status){
|
|
this.logsKeys=rep.logskeys
|
|
for(let key in this.logsKeys){
|
|
this.$set(this.logs,key,{filesNames:[],files:{}})
|
|
}
|
|
return
|
|
}
|
|
|
|
this.error=rep.msg
|
|
})
|
|
.catch((err)=>{
|
|
this.error='erreur AJAX : '+err
|
|
})
|
|
},
|
|
getLogsList(){
|
|
this.ajax(this.bridge+'/logslist',{
|
|
data:{
|
|
key:this.menuActiveKey
|
|
}
|
|
})
|
|
.then((rep)=>{
|
|
if(rep.status){
|
|
this.$set(this.logs[this.menuActiveKey],'filesNames',rep.logs);
|
|
return
|
|
}
|
|
|
|
this.error=rep.msg
|
|
})
|
|
.catch((err)=>{
|
|
this.error='erreur AJAX : '+err
|
|
})
|
|
},
|
|
checkOutLog(logCollectionKey,fileName){
|
|
if(!this.logs[logCollectionKey].files[`${logCollectionKey}_${fileName}`]){
|
|
this.getALog(logCollectionKey,fileName).then(()=>{
|
|
this.showLog(logCollectionKey,fileName)
|
|
})
|
|
return
|
|
}
|
|
this.showLog(logCollectionKey,fileName)
|
|
},
|
|
showLog(logCollectionKey,fileName){
|
|
|
|
if(!_.isEmpty(this.activeLog))
|
|
this.$set(this.logs[this.activeLogKey].files[this.activeLog],'active',false)
|
|
|
|
|
|
this.$set(this.logs[logCollectionKey].files[`${logCollectionKey}_${fileName}`],'active',true)
|
|
this.activeLog=`${logCollectionKey}_${fileName}`
|
|
this.activeLogKey=logCollectionKey
|
|
},
|
|
getALog(logCollectionKey,fileName){
|
|
return new Promise((res,rej)=>{
|
|
this.ajax(this.bridge+'/log',{
|
|
data:{
|
|
key:logCollectionKey,
|
|
logName:fileName
|
|
}
|
|
})
|
|
.then((rep)=>{
|
|
if(rep.status){
|
|
let content=this.parseLog(rep.log.content)
|
|
|
|
let autoRefresh=false
|
|
let isRefreshing=false
|
|
let refreshTimer=5
|
|
let intervalFct=false
|
|
if(this.logs[logCollectionKey].files[`${logCollectionKey}_${fileName}`]){
|
|
autoRefresh=this.logs[logCollectionKey].files[`${logCollectionKey}_${fileName}`].autoRefresh
|
|
intervalFct=this.logs[logCollectionKey].files[`${logCollectionKey}_${fileName}`].intervalFct
|
|
}
|
|
|
|
|
|
this.$set(this.logs[logCollectionKey].files,`${logCollectionKey}_${fileName}`,{
|
|
active:false
|
|
,content:content,
|
|
autoRefresh:autoRefresh,
|
|
isRefreshing:false,
|
|
refreshTimer:5,
|
|
intervalFct:intervalFct,
|
|
extractSize:rep.log.extractSize,
|
|
size:rep.log.size,
|
|
})
|
|
res()
|
|
return
|
|
}
|
|
res()
|
|
this.error=rep.msg
|
|
})
|
|
.catch((err)=>{
|
|
res()
|
|
this.error='erreur AJAX : '+err
|
|
})
|
|
})
|
|
},
|
|
parseLog(txt){
|
|
let logArr=txt.split('\n');
|
|
let ret='';
|
|
// console.log(logArr)
|
|
for(let i=logArr.length-1;i>-1;i--){
|
|
if(logArr[i].length){
|
|
let rgx=/^(\[.+?\]+?)\s(\w+)\.(\w+):(.+?)(\{{1}.+?\}{1})?$/
|
|
let logz=logArr[i].match(rgx)
|
|
if(logz){
|
|
let hour=logz[1]
|
|
let channel=logz[2]
|
|
let level=logz[3]
|
|
let levelClass=level.toLowerCase()
|
|
let msg=logz[4]
|
|
msg=msg.replace(/(line\s\d+)/,'<span class="lline">$1</span>')
|
|
let data=logz[5]
|
|
ret+=`<div><span class="lhour">${hour}</span> <span class="llevel ${levelClass}">${level}</span><span class="lmsg">${msg}</span>${data?`<span class="ldata">${data}</span>`:''}</div>`
|
|
}
|
|
else{
|
|
ret+=`<div>${logArr[i]}</div>`
|
|
}
|
|
}
|
|
}
|
|
// console.log(ret);
|
|
return ret
|
|
},
|
|
closeLog(logCollectionKey,fileName){
|
|
|
|
let toActivate;
|
|
|
|
for(let i=0,len=this.loadedLogs.length;i<len;i++){
|
|
let thisLog=this.loadedLogs[i]
|
|
// le log suivant
|
|
if(thisLog.logCollectionKey===logCollectionKey && thisLog.fileName===fileName && this.loadedLogs[i+1])
|
|
toActivate=this.loadedLogs[i+1]
|
|
|
|
// le log précédent
|
|
if(thisLog.logCollectionKey===logCollectionKey && thisLog.fileName===fileName && !this.loadedLogs[i+1] && this.loadedLogs[i-1])
|
|
toActivate=this.loadedLogs[i-1]
|
|
}
|
|
|
|
if(toActivate)
|
|
this.showLog(toActivate.logCollectionKey,toActivate.fileName)
|
|
else
|
|
this.activeLog=''
|
|
|
|
clearInterval(this.logs[logCollectionKey].files[`${logCollectionKey}_${fileName}`].intervalFct)
|
|
this.$delete(this.logs[logCollectionKey].files,`${logCollectionKey}_${fileName}`)
|
|
},
|
|
refresh(logCollectionKey,fileName){
|
|
let log=this.logs[logCollectionKey].files[`${logCollectionKey}_${fileName}`]
|
|
|
|
if(!log.isRefreshing){
|
|
this.$set(log,'isRefreshing',true)
|
|
this.getALog(logCollectionKey,fileName).then(()=>{
|
|
|
|
})
|
|
}
|
|
|
|
},
|
|
autoRefresh(logCollectionKey,fileName,forceStop=false){
|
|
let log=this.logs[logCollectionKey].files[`${logCollectionKey}_${fileName}`]
|
|
|
|
if(!log.autoRefresh || forceStop){
|
|
clearInterval(log.intervalFct)
|
|
return
|
|
}
|
|
|
|
let interval=parseInt(log.refreshTimer);
|
|
if(isNaN(interval)){
|
|
interval=5
|
|
this.$set(log,'refreshTimer',5)
|
|
}
|
|
interval*=1000;
|
|
|
|
log.intervalFct=setInterval(() => {
|
|
this.refresh(logCollectionKey,fileName);
|
|
}, interval);
|
|
|
|
}
|
|
}
|
|
}) |