vuetify 2.1.14

This commit is contained in:
andy 2019-12-13 23:06:33 +00:00
parent 744468d631
commit 6c4dff216d
29 changed files with 564 additions and 327 deletions

View file

@ -19,4 +19,11 @@
<natures>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures>
<linkedResources>
<link>
<name>_MasterFiles_</name>
<type>2</type>
<locationURI>virtual:/virtual</locationURI>
</link>
</linkedResources>
</projectDescription>

View file

@ -151,8 +151,7 @@
{href: '/tabs',text: 'Tabs',icon: 'switch_camera'},
{href: '/validate',text: 'Validate',icon: 'playlist_add_check'},
{href: '/transform',text: 'XSLT Transform',icon: 'forward'},
{href: '/tasks',text: 'Tasks',icon: 'update'},
{href: '/logdate',text: 'XML logs',icon: 'dns'},
{href: '/history/tasks',text: 'history',icon: 'history'}
]},
{
@ -163,6 +162,8 @@
{href: '/database', text: 'Databases',icon: 'developer_mode' },
{href: '/files', text: 'File system',icon: 'folder' },
{href: '/documentation', text: 'Documentation',icon: 'library_books' },
{href: '/tasks',text: 'Tasks',icon: 'update'},
{href: '/logdate',text: 'XML logs',icon: 'dns'},
{href: '/history/files',text: 'history',icon: 'history'}
]},
{

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<!--
dropdown with dice range
props
'query' object with start and limit
-->
<template id="qd-range">
<v-menu left bottom :close-on-content-click="false" >
<template v-slot:activator="{ on }">
<v-chip v-on="on">
Range
<v-icon right>arrow_drop_down</v-icon>
</v-chip>
</template>
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>Range</v-card-title>
<v-card-text>
<v-text-field type="number" v-model.number="query.window" label="window (secs)" > </v-text-field>
<v-text-field type="number" v-model.number="query.start" label="start" > </v-text-field>
<v-text-field type="number" v-model.number="query.limit" label="limit" > </v-text-field>
</v-card-text>
<v-card-actions>
<v-btn>Reset</v-btn>
</v-card-actions>
</v-card>
</v-menu>
</template>
<script>{
props: ['query' ]
}</script>

View file

@ -25,6 +25,9 @@ for vis-time-line http://visjs.org/docs/graph2d/
items(newItems){
console.log("timeline new:" + newItems.length)
this.rebuild(newItems)
},
options(newOpts){
console.log("opts: ",newOpts)
}
},
mounted: function () {

View file

@ -57,11 +57,14 @@ event fired cmd outline
},
"settings":{
handler:function(vnew,vold){
//console.log("aCe settings:",vnew,this)
this.applySettings(vnew)
// alert("setting")
},
deep:true
}
},
// whenever theme changes, this function will run
"$vuetify.theme.dark": function (newState) {this.setTheme()}
},
methods:{
@ -109,10 +112,7 @@ event fired cmd outline
}
},
watch: {
// whenever theme changes, this function will run
"$vuetify.theme.dark": function (newState) {this.setTheme()}
},
mounted () {
const mode = this.mode || 'text'

View file

@ -100,8 +100,6 @@ return $a `},
"edit/query": "todo edit/query"
},
getItem (key) {
if (this.debug) console.log('getItem',key);
return localforage.getItem(key)
@ -115,6 +113,7 @@ return $a `},
});
},
setItem (key,value) {
if (this.debug) console.log('setItem',key,value);
return localforage.setItem(key, value)
@ -137,10 +136,11 @@ return $a `},
console.log('delete failed');
});
},
keys(){
return localforage.keys() // returns array of keys
},
clear(){
localforage.clear()
}

View file

@ -1,6 +1,5 @@
<entity name="basexjob" xmlns="https://github.com/Quodatum/app-doc/entity">
<description>A BaseX job</description>
<namespace prefix="xqdoc" uri="http://www.xqdoc.org/1.0"/>
<entity name="basex.job" xmlns="https://github.com/Quodatum/app-doc/entity">
<description>An active BaseX job</description>
<fields>
<field name="id" type="xs:string">
<description>unique id</description>
@ -27,7 +26,7 @@
<xpath>@start</xpath>
</field>
<field name="duration" type="xs:string">
<description>start</description>
<description>duration</description>
<xpath>@duration</xpath>
</field>
<field name="interval" type="xs:string">

View file

@ -1,4 +1,4 @@
<entity name="basexlog" xmlns="https://github.com/Quodatum/app-doc/entity">
<entity name="basex.log" xmlns="https://github.com/Quodatum/app-doc/entity">
<description>BaseX log entries for today and yesterday from the running server</description>
<fields>

View file

@ -1,4 +1,4 @@
<entity name="repo" xmlns="https://github.com/Quodatum/app-doc/entity">
<entity name="basex.repo" xmlns="https://github.com/Quodatum/app-doc/entity">
<description>An entry in the basex repository</description>
<fields>

View file

@ -1,4 +1,4 @@
<entity name="service" xmlns="https://github.com/Quodatum/app-doc/entity">
<entity name="basex.service" xmlns="https://github.com/Quodatum/app-doc/entity">
<description>basex services a list of all jobs that have been persistently registered as Services.</description>
<fields>
<field name="id" type="xs:string">

View file

@ -1,4 +1,4 @@
<entity name="user" xmlns="https://github.com/Quodatum/app-doc/entity">
<entity name="basex.user" xmlns="https://github.com/Quodatum/app-doc/entity">
<description>A BaseX user </description>
<fields>

View file

@ -1,20 +1,45 @@
<entity name="basexlogfile" xmlns="https://github.com/Quodatum/app-doc/entity">
<description>saved BaseX log entries in the vue-poc database</description>
<description>list of saved BaseX log files with entries in the vue-poc database</description>
<fields>
<field name="date" type="xs:string">
<description>log date</description>
<xpath>text()!fn:replace(.,".*(\d{4}-\d{2}-\d{2}).*","$1")</xpath>
<xpath>@date</xpath>
</field>
<field name="name" type="xs:string">
<description>file name</description>
<xpath>.</xpath>
<xpath>@file</xpath>
</field>
<field name="entries" type="xs:integer">
<description>total entries</description>
<xpath>@entries</xpath>
</field>
<field name="max" type="xs:integer">
<description>longest response time (secs)</description>
<xpath>@max</xpath>
</field>
<field name="perhr" type="xs:string">
<description>entries by hour</description>
<xpath>@perhr</xpath>
</field>
</fields>
<views iconclass="calendar_today"/>
<data type="element(resource)">
db:dir("vue-poc","logs")
<data type="element(day)">
let $hrs:=(0 to 23)!format-number(., "00")
for $item in db:dir("vue-poc","logs")
let $es:=db:open("vue-poc","logs/" || $item)/entries/entry
let $max:=round(max($es/@ms) div 1000)
let $times:=(for $e in $es
group by $hr:=substring($e/@time,1,2)
return map:entry($hr, max($e/@ms)))=>map:merge()
let $c:=for $h in $hrs return if(map:contains($times,$h)) then map:get($times,$h) else 0
return &lt;day file="{ $item }"
date="{ fn:replace($item,".*(\d{4}-\d{2}-\d{2}).*","$1")}"
entries="{ count($es) }"
max="{ $max }"
perhr="{ string-join($c,' ') }"
/&gt;
</data>
</entity>

View file

@ -4,11 +4,11 @@
<fields>
<field name="time" type="xs:string">
<description>time of event</description>
<xpath>concat("2019-01-01",'T',@time)</xpath>
<xpath>@date</xpath>
</field>
<field name="end" type="xs:string?">
<description>end time of event</description>
<xpath>self::*[@ms]!(xs:dateTime(concat("2019-01-01",'T',@time))+ xs:dayTimeDuration("PT" || (@ms div 1000) || "S"))</xpath>
<xpath>self::*[@ms]!(xs:dateTime(@date)+ xs:dayTimeDuration("PT" || (@ms div 1000) || "S"))</xpath>
</field>
<field name="address" type="xs:string">
<description>IP address</description>
@ -34,6 +34,6 @@
<views iconclass="calendar_today"/>
<data type="element(entry)">
db:open("vue-poc","/logs/")[1]/entries/entry
db:open("vue-poc","/logs/")[1]/entries/entry (: test data 1st doc :)
</data>
</entity>

View file

@ -13,10 +13,6 @@
</template>
</v-breadcrumbs>
</v-toolbar-title>
<v-btn @click="load" icon :loading="loading"
:disabled="loading"
><v-icon>refresh</v-icon></v-btn>
<v-spacer></v-spacer>
<v-text-field prepend-icon="filter_list" label="Filter..." v-model="q" type="search"
@ -24,6 +20,9 @@
clearable></v-text-field>
<v-spacer></v-spacer>
<v-btn @click="load" icon :loading="loading"
:disabled="loading"
><v-icon>refresh</v-icon></v-btn>
<vp-entitylink entity="basexlogfile"></vp-entitylink>
</v-toolbar>
@ -43,6 +42,16 @@
</router-link></td>
</template>
<template v-slot:item.perhr="{ item }" >
<td >
<v-sparkline
:value="points(item.perhr)" :labels="labels" :fill="true" height="30px" type="bar"
:gradient="['red', 'orange', 'yellow','green','blue']"
></v-sparkline>
</td>
</template>
<template slot="no-results">
No matching results.
</template>
@ -64,9 +73,22 @@
selected:[],
headers: [
{ text: 'Date', value: 'date' },
{text: 'Entries', value: 'entries', align:"end" },
{text: 'Max (secs)', value: 'max', align:"end" },
{text: 'Rate', value: 'perhr' },
{ text: 'File name', value: 'name' }
],
crumbs:[{to:"/logdate", text:"Log files"}]
crumbs:[{to:"/logdate", text:"Log files"}],
labels: [
'.','.','.',
'3am','.','.',
'6am','.','.',
'9am','.','.',
'noon','.','.',
'3pm','.','.',
'6pm','.','.',
'9pm','.','.'
],
}
},
methods: {
@ -80,6 +102,9 @@
})
},
points(perhr){
return perhr.split(' ').map(Number);
},
setfilter(){
console.log("TODO",this.q)
this.$router.push({ query: {url:this.url,q:this.q }})

View file

@ -5,13 +5,18 @@
<template id="basexlogdate1">
<v-container fluid>
<v-card>
<v-toolbar class="lime darken-1">
<v-toolbar >
<v-card-title >
<qd-breadcrumbs @todo="showmenu= ! showmenu"
:crumbs="[{to: '/logdate', text:'log files'}, {text: date, disabled: false, menu: 'todo'}]"
>crumbs</qd-breadcrumbs>
</v-card-title>
<v-btn @click="pageBack()" icon>
<v-avatar><v-icon>skip_previous</v-icon> </v-avatar>
</v-btn>
<v-btn @click="pageNext()" icon>
<v-avatar> <v-icon>skip_next</v-icon> </v-avatar>
</v-btn>
<v-menu
ref="menu"
v-model="showFrom"
@ -39,24 +44,29 @@
@click:second="$refs.menu.save(query.from)"
></v-time-picker>
</v-menu>
<v-toolbar-items>
<v-text-field type="number" v-model.number="query.start" label="start" > </v-text-field>
<v-text-field type="number" v-model.number="query.limit" label="limit" > </v-text-field>
</v-toolbar-items>
<qd-range :query="query"></qd-range>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn @click="fit">fit</v-btn>
<v-btn @click="getItems">
<v-avatar><v-icon>refresh</v-icon></v-avatar>
</v-btn>
<v-btn @click="pageBack()" :disabled="query.start==1" icon>
<v-avatar><v-icon>arrow_back</v-icon> </v-avatar>
</v-btn>
<v-btn @click="pageNext()" icon>
<v-avatar> <v-icon>arrow_forward</v-icon> </v-avatar>
</v-btn>
</v-toolbar-items>
<v-menu bottom left >
<template v-slot:activator="{ on }">
<v-btn icon v-on="on" >
<v-icon>more_vert</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item >
<v-list-item-title> <qd-range :query="query"></qd-range></v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-toolbar>
<v-card-text>
@ -82,7 +92,7 @@
timeAxis: {scale: 'minute', step: 1}
},
data:[],
query:{name: "2019-09-23", start: 1, limit:30, from:"00:00:00", mins:10},
query:{date: this.date, start: 1, limit:30, from:"00:00:00", window:600},
showmenu: false,
Events: new Vue({}),
msg:"Select an entry",
@ -94,31 +104,33 @@ methods:{
fit(){
this.Events.$emit('fit');
},
select(sel){
select(sel){
var hit=this.data.find(item => item.id==sel )
var h=JSON.stringify(hit,null,2)
this.msg= h
},
pageNext(){
this.query.start+= this.query.limit
this.query.from= this.addtime(this.query.from,this.query.mins)
this.query.from= this.addtime(this.query.from,this.query.window)
this.getItems()
},
pageBack(){
this.query.start-= this.query.limit
this.query.from = this.addtime(this.query.from,-this.query.mins)
this.query.from = this.addtime(this.query.from,-this.query.window)
this.getItems()
},
addtime(time,mins){
return moment(time,moment.HTML5_FMT.TIME_SECONDS).add(mins,"m").format(moment.HTML5_FMT.TIME_SECONDS)
addtime(time,secs){
var result= moment(time,moment.HTML5_FMT.TIME_SECONDS).add(secs,"s")
var result= moment.max(result,moment("00:00:00",moment.HTML5_FMT.TIME_SECONDS))
return result.format(moment.HTML5_FMT.TIME_SECONDS)
},
getItems(){
this.loading=true
HTTP.get("logxml", {params:this.query})
.then(r=>{
this.loading=false
//var items=r.data.items.filter(item=>{return item.text!="[GET] http://localhost:8984/vue-poc/api/log"})
var items=r.data.items
//console.log("logxml",items)
@ -130,15 +142,32 @@ methods:{
style: x.text.startsWith("[POST] ")?"background-color: red;": "background-color: yellow;",
group: x.user}
))
//https://stackoverflow.com/a/39637877/3210344 round(date, moment.duration(15, "minutes"), "ceil")
var roundDate= function (date, duration, method) {
return moment(Math[method]((+date) / (+duration)) * (+duration));
}
var start=moment(this.date + "T" + this.query.from)
var first=this.data[0]
if(first){
first=moment(first.time)
start=roundDate(first,moment.duration(this.query.window, "seconds"), "floor")
//console.log(r.format(moment.HTML5_FMT.TIME_SECONDS))
this.query.from=start.format(moment.HTML5_FMT.TIME_SECONDS)
}
this.options.start=start.toDate()
this.options.end=start.add(this.query.window,"s").toDate()
//console.log("data",this.data)
this.loading=false
})
}
},
watch:{
"query":{
handler:function(vnew,vold){
console.log("watch",vnew,vold)
//console.log("watch",this.query)
this.$router.push({ query: this.query })
if(!this.loading) this.getItems()
},
deep:true
}

View file

@ -109,7 +109,7 @@
},
getItems(){
this.loading=true
HTTP.get("log",{params:this.q})
HTTP.get("basex.log",{params:this.q})
.then(r=>{
this.loading=false
//console.log(r.data)

View file

@ -24,17 +24,18 @@ as element(json)
:)
declare
%rest:GET %rest:path("/vue-poc/api/logxml")
%rest:query-param("from", "{ $from }")
%rest:query-param("name", "{ $name }")
%rest:query-param("mins", "{ $mins }")
%rest:query-param("from", "{ $time }")
%rest:query-param("date", "{ $date }")
%rest:query-param("window", "{ $window }")
%output:method("json")
function j:archive( $name,$from,$mins)
function j:archive( $date as xs:string,$time as xs:string,$window)
as element(json)
{
let $_:=trace($from,"from: ")
let $start:=xs:dateTime(concat($date,"T",$time))
let $items:=db:open("vue-poc","/logs/")[contains(base-uri(),$date)]/entries/entry
let $items:=$items transform with { insert node attribute date { concat($date,'T',@time) } into .}
let $items:= if ($time) then $items[xs:dateTime(@date) ge $start] else $items
let $entity:=$entity:list("logxml")
let $items:=db:open("vue-poc","/logs/")/entries[contains(db:path(.),$name)]/entry
(: let $items:= if ($from) then $items[true()] else $items :)
return dice:response($items,$entity,web:dice())
};

View file

@ -9,11 +9,7 @@
>
<template v-slot:header>
<v-toolbar
dark
color="blue darken-3"
class="mb-1"
>
<v-toolbar>
<v-toolbar-title>XQDocs</v-toolbar-title>
<v-spacer></v-spacer>
<v-text-field

View file

@ -83,7 +83,7 @@
methods:{
load(){
this.loading= true
HTTP.get("data/service",{params:{q:this.q}})
HTTP.get("data/basex.service",{params:{q:this.q}})
.then(r=>{
this.items= r.data.items
this.loading= false

View file

@ -1,7 +1,7 @@
<!DOCTYPE html>
<template id="login">
<v-container fluid>
<v-card >
<v-card class="col-md-8 offset-md-2 ">
<v-card-title class="red">
<span class="white--text">The current credentials do the give access this page, please login.</span>
</v-card-title>

View file

@ -16,12 +16,13 @@ declare variable $vue-login:SESSION-VALUE := session:get($vue-login:SESSION-KEY)
: Checks if a session id exists for the current user; if not, redirects to the login page.
:)
declare
(: %perm:check('/vue-poc') :)
%perm:check('/vue-poc')
function vue-login:check-app() {
let $user := session:get('id')
where empty($user)
return web:redirect('/vue-poc/login')
let $_:=trace($user,"CHECK")
return ()
};
(:~
: get status
:)
@ -98,15 +99,22 @@ declare %private function vue-login:accept(
$pass as xs:string,
$path as xs:string?
) {
let $session:=random:uuid()
let $token:= random:uuid()
let $opts:=map{'expires': xs:dayTimeDuration('P7D')}
let $cookies:= map{ "session": $session,
"hash": crypto:hmac($token, 'quo1', 'md5', 'hex')
}
let $val:=vue-login:cookie("remember", random:uuid(),map{'expires': xs:dayTimeDuration('P7D')})
return (
session:set($vue-login:SESSION-KEY, $name),
admin:write-log('VUEPOC user was logged in: ' || $name),
<rest:response>
<http:response>
<http:header name="Set-Cookie" value="{ $val }"/>
<http:header name="Set-Cookie" value="{ vue-login:cookie("hash",$cookies?hash, $opts) }"/>
<http:header name="Set-Cookie" value="{ vue-login:cookie("session",$cookies?session, $opts) }"/>
</http:response>
</rest:response>,
@ -128,7 +136,7 @@ declare %private function vue-login:reject(
$message as xs:string,
$path as xs:string?)
{
let $cookie:=vue-login:cookie("remember", "", map{})
let $cookie:=vue-login:cookie("session", "", map{})
return ( admin:write-log('VUE login was denied: ' || $name),
<rest:response>
<http:response>
@ -144,11 +152,10 @@ declare %private function vue-login:reject(
(:~ return cookie string
:)
declare function vue-login:cookie($name as xs:string,$val,$opts as map(*)?)
declare function vue-login:cookie($name as xs:string, $val ,$opts as map(*)?)
as xs:string
{
let $pic:="[FNn,3-3],[D01] [MNn,3-3] [Y4] [H01]:[m01]:[s01] [z]"
let $expires:=if(map:contains($opts,"expires")) then current-dateTime() + $opts?expires else ()
return``[`{ $name }`=`{ $val }`; path=/; expires=`{ format-dateTime($expires,$pic) }`;]``
};

View file

@ -1,7 +1,7 @@
<!DOCTYPE html>
<template id="repo">
<v-container fluid>
<qd-table :headers="headers" data-uri="data/repo" entity="repo" no-data-msg="Nothing found">
<qd-table :headers="headers" data-uri="data/basex.repo" entity="repo" no-data-msg="Nothing found">
<template slot="items" slot-scope="props">
<td >
<v-checkbox

View file

@ -13,14 +13,14 @@
<table class="v-table">
<thead>
<tr>
<th xs1>Action</th>
<th xs1>Repeat</th>
<th xs1>Last</th>
<th xs1>Count</th>
<th xs1>Avg</th>
<th xs1>min</th>
<th xs1>max</th>
<th xs1>Median</th>
<th class="col-md-1">Action</th>
<th class="col-md-1">Repeat</th>
<th class="col-md-1 text-right">Last</th>
<th class="col-md-1 text-right">Count</th>
<th class="col-md-1 text-right">Avg</th>
<th class="col-md-1 text-right">min</th>
<th class="col-md-1 text-right">max</th>
<th class="col-md-1 text-right">Median</th>
</tr>
</thead>
<tbody>
@ -38,24 +38,24 @@
</td>
<td>
<span >{{getValues.last}}</span>
<p class="text-right">{{getValues.last}}</p>
</td>
<td>
<span >{{getValues.count}}</span>
<p class="text-right" >{{getValues.count}}</p>
</td>
<td>
<span >{{getValues.avg | round(2)}}</span>
<p class="text-right" >{{getValues.avg | round(2)}}</p>
</td>
<td>
<span >{{getValues.min}}</span>
<p class="text-right" >{{getValues.min}}</p>
</td>
<td>
<span >{{getValues.max}}</span>
<p class="text-right" >{{getValues.max}}</p>
</td>
<td>
<span >{{getValues.median}}</span>
<p class="text-right" >{{getValues.median}}</p>
</td>
</tr>
@ -69,26 +69,24 @@
<td>
<v-switch v-on:change="pchange" v-model="repeat.post"></v-switch>
</td>
<td class="col-md-1">
<td class="text-right">
<span >{{postValues.last}}</span>
</td>
<td class="col-md-1">
<td class="text-right">
<span >{{postValues.count}}</span>
</td >
<td class="col-md-1">
<td class="text-right">
<span >{{postValues.avg | round(2)}}</span>
</td>
<td class="col-md-1">
<td class="text-right">
<span >{{postValues.min}}</span>
</td>
<td class="col-md-1">
<td class="text-right">
<span >{{postValues.max}}</span>
</td>
<td class="col-md-1">
<td class="text-right">
<span >{{postValues.median}}</span>
</td>
</tr>

View file

@ -7,7 +7,7 @@
<v-card>
<v-toolbar class="orange">
<v-card-title > <qd-breadcrumbs
:crumbs="[{to: '/settings', text:'Settings'}, {text: 'Common Ace editor settings', disabled: true }]"
:crumbs="[{to: '/settings', text:'Settings'}, {text: 'Common Ace editor settings.', disabled: true }]"
>crumbs</qd-breadcrumbs></v-card-title>
</v-toolbar>
<v-card-text>
@ -18,13 +18,14 @@
<v-flex >
<v-select
:disabled= "$vuetify.theme.dark"
v-bind:items="themes"
v-model="ace.theme"
label="Theme"
></v-select>
</v-flex>
<v-flex >
<v-select
<v-select :disabled= "!$vuetify.theme.dark"
v-bind:items="themesDark"
v-model="ace.themeDark"
label="Dark Theme"
@ -61,7 +62,7 @@
<v-list two-line subheader>
<v-subheader>Ace editor settings</v-subheader>
<v-subheader>Ace editor behaviour</v-subheader>
<v-list-item >
<v-list-item-action>
@ -127,6 +128,7 @@
return obj;
}
},
beforeRouteLeave (to, from, next) {
Settings.setItem('settings/ace',this.ace)
.then(v=>{

View file

@ -1,7 +1,7 @@
<!DOCTYPE html>
<template id="users">
<v-container fluid>
<qd-table :headers="headers" data-uri="data/user" entity="user" no-data-msg="Nothing found">
<qd-table :headers="headers" data-uri="data/basex.user" entity="user" no-data-msg="Nothing found">
<template slot="items" slot-scope="props">
<td >
<v-checkbox

View file

@ -1,18 +1,18 @@
(: entity access maps
: auto generated from xml files in entities folder at: 2019-11-07T11:13:26.624Z
: auto generated from xml files in entities folder at: 2019-12-13T21:11:55.13Z
:)
module namespace entity = 'quodatum.models.generated';
import module namespace cfg = "quodatum:media.image.configure" at "features/images/config.xqm";declare namespace xqdoc='http://www.xqdoc.org/1.0';
declare namespace ent='https://github.com/Quodatum/app-doc/entity';
import module namespace cfg = "quodatum:media.image.configure" at "features/images/config.xqm";declare namespace ent='https://github.com/Quodatum/app-doc/entity';
declare namespace h='urn:quodatum:vue-poc.history';
declare namespace xqdoc='http://www.xqdoc.org/1.0';
declare namespace qns='https://github.com/Quodatum/namespaces';
declare namespace c='http://www.w3.org/ns/xproc-step';
declare variable $entity:list:=map {
"basexjob": map{
"name": "basexjob",
"description": "A BaseX job",
"basex.job": map{
"name": "basex.job",
"description": "An active BaseX job",
"access": map{
"duration": function($_ as element()) as xs:string {$_/@duration },
"id": function($_ as element()) as xs:string {$_/@id },
@ -84,8 +84,8 @@ declare variable $entity:list:=map {
'filter': 'name description'
}
},
"basexlog": map{
"name": "basexlog",
"basex.log": map{
"name": "basex.log",
"description": "BaseX log entries for today and yesterday from the running server",
"access": map{
"address": function($_ as element()) as xs:string {$_/@address },
@ -138,14 +138,121 @@ hof:top-k-by(admin:logs(), string#1, 2)
"views": map{
}
},
"basex.repo": map{
"name": "basex.repo",
"description": "An entry in the basex repository",
"access": map{
"name": function($_ as element()) as xs:string {$_/@name },
"type": function($_ as element()) as xs:string {$_/@type },
"version": function($_ as element()) as xs:string {$_/@version } },
"filter": function($item,$q) as xs:boolean{
some $e in ( ) satisfies
fn:contains($e,$q, 'http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive')
},
"json": map{
"name": function($_ as element()) as element(name)? {
(: xs:string :)
fn:data($_/@name)!element name { .}
},
"type": function($_ as element()) as element(type)? {
(: xs:string :)
fn:data($_/@type)!element type { .}
},
"version": function($_ as element()) as element(version)? {
(: xs:string :)
fn:data($_/@version)!element version { .}
} },
"data": function() as element(package)*
{ repo:list() },
"views": map{
}
},
"basex.service": map{
"name": "basex.service",
"description": "basex services a list of all jobs that have been persistently registered as Services.",
"access": map{
"base-uri": function($_ as element()) as xs:string {$_/@base-uri },
"id": function($_ as element()) as xs:string {$_/@id },
"interval": function($_ as element()) as xs:string {$_/@interval },
"query": function($_ as element()) as xs:string {$_/. },
"running": function($_ as element()) as xs:boolean {$_/(@id = jobs:list-details()/@id) } },
"filter": function($item,$q) as xs:boolean{
some $e in ( ) satisfies
fn:contains($e,$q, 'http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive')
},
"json": map{
"base-uri": function($_ as element()) as element(base-uri)? {
(: xs:string :)
fn:data($_/@base-uri)!element base-uri { .}
},
"id": function($_ as element()) as element(id)? {
(: xs:string :)
fn:data($_/@id)!element id { .}
},
"interval": function($_ as element()) as element(interval)? {
(: xs:string :)
fn:data($_/@interval)!element interval { .}
},
"query": function($_ as element()) as element(query)? {
(: xs:string :)
fn:data($_/.)!element query { .}
},
"running": function($_ as element()) as element(running)? {
(: xs:boolean :)
fn:data($_/(@id = jobs:list-details()/@id))!element running { attribute type {'boolean'}, .}
} },
"data": function() as element(job)*
{ jobs:services() },
"views": map{
}
},
"basex.user": map{
"name": "basex.user",
"description": "A BaseX user ",
"access": map{
"name": function($_ as element()) as xs:string {$_/@name },
"permission": function($_ as element()) as xs:string {$_/@permission } },
"filter": function($item,$q) as xs:boolean{
some $e in ( ) satisfies
fn:contains($e,$q, 'http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive')
},
"json": map{
"name": function($_ as element()) as element(name)? {
(: xs:string :)
fn:data($_/@name)!element name { .}
},
"permission": function($_ as element()) as element(permission)? {
(: xs:string :)
fn:data($_/@permission)!element permission { .}
} },
"data": function() as element(user)*
{ user:list-details() },
"views": map{
}
},
"basexlogfile": map{
"name": "basexlogfile",
"description": "saved BaseX log entries in the vue-poc database",
"description": "list of saved BaseX log files with entries in the vue-poc database",
"access": map{
"date": function($_ as element()) as xs:string {$_/text()!fn:replace(.,".*(\d{4}-\d{2}-\d{2}).*","$1") },
"name": function($_ as element()) as xs:string {$_/. } },
"date": function($_ as element()) as xs:string {$_/@date },
"entries": function($_ as element()) as xs:integer {$_/@entries },
"max": function($_ as element()) as xs:integer {$_/@max },
"name": function($_ as element()) as xs:string {$_/@file },
"perhr": function($_ as element()) as xs:string {$_/@perhr } },
"filter": function($item,$q) as xs:boolean{
some $e in ( ) satisfies
@ -154,16 +261,42 @@ hof:top-k-by(admin:logs(), string#1, 2)
"json": map{
"date": function($_ as element()) as element(date)? {
(: xs:string :)
fn:data($_/text()!fn:replace(.,".*(\d{4}-\d{2}-\d{2}).*","$1"))!element date { .}
fn:data($_/@date)!element date { .}
},
"entries": function($_ as element()) as element(entries)? {
(: xs:integer :)
fn:data($_/@entries)!element entries { attribute type {'number'}, .}
},
"max": function($_ as element()) as element(max)? {
(: xs:integer :)
fn:data($_/@max)!element max { attribute type {'number'}, .}
},
"name": function($_ as element()) as element(name)? {
(: xs:string :)
fn:data($_/.)!element name { .}
fn:data($_/@file)!element name { .}
},
"perhr": function($_ as element()) as element(perhr)? {
(: xs:string :)
fn:data($_/@perhr)!element perhr { .}
} },
"data": function() as element(resource)*
"data": function() as element(day)*
{
db:dir("vue-poc","logs")
let $hrs:=(0 to 23)!format-number(., "00")
for $item in db:dir("vue-poc","logs")
let $es:=db:open("vue-poc","logs/" || $item)/entries/entry
let $max:=round(max($es/@ms) div 1000)
let $times:=(for $e in $es
group by $hr:=substring($e/@time,1,2)
return map:entry($hr, max($e/@ms)))=>map:merge()
let $c:=for $h in $hrs return if(map:contains($times,$h)) then map:get($times,$h) else 0
return <day file="{ $item }"
date="{ fn:replace($item,".*(\d{4}-\d{2}-\d{2}).*","$1")}"
entries="{ count($es) }"
max="{ $max }"
perhr="{ string-join($c,' ') }"
/>
},
"views": map{
@ -393,11 +526,11 @@ hof:top-k-by(admin:logs(), string#1, 2)
"description": " log entries in XML format",
"access": map{
"address": function($_ as element()) as xs:string {$_/@address },
"end": function($_ as element()) as xs:string? {$_/self::*[@ms]!(xs:dateTime(concat("2019-01-01",'T',@time))+ xs:dayTimeDuration("PT" || (@ms div 1000) || "S")) },
"end": function($_ as element()) as xs:string? {$_/self::*[@ms]!(xs:dateTime(@date)+ xs:dayTimeDuration("PT" || (@ms div 1000) || "S")) },
"ms": function($_ as element()) as xs:integer {$_/@ms },
"status": function($_ as element()) as xs:string {$_/@type },
"text": function($_ as element()) as xs:string {$_/. },
"time": function($_ as element()) as xs:string {$_/concat("2019-01-01",'T',@time) },
"time": function($_ as element()) as xs:string {$_/@date },
"user": function($_ as element()) as xs:string {$_/@user } },
"filter": function($item,$q) as xs:boolean{
@ -411,7 +544,7 @@ hof:top-k-by(admin:logs(), string#1, 2)
},
"end": function($_ as element()) as element(end)? {
(: xs:string? :)
fn:data($_/self::*[@ms]!(xs:dateTime(concat("2019-01-01",'T',@time))+ xs:dayTimeDuration("PT" || (@ms div 1000) || "S")))!element end { .}
fn:data($_/self::*[@ms]!(xs:dateTime(@date)+ xs:dayTimeDuration("PT" || (@ms div 1000) || "S")))!element end { .}
},
"ms": function($_ as element()) as element(ms)? {
(: xs:integer :)
@ -427,7 +560,7 @@ hof:top-k-by(admin:logs(), string#1, 2)
},
"time": function($_ as element()) as element(time)? {
(: xs:string :)
fn:data($_/concat("2019-01-01",'T',@time))!element time { .}
fn:data($_/@date)!element time { .}
},
"user": function($_ as element()) as element(user)? {
(: xs:string :)
@ -436,7 +569,7 @@ hof:top-k-by(admin:logs(), string#1, 2)
"data": function() as element(entry)*
{
db:open("vue-poc","/logs/")[1]/entries/entry
db:open("vue-poc","/logs/")[1]/entries/entry (: test data 1st doc :)
},
"views": map{
@ -519,39 +652,6 @@ hof:top-k-by(admin:logs(), string#1, 2)
"views": map{
'filter': 'name description'
}
},
"repo": map{
"name": "repo",
"description": "An entry in the basex repository",
"access": map{
"name": function($_ as element()) as xs:string {$_/@name },
"type": function($_ as element()) as xs:string {$_/@type },
"version": function($_ as element()) as xs:string {$_/@version } },
"filter": function($item,$q) as xs:boolean{
some $e in ( ) satisfies
fn:contains($e,$q, 'http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive')
},
"json": map{
"name": function($_ as element()) as element(name)? {
(: xs:string :)
fn:data($_/@name)!element name { .}
},
"type": function($_ as element()) as element(type)? {
(: xs:string :)
fn:data($_/@type)!element type { .}
},
"version": function($_ as element()) as element(version)? {
(: xs:string :)
fn:data($_/@version)!element version { .}
} },
"data": function() as element(package)*
{ repo:list() },
"views": map{
}
},
"search-result": map{
@ -590,49 +690,6 @@ hof:top-k-by(admin:logs(), string#1, 2)
"views": map{
}
},
"service": map{
"name": "service",
"description": "basex services a list of all jobs that have been persistently registered as Services.",
"access": map{
"base-uri": function($_ as element()) as xs:string {$_/@base-uri },
"id": function($_ as element()) as xs:string {$_/@id },
"interval": function($_ as element()) as xs:string {$_/@interval },
"query": function($_ as element()) as xs:string {$_/. },
"running": function($_ as element()) as xs:boolean {$_/(@id = jobs:list-details()/@id) } },
"filter": function($item,$q) as xs:boolean{
some $e in ( ) satisfies
fn:contains($e,$q, 'http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive')
},
"json": map{
"base-uri": function($_ as element()) as element(base-uri)? {
(: xs:string :)
fn:data($_/@base-uri)!element base-uri { .}
},
"id": function($_ as element()) as element(id)? {
(: xs:string :)
fn:data($_/@id)!element id { .}
},
"interval": function($_ as element()) as element(interval)? {
(: xs:string :)
fn:data($_/@interval)!element interval { .}
},
"query": function($_ as element()) as element(query)? {
(: xs:string :)
fn:data($_/.)!element query { .}
},
"running": function($_ as element()) as element(running)? {
(: xs:boolean :)
fn:data($_/(@id = jobs:list-details()/@id))!element running { attribute type {'boolean'}, .}
} },
"data": function() as element(job)*
{ jobs:services() },
"views": map{
}
},
"task": map{
@ -772,34 +829,6 @@ hof:top-k-by(admin:logs(), string#1, 2)
"views": map{
'filter': 'name'
}
},
"user": map{
"name": "user",
"description": "A BaseX user ",
"access": map{
"name": function($_ as element()) as xs:string {$_/@name },
"permission": function($_ as element()) as xs:string {$_/@permission } },
"filter": function($item,$q) as xs:boolean{
some $e in ( ) satisfies
fn:contains($e,$q, 'http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive')
},
"json": map{
"name": function($_ as element()) as element(name)? {
(: xs:string :)
fn:data($_/@name)!element name { .}
},
"permission": function($_ as element()) as element(permission)? {
(: xs:string :)
fn:data($_/@permission)!element permission { .}
} },
"data": function() as element(user)*
{ user:list-details() },
"views": map{
}
},
"xqdoc": map{

View file

@ -18,6 +18,6 @@
"vuetify-jsonschema-form": "0.27.1",
"prism": "1.15.0",
"vue-prism-component": "1.1.1",
"vis": "4.21.0"
"vis-timeline-graph2d": "4.21.0"
}
}

View file

@ -1,4 +1,4 @@
// generated 2019-11-07T12:55:30.849Z
// generated 2019-12-13T23:01:01.285Z
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/qd-autoheight.vue
Vue.component('qd-autoheight',{template:`
@ -312,6 +312,35 @@ Vue.component('qd-panel',{template:`
);
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/qd-range.vue
Vue.component('qd-range',{template:`
<v-menu left bottom :close-on-content-click="false">
<template v-slot:activator="{ on }">
<v-chip v-on="on">
Range
<v-icon right>arrow_drop_down</v-icon>
</v-chip>
</template>
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>Range</v-card-title>
<v-card-text>
<v-text-field type="number" v-model.number="query.window" label="window (secs)"> </v-text-field>
<v-text-field type="number" v-model.number="query.start" label="start"> </v-text-field>
<v-text-field type="number" v-model.number="query.limit" label="limit"> </v-text-field>
</v-card-text>
<v-card-actions>
<v-btn>Reset</v-btn>
</v-card-actions>
</v-card>
</v-menu>
`,
props: ['query' ]
}
);
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/qd-search.vue
Vue.component('qd-search',{template:`
<v-combobox placeholder="Search..." prepend-icon="search" autocomplete :loading="loading" clearable :items="items2" @keyup.enter="goSearch" :search-input.sync="si" v-model="q">
@ -549,6 +578,9 @@ Vue.component('vis-time-line',{template:`
items(newItems){
console.log("timeline new:" + newItems.length)
this.rebuild(newItems)
},
options(newOpts){
console.log("opts: ",newOpts)
}
},
mounted: function () {
@ -1002,11 +1034,14 @@ Vue.component('vue-ace',{template:`
},
"settings":{
handler:function(vnew,vold){
//console.log("aCe settings:",vnew,this)
this.applySettings(vnew)
// alert("setting")
},
deep:true
}
},
// whenever theme changes, this function will run
"$vuetify.theme.dark": function (newState) {this.setTheme()}
},
methods:{
@ -1054,10 +1089,7 @@ Vue.component('vue-ace',{template:`
}
},
watch: {
// whenever theme changes, this function will run
"$vuetify.theme.dark": function (newState) {this.setTheme()}
},
mounted () {
const mode = this.mode || 'text'
@ -1621,13 +1653,12 @@ const Basexlogdate=Vue.extend({template:`
</template>
</v-breadcrumbs>
</v-toolbar-title>
<v-btn @click="load" icon :loading="loading" :disabled="loading"><v-icon>refresh</v-icon></v-btn>
<v-spacer></v-spacer>
<v-text-field prepend-icon="filter_list" label="Filter..." v-model="q" type="search" hide-details single-line @keyup.enter="setfilter" clearable></v-text-field>
<v-spacer></v-spacer>
<v-btn @click="load" icon :loading="loading" :disabled="loading"><v-icon>refresh</v-icon></v-btn>
<vp-entitylink entity="basexlogfile"></vp-entitylink>
</v-toolbar>
@ -1640,6 +1671,12 @@ const Basexlogdate=Vue.extend({template:`
</router-link></td>
</template>
<template v-slot:item.perhr="{ item }">
<td>
<v-sparkline :value="points(item.perhr)" :labels="labels" :fill="true" height="30px" type="bar" :gradient="['red', 'orange', 'yellow','green','blue']"></v-sparkline>
</td>
</template>
<template slot="no-results">
No matching results.
</template>
@ -1660,9 +1697,22 @@ const Basexlogdate=Vue.extend({template:`
selected:[],
headers: [
{ text: 'Date', value: 'date' },
{text: 'Entries', value: 'entries', align:"end" },
{text: 'Max (secs)', value: 'max', align:"end" },
{text: 'Rate', value: 'perhr' },
{ text: 'File name', value: 'name' }
],
crumbs:[{to:"/logdate", text:"Log files"}]
crumbs:[{to:"/logdate", text:"Log files"}],
labels: [
'.','.','.',
'3am','.','.',
'6am','.','.',
'9am','.','.',
'noon','.','.',
'3pm','.','.',
'6pm','.','.',
'9pm','.','.'
],
}
},
methods: {
@ -1676,6 +1726,9 @@ const Basexlogdate=Vue.extend({template:`
})
},
points(perhr){
return perhr.split(' ').map(Number);
},
setfilter(){
console.log("TODO",this.q)
this.$router.push({ query: {url:this.url,q:this.q }})
@ -1703,35 +1756,45 @@ const Basexlogdate=Vue.extend({template:`
const Basexlogdate1=Vue.extend({template:`
<v-container fluid>
<v-card>
<v-toolbar class="lime darken-1">
<v-toolbar>
<v-card-title>
<qd-breadcrumbs @todo="showmenu= ! showmenu" :crumbs="[{to: '/logdate', text:'log files'}, {text: date, disabled: false, menu: 'todo'}]">crumbs</qd-breadcrumbs>
</v-card-title>
<v-btn @click="pageBack()" icon>
<v-avatar><v-icon>skip_previous</v-icon> </v-avatar>
</v-btn>
<v-btn @click="pageNext()" icon>
<v-avatar> <v-icon>skip_next</v-icon> </v-avatar>
</v-btn>
<v-menu ref="menu" v-model="showFrom" :close-on-content-click="false" :nudge-right="40" :return-value.sync="query.from" transition="scale-transition" offset-y max-width="290px" min-width="100px">
<template v-slot:activator="{ on }">
<v-text-field v-model="query.from" label="Start time" prepend-icon="access_time" readonly v-on="on"></v-text-field>
</template>
<v-time-picker v-if="showFrom" v-model="query.from" full-width use-seconds @click:second="$refs.menu.save(query.from)"></v-time-picker>
</v-menu>
<v-toolbar-items>
<v-text-field type="number" v-model.number="query.start" label="start"> </v-text-field>
<v-text-field type="number" v-model.number="query.limit" label="limit"> </v-text-field>
</v-toolbar-items>
<qd-range :query="query"></qd-range>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn @click="fit">fit</v-btn>
<v-btn @click="getItems">
<v-avatar><v-icon>refresh</v-icon></v-avatar>
</v-btn>
<v-btn @click="pageBack()" :disabled="query.start==1" icon>
<v-avatar><v-icon>arrow_back</v-icon> </v-avatar>
</v-btn>
<v-btn @click="pageNext()" icon>
<v-avatar> <v-icon>arrow_forward</v-icon> </v-avatar>
</v-btn>
</v-toolbar-items>
<v-menu bottom left>
<template v-slot:activator="{ on }">
<v-btn icon v-on="on">
<v-icon>more_vert</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item>
<v-list-item-title> <qd-range :query="query"></qd-range></v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-toolbar>
<v-card-text>
@ -1755,7 +1818,7 @@ const Basexlogdate1=Vue.extend({template:`
timeAxis: {scale: 'minute', step: 1}
},
data:[],
query:{name: "2019-09-23", start: 1, limit:30, from:"00:00:00", mins:10},
query:{date: this.date, start: 1, limit:30, from:"00:00:00", window:600},
showmenu: false,
Events: new Vue({}),
msg:"Select an entry",
@ -1767,31 +1830,33 @@ methods:{
fit(){
this.Events.$emit('fit');
},
select(sel){
select(sel){
var hit=this.data.find(item => item.id==sel )
var h=JSON.stringify(hit,null,2)
this.msg= h
},
pageNext(){
this.query.start+= this.query.limit
this.query.from= this.addtime(this.query.from,this.query.mins)
this.query.from= this.addtime(this.query.from,this.query.window)
this.getItems()
},
pageBack(){
this.query.start-= this.query.limit
this.query.from = this.addtime(this.query.from,-this.query.mins)
this.query.from = this.addtime(this.query.from,-this.query.window)
this.getItems()
},
addtime(time,mins){
return moment(time,moment.HTML5_FMT.TIME_SECONDS).add(mins,"m").format(moment.HTML5_FMT.TIME_SECONDS)
addtime(time,secs){
var result= moment(time,moment.HTML5_FMT.TIME_SECONDS).add(secs,"s")
var result= moment.max(result,moment("00:00:00",moment.HTML5_FMT.TIME_SECONDS))
return result.format(moment.HTML5_FMT.TIME_SECONDS)
},
getItems(){
this.loading=true
HTTP.get("logxml", {params:this.query})
.then(r=>{
this.loading=false
//var items=r.data.items.filter(item=>{return item.text!="[GET] http://localhost:8984/vue-poc/api/log"})
var items=r.data.items
//console.log("logxml",items)
@ -1803,15 +1868,32 @@ methods:{
style: x.text.startsWith("[POST] ")?"background-color: red;": "background-color: yellow;",
group: x.user}
))
//https://stackoverflow.com/a/39637877/3210344 round(date, moment.duration(15, "minutes"), "ceil")
var roundDate= function (date, duration, method) {
return moment(Math[method]((+date) / (+duration)) * (+duration));
}
var start=moment(this.date + "T" + this.query.from)
var first=this.data[0]
if(first){
first=moment(first.time)
start=roundDate(first,moment.duration(this.query.window, "seconds"), "floor")
//console.log(r.format(moment.HTML5_FMT.TIME_SECONDS))
this.query.from=start.format(moment.HTML5_FMT.TIME_SECONDS)
}
this.options.start=start.toDate()
this.options.end=start.add(this.query.window,"s").toDate()
//console.log("data",this.data)
this.loading=false
})
}
},
watch:{
"query":{
handler:function(vnew,vold){
console.log("watch",vnew,vold)
//console.log("watch",this.query)
this.$router.push({ query: this.query })
if(!this.loading) this.getItems()
},
deep:true
}
@ -1980,7 +2062,7 @@ const Log=Vue.extend({template:`
},
getItems(){
this.loading=true
HTTP.get("log",{params:this.q})
HTTP.get("basex.log",{params:this.q})
.then(r=>{
this.loading=false
//console.log(r.data)
@ -2014,7 +2096,7 @@ const Documentation=Vue.extend({template:`
<v-data-iterator :items="items" :items-per-page.sync="itemsPerPage" :search="search" hide-default-footer>
<template v-slot:header>
<v-toolbar dark color="blue darken-3" class="mb-1">
<v-toolbar>
<v-toolbar-title>XQDocs</v-toolbar-title>
<v-spacer></v-spacer>
<v-text-field v-model="search" clearable flat solo-inverted hide-details prepend-inner-icon="search" label="Search"></v-text-field>
@ -4804,7 +4886,7 @@ const Services=Vue.extend({template:`
methods:{
load(){
this.loading= true
HTTP.get("data/service",{params:{q:this.q}})
HTTP.get("data/basex.service",{params:{q:this.q}})
.then(r=>{
this.items= r.data.items
this.loading= false
@ -4838,7 +4920,7 @@ const Services=Vue.extend({template:`
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/login/login.vue
const Login=Vue.extend({template:`
<v-container fluid>
<v-card>
<v-card class="col-md-8 offset-md-2 ">
<v-card-title class="red">
<span class="white--text">The current credentials do the give access this page, please login.</span>
</v-card-title>
@ -5431,7 +5513,7 @@ const Puzzle=Vue.extend({template:`
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/repository.vue
const Repo=Vue.extend({template:`
<v-container fluid>
<qd-table :headers="headers" data-uri="data/repo" entity="repo" no-data-msg="Nothing found">
<qd-table :headers="headers" data-uri="data/basex.repo" entity="repo" no-data-msg="Nothing found">
<template slot="items" slot-scope="props">
<td>
<v-checkbox primary hide-details v-model="props.selected"></v-checkbox>
@ -6089,14 +6171,14 @@ const Ping=Vue.extend({template:`
<table class="v-table">
<thead>
<tr>
<th xs1>Action</th>
<th xs1>Repeat</th>
<th xs1>Last</th>
<th xs1>Count</th>
<th xs1>Avg</th>
<th xs1>min</th>
<th xs1>max</th>
<th xs1>Median</th>
<th class="col-md-1">Action</th>
<th class="col-md-1">Repeat</th>
<th class="col-md-1 text-right">Last</th>
<th class="col-md-1 text-right">Count</th>
<th class="col-md-1 text-right">Avg</th>
<th class="col-md-1 text-right">min</th>
<th class="col-md-1 text-right">max</th>
<th class="col-md-1 text-right">Median</th>
</tr>
</thead>
<tbody>
@ -6114,24 +6196,24 @@ const Ping=Vue.extend({template:`
</td>
<td>
<span>{{getValues.last}}</span>
<p class="text-right">{{getValues.last}}</p>
</td>
<td>
<span>{{getValues.count}}</span>
<p class="text-right">{{getValues.count}}</p>
</td>
<td>
<span>{{getValues.avg | round(2)}}</span>
<p class="text-right">{{getValues.avg | round(2)}}</p>
</td>
<td>
<span>{{getValues.min}}</span>
<p class="text-right">{{getValues.min}}</p>
</td>
<td>
<span>{{getValues.max}}</span>
<p class="text-right">{{getValues.max}}</p>
</td>
<td>
<span>{{getValues.median}}</span>
<p class="text-right">{{getValues.median}}</p>
</td>
</tr>
@ -6145,26 +6227,24 @@ const Ping=Vue.extend({template:`
<td>
<v-switch v-on:change="pchange" v-model="repeat.post"></v-switch>
</td>
<td class="col-md-1">
<td class="text-right">
<span>{{postValues.last}}</span>
</td>
<td class="col-md-1">
<td class="text-right">
<span>{{postValues.count}}</span>
</td>
<td class="col-md-1">
<td class="text-right">
<span>{{postValues.avg | round(2)}}</span>
</td>
<td class="col-md-1">
<td class="text-right">
<span>{{postValues.min}}</span>
</td>
<td class="col-md-1">
<td class="text-right">
<span>{{postValues.max}}</span>
</td>
<td class="col-md-1">
<td class="text-right">
<span>{{postValues.median}}</span>
</td>
</tr>
@ -6371,7 +6451,7 @@ const Acesettings=Vue.extend({template:`
<v-flex xs12 sm8 offset-sm2>
<v-card>
<v-toolbar class="orange">
<v-card-title> <qd-breadcrumbs :crumbs="[{to: '/settings', text:'Settings'}, {text: 'Common Ace editor settings', disabled: true }]">crumbs</qd-breadcrumbs></v-card-title>
<v-card-title> <qd-breadcrumbs :crumbs="[{to: '/settings', text:'Settings'}, {text: 'Common Ace editor settings.', disabled: true }]">crumbs</qd-breadcrumbs></v-card-title>
</v-toolbar>
<v-card-text>
<v-container fluid>
@ -6380,10 +6460,10 @@ const Acesettings=Vue.extend({template:`
<v-layout row>
<v-flex>
<v-select v-bind:items="themes" v-model="ace.theme" label="Theme"></v-select>
<v-select :disabled="$vuetify.theme.dark" v-bind:items="themes" v-model="ace.theme" label="Theme"></v-select>
</v-flex>
<v-flex>
<v-select v-bind:items="themesDark" v-model="ace.themeDark" label="Dark Theme"></v-select>
<v-select :disabled="!$vuetify.theme.dark" v-bind:items="themesDark" v-model="ace.themeDark" label="Dark Theme"></v-select>
</v-flex>
</v-layout>
@ -6409,7 +6489,7 @@ const Acesettings=Vue.extend({template:`
<v-list two-line subheader>
<v-subheader>Ace editor settings</v-subheader>
<v-subheader>Ace editor behaviour</v-subheader>
<v-list-item>
<v-list-item-action>
@ -6474,6 +6554,7 @@ const Acesettings=Vue.extend({template:`
return obj;
}
},
beforeRouteLeave (to, from, next) {
Settings.setItem('settings/ace',this.ace)
.then(v=>{
@ -7156,7 +7237,7 @@ const Thumbnail=Vue.extend({template:`
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/users/users.vue
const Users=Vue.extend({template:`
<v-container fluid>
<qd-table :headers="headers" data-uri="data/user" entity="user" no-data-msg="Nothing found">
<qd-table :headers="headers" data-uri="data/basex.user" entity="user" no-data-msg="Nothing found">
<template slot="items" slot-scope="props">
<td>
<v-checkbox primary hide-details v-model="props.selected"></v-checkbox>
@ -7747,8 +7828,7 @@ const Vuepoc=Vue.extend({template:`
{href: '/tabs',text: 'Tabs',icon: 'switch_camera'},
{href: '/validate',text: 'Validate',icon: 'playlist_add_check'},
{href: '/transform',text: 'XSLT Transform',icon: 'forward'},
{href: '/tasks',text: 'Tasks',icon: 'update'},
{href: '/logdate',text: 'XML logs',icon: 'dns'},
{href: '/history/tasks',text: 'history',icon: 'history'}
]},
{
@ -7759,6 +7839,8 @@ const Vuepoc=Vue.extend({template:`
{href: '/database', text: 'Databases',icon: 'developer_mode' },
{href: '/files', text: 'File system',icon: 'folder' },
{href: '/documentation', text: 'Documentation',icon: 'library_books' },
{href: '/tasks',text: 'Tasks',icon: 'update'},
{href: '/logdate',text: 'XML logs',icon: 'dns'},
{href: '/history/files',text: 'history',icon: 'history'}
]},
{
@ -8014,8 +8096,6 @@ return $a `},
"edit/query": "todo edit/query"
},
getItem (key) {
if (this.debug) console.log('getItem',key);
return localforage.getItem(key)
@ -8029,6 +8109,7 @@ return $a `},
});
},
setItem (key,value) {
if (this.debug) console.log('setItem',key,value);
return localforage.setItem(key, value)
@ -8051,10 +8132,11 @@ return $a `},
console.log('delete failed');
});
},
keys(){
return localforage.keys() // returns array of keys
},
clear(){
localforage.clear()
}

View file

@ -10,7 +10,7 @@
<link rel="shortcut icon" href="/vue-poc/ui/icon.png"/>
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic"/>
<link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons"/>
<link rel="stylesheet" href="//unpkg.com/vuetify@2.1.9/dist/vuetify.min.css" type="text/css"/>
<link rel="stylesheet" href="//unpkg.com/vuetify@2.1.14/dist/vuetify.min.css" type="text/css"/>
<link rel="stylesheet" href="//unpkg.com/@riophae/vue-treeselect@0.0.29/dist/vue-treeselect.min.css"/>
<link rel="stylesheet" href="/vue-poc/ui/prism/prism.css" type="text/css"/>
<link rel="stylesheet" href="//unpkg.com/leaflet@1.0.3/dist/leaflet.css"/>
@ -39,10 +39,10 @@
<script src="//cdnjs.cloudflare.com/ajax/libs/axios/0.18.1/axios.js" crossorigin="anonymous"></script>
<script src="//unpkg.com/vuex@3.1.0/dist/vuex.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/qs/6.4.0/qs.js" crossorigin="anonymous" ></script>
<script src="//unpkg.com/vuetify@2.1.9/dist/vuetify.min.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ace/1.4.6/ace.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ace/1.4.6/ext-language_tools.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ace/1.4.6/ext-linking.js" crossorigin="anonymous" charset="utf-8"></script>
<script src="//unpkg.com/vuetify@2.1.14/dist/vuetify.min.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ace/1.4.7/ace.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ace/1.4.7/ext-language_tools.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ace/1.4.7/ext-linking.js" crossorigin="anonymous" charset="utf-8"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/js-beautify/1.9.0/beautify.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/js-beautify/1.9.0/beautify-css.js" crossorigin="anonymous"></script>