diff --git a/src/vue-poc/collection.xq b/src/vue-poc/collection.xq new file mode 100644 index 0000000..fc5a6b5 --- /dev/null +++ b/src/vue-poc/collection.xq @@ -0,0 +1,6 @@ +declare namespace fw="quodatum:collection.walker"; +declare namespace c="http://www.w3.org/ns/xproc-step"; +import module namespace tree="quodatum.data.tree" at "lib/tree.xqm"; + +let $paths:=uri-collection("/ALO") +return tree:build($paths) \ No newline at end of file diff --git a/src/vue-poc/data/vue-poc/xproc-enrich.xpl b/src/vue-poc/data/vue-poc/xproc-enrich.xpl new file mode 100644 index 0000000..717ffd0 --- /dev/null +++ b/src/vue-poc/data/vue-poc/xproc-enrich.xpl @@ -0,0 +1,69 @@ + + + Convert xpl to standard format + taken from Phillip Fennel's xproc-plus-time + https://code.google.com/p/xproc-plus-time/ + + + + + + + An xproc document + + + +

+ Copy of the source in a standard format with + additional info +

    +
  1. normalize : pipeline elements replaced with declare-step
  2. +
  3. augment: add missing (default) ports with @xml:id
  4. +
  5. connect: add @xpt:boundPorts showing links
  6. +
+

+
+ + + + Normalises XProc pipelines. + + + + + + + + + + + + Adds missing 'implied' information. + + + + + + + + + + + + Makes step connections explicit. + + + + + + + + +
+ +
\ No newline at end of file diff --git a/src/vue-poc/lib/tree.xqm b/src/vue-poc/lib/tree.xqm new file mode 100644 index 0000000..14c7aee --- /dev/null +++ b/src/vue-poc/lib/tree.xqm @@ -0,0 +1,78 @@ +xquery version "3.1"; +module namespace tree = 'quodatum.data.tree'; + + +(:~ + : convert path(s) to tree + :) +declare function tree:build($a as xs:string*) +{ +fn:fold-right($a, + (), + function($a,$b){tree:merge(tree:tree($a),$b)} + ) +}; + +declare function tree:w($this,$seen) +as element(*) +{ + {$seen} +}; + +declare function tree:tree($path as xs:string) +as element(*) +{ + let $parts:=fn:tokenize($path,"/") + return fn:fold-right(subsequence($parts,1,count($parts)-1), + , + tree:w#2 + ) +}; + +declare function tree:merge($a1 as element(*)?,$a2 as element(*)?) +as element(*)* +{ + if($a1/@name=$a2/@name) then + let $n1:=$a1/* + let $n2:=$a2/* + + let $t:=( + for $x in fn:distinct-values($n1/@name[.=$n2/@name]) (:both:) + return tree:merge($a1/*[@name=$x],$a2/*[@name=$x]), + + for $x in fn:distinct-values($n1/@name[fn:not(.=$n2/@name)]) (:only $a1 :) + return $a1/*[@name=$x], + + for $x in fn:distinct-values($n2/@name[fn:not(.=$n1/@name)]) (:only $a2 :) + return $a2/*[@name=$x] + ) + return tree:w($a1/@name,for $x in $t order by $x/@name return $x) + else + ($a1,$a2) +}; + + + + +declare %unit:test +(:~ + : smoke test + :) +function tree:test(){ + let $a:=("/", + "/api/environment/", + "/api/execute/", + "/api/library/", + "/api/library/", + "/api/library/{$id}/", + "/api/library/{$id}/", + "/api/state/", + "/api/~testbed/", + "/api/state/", + "/api/state/", + "/api/suite/", + "/api/suite/{$suite}/", + "/api/execute/zz") + let $t:=tree:build($a) + return unit:assert(fn:true()) +}; diff --git a/src/vue-poc/login.xqm b/src/vue-poc/login.xqm index 20ff323..cb3558b 100644 --- a/src/vue-poc/login.xqm +++ b/src/vue-poc/login.xqm @@ -20,23 +20,21 @@ declare variable $vue-login:SESSION-VALUE := Session:get($vue-login:SESSION-KEY) :) declare %rest:path("/vue-poc/api/login-check") - %rest:query-param("name", "{$name}") - %rest:query-param("pass", "{$pass}") - %rest:query-param("redirect", "{$path}") + %rest:form-param("username", "{$name}") + %rest:form-param("password", "{$pass}") function vue-login:login( $name as xs:string, - $pass as xs:string, - $path as xs:string? + $pass as xs:string ) as element(rest:response) { try { user:check($name, $pass), if(false() and user:list-details($name)/@permission ) then ( - vue-login:reject($name, 'Admin credentials required.', $path) + vue-login:reject($name, 'Admin credentials required.', "$path") ) else ( - vue-login:accept($name, $pass, $path) + vue-login:accept($name, $pass, "$path") ) } catch user:* { - vue-login:reject($name, 'Please check your login data.', $path) + vue-login:reject($name, 'Please check your login data.', "$path") } }; diff --git a/src/vue-poc/ping.xqm b/src/vue-poc/ping.xqm new file mode 100644 index 0000000..d27c152 --- /dev/null +++ b/src/vue-poc/ping.xqm @@ -0,0 +1,26 @@ +module namespace ping = 'quodatum.test.ping'; +declare variable $ping:db as xs:string:="doc-doc"; +declare variable $ping:state as element(state):=db:open($ping:db,"/state.xml")/state; + +(:~ + : ping incr counter + :) +declare %updating +%rest:POST %rest:path("/vue-poc/api/ping") +%output:method("text") +function ping:dopost() +{ + (replace value of node $ping:state/hits with 1+$ping:state/hits, + db:output(1+$ping:state/hits)) +}; + +(:~ + : ping incr counter + :) +declare +%output:method("text") +%rest:GET %rest:path("/vue-poc/api/ping") +function ping:dostate() +{ + $ping:state/hits +}; \ No newline at end of file diff --git a/src/vue-poc/static/app-gen.js b/src/vue-poc/static/app-gen.js index a4a9e97..155e029 100644 --- a/src/vue-poc/static/app-gen.js +++ b/src/vue-poc/static/app-gen.js @@ -1,4 +1,4 @@ -// generated 2017-06-04T17:31:45.572+01:00 +// generated 2017-06-16T23:13:22.444+01:00 const Edit=Vue.extend({template:` @@ -95,6 +95,11 @@ load html + + + load css + + @@ -249,6 +254,48 @@ } } +); +const Extension=Vue.extend({template:` + + + + + + + +
{{cell}}
+
+ + demo +
+ `, + + data: function(){ + return {grid: [ + [1,5,8,12], + [2,6,9,13], + [3,7,10,14], + [4,null,11,15] + ], + empty:[3,1] + } + }, + methods: { + click: function (row,col) { + var g=this.grid + var h=g[row][col] + g[row][col]=null + g[this.empty[0]][this.empty[1]]=h + var e=[row,col] + this.empty=e + this.grid= g + console.log("click",this.grid,e) + this.$forceUpdate() + } + } +} + + ); const Files=Vue.extend({template:` @@ -280,7 +327,7 @@ const Files=Vue.extend({template:` {{ item.name }} - modified: {{ item.modified | formatDate}} size: {{ item.size | any}} + modified: {{ item.modified | formatDate}} size: {{ item.size | readablizeBytes}} @@ -404,6 +451,7 @@ const Home=Vue.extend({template:`
  • vue-multiselect
  • vue-select
  • js-beautify
  • +
  • doc
  • @@ -430,7 +478,7 @@ const Login=Vue.extend({template:` - + @@ -443,15 +491,27 @@ const Login=Vue.extend({template:` data () { return { - e1: true, + hidepass: true, name:'', password: '' } }, methods:{ go () { - HTTP.post("login-check",axios_json) + this.hidepass=true + var data=Qs.stringify( + { + username: this.name, //gave the values directly for testing + password: this.password, + client_id: 'user-client' + }) + HTTP.post("login-check", data, + { + headers: { + "Content-Type": "application/x-www-form-urlencoded" + }}) .then(r=>{ + console.log(r) alert("loh") }).catch(error=> { alert("err") @@ -537,6 +597,131 @@ const People=Vue.extend({template:` } +); +const Ping=Vue.extend({template:` + +

    Simple performance measure. Read or increment a database value.

    +

    Counter:{{counter}}

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionRepeatLastCountMedianAvgminmax
    + Get count + + + + {{getValues.last}} + + {{getValues.count}} + + {{getValues.median}} + + {{getValues.avg | round(2)}} + + {{getValues.min}} + + {{getValues.max}} +
    + Update count + + + + {{postValues.last}} + + {{postValues.count}} + + {{postValues.median}} + + {{postValues.avg | round(2)}} + + {{postValues.min}} + + {{postValues.max}} +
    +
    + `, + + data: function(){ + return { + getValues: new perfStat(), + postValues: new perfStat(), + repeat:{get:false,post:false}, + counter:0 + } + }, + methods:{ + update () { + var _start = performance.now(); + HTTP.post("ping",axios_json) + .then(r=>{ + var elapsed=Math.floor(performance.now() - _start); + this.counter=r.data + Object.assign(this.postValues,this.postValues.log(elapsed)) + if(this.repeat.post){ + this.update(); //does this leak?? + } + }) + }, + + get(){ + var _start = performance.now(); + HTTP.get("ping",axios_json) + .then(r=>{ + var elapsed=Math.floor(performance.now() - _start); + this.counter=r.data + Object.assign(this.getValues,this.getValues.log(elapsed)) + this.$forceUpdate() + if(this.repeat.get){ + this.get(); //does this leak?? + } + }) + } + }, + computed: { + + } +} + ); const Search=Vue.extend({template:` @@ -617,68 +802,100 @@ const Select=Vue.extend({template:` ); -const Stepper=Vue.extend({template:` - - - - Select image location - - Set thumbnail details - - Result - - - - - - - Next - - - - - - - - Back - Next - +const Settings=Vue.extend({template:` + + + - - - output todo - - - Back - go - - - + + Ace editor settings + + + + + + + Notifications + Allow notifications + + + + + + + + + + Sound + Hangouts message + + + + + + + + + + Video sounds + Hangouts vidoe call + + + + + + + + + + Invites + Notify when receiving invites + + + + + + +
    `, - data(){ + data () { return { - image:"http://images.metmuseum.org/CRDImages/ep/original/DT46.jpg", - step: 0, - taskxml:"" - } + ace: { + notifications: false, + sound: false, + video: false, + invites: false + } + } }, - methods:{ - onChange (val) { - if (this.taskxml !== val) this.taskxml = val; - }, - go(){ - alert("post") - HTTP.post("thumbnail",Qs.stringify({task: this.taskxml,url:this.image})) - .then(function(r){ - console.log(r) - alert("not yet:"+r); - }) - } + created: function () { + // `this` points to the vm instance + console.log('created: ') + localforage.getItem('ace').then((value) => { + console.log('oh say can you see, ' + value); + this.ace=value || this.ace + }).catch((err) => { + console.log('the rockets red glare has blinded me'); + }); + }, + updated: function () { + // `this` points to the vm instance + console.log('updated: ') + localforage.setItem('ace', this.ace).then((value) => { + console.log('woot! we saved ' + value); + }).catch((err) => { + console.log('he\'s dead, jim!'); + }); + }, + methods: { + reverseMessage: function () { + alert("unused") + } } - } + ); const Tabs=Vue.extend({template:` @@ -722,6 +939,73 @@ const Tabs=Vue.extend({template:` } } +); +const Thumbnail=Vue.extend({template:` + + + + Select image location + + Set thumbnail details + + Result + + + + + + + Next + + + + + + + + Back + Validate + Next + + + + + output todo + + + Back + go + + + + `, + + data(){ + return { + image:"http://images.metmuseum.org/CRDImages/ep/original/DT46.jpg", + step: 0, + taskxml:"" + } + }, + methods:{ + onChange (val) { + if (this.taskxml !== val) this.taskxml = val; + }, + validate(){ + alert + }, + go(){ + alert("post") + HTTP.post("thumbnail",Qs.stringify({task: this.taskxml,url:this.image})) + .then(function(r){ + console.log(r) + alert("not yet:"+r); + }) + } + } + +} + ); // base ----------------------- localforage.config({ @@ -736,10 +1020,12 @@ const HTTP = axios.create({ }); const axios_json={ headers: {accept: 'application/json'}}; +// Filters: //Define the date time format filter Vue.filter("formatDate", function(date) { return moment(date).format("MMMM D, YYYY") }); + Vue.filter('readablizeBytes', function (bytes,decimals) { if(bytes == 0) return '0 Bytes'; var k = 1000, @@ -751,6 +1037,25 @@ Vue.filter('readablizeBytes', function (bytes,decimals) { Vue.filter("any", function(any) { return "ANY" }); +/** + * Vue filter to round the decimal to the given place. + * http://jsfiddle.net/bryan_k/3ova17y9/ + * + * @param {String} value The value string. + * @param {Number} decimals The number of decimal places. + */ +Vue.filter('round', function(value, decimals) { + if(!value) { + value = 0; + } + + if(!decimals) { + decimals = 0; + } + + value = Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals); + return value; +}); Vue.config.errorHandler = function (err, vm, info) { // handle error @@ -773,7 +1078,7 @@ const router = new VueRouter({ base:"/vue-poc/ui/", mode: 'history', routes: [ - { path: '/', component: Home }, + { path: '/', component: Home,meta:{title:"Home"} }, { path: '/people', component: People ,meta:{title:"People"}}, { path: '/options', component: Options,meta:{title:"Options"} }, { path: '/select', component: Select,meta:{title:"Select"} }, @@ -781,8 +1086,11 @@ const router = new VueRouter({ { path: '/tabs', component: Tabs,meta:{title:"tab test",requiresAuth: true} }, { path: '/login', component: Login,meta:{title:"login"} }, { path: '/edit', component: Edit,meta:{title:"Ace editor"} }, - { path: '/stepper', component: Stepper,meta:{title:"Stepper"} }, - { path: '/files', component: Files,meta:{title:"Files"} } + { path: '/thumbnail', component: Thumbnail,meta:{title:"Thumbnail generator"} }, + { path: '/files', component: Files,meta:{title:"Files"} }, + { path: '/ping', component: Ping,meta:{title:"Ping"} }, + { path: '/settings', component: Settings,meta:{title:"Settings"} }, + { path: '/extension', component: Extension,meta:{title:"Xform"} } ], }); router.afterEach(function(route) { @@ -813,7 +1121,7 @@ const app = new Vue({ q:"", status:{}, drawer:true, - title:"my title2", + title:"@TODO title", mini: false, items: [{ href: '/', @@ -861,10 +1169,25 @@ const app = new Vue({ title: 'login', icon: 'account_balance' }, { - href: 'stepper', + href: 'ping', router: true, - title: 'stepper', - icon: 'touch_app' + title: 'ping', + icon: 'update' +},{ + href: 'thumbnail', + router: true, + title: 'thumbnail', + icon: 'touch_app' +},{ + href: 'settings', + router: true, + title: 'settings', + icon: 'settings' +},{ + href: 'extension', + router: true, + title: 'extension', + icon: 'extension' }] }}, diff --git a/src/vue-poc/static/app.html b/src/vue-poc/static/app.html index bfebdb8..ed6611f 100644 --- a/src/vue-poc/static/app.html +++ b/src/vue-poc/static/app.html @@ -9,7 +9,7 @@ Vue Router Test - + @@ -19,7 +19,7 @@ - + @@ -30,6 +30,8 @@ + + @@ -73,7 +75,7 @@ - {{title}} + {{$route.meta.title}} diff --git a/src/vue-poc/static/core.js b/src/vue-poc/static/core.js index f9b0171..9de63c0 100644 --- a/src/vue-poc/static/core.js +++ b/src/vue-poc/static/core.js @@ -11,10 +11,12 @@ const HTTP = axios.create({ }); const axios_json={ headers: {accept: 'application/json'}}; +// Filters: //Define the date time format filter Vue.filter("formatDate", function(date) { return moment(date).format("MMMM D, YYYY") }); + Vue.filter('readablizeBytes', function (bytes,decimals) { if(bytes == 0) return '0 Bytes'; var k = 1000, @@ -26,6 +28,25 @@ Vue.filter('readablizeBytes', function (bytes,decimals) { Vue.filter("any", function(any) { return "ANY" }); +/** + * Vue filter to round the decimal to the given place. + * http://jsfiddle.net/bryan_k/3ova17y9/ + * + * @param {String} value The value string. + * @param {Number} decimals The number of decimal places. + */ +Vue.filter('round', function(value, decimals) { + if(!value) { + value = 0; + } + + if(!decimals) { + decimals = 0; + } + + value = Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals); + return value; +}); Vue.config.errorHandler = function (err, vm, info) { // handle error @@ -48,7 +69,7 @@ const router = new VueRouter({ base:"/vue-poc/ui/", mode: 'history', routes: [ - { path: '/', component: Home }, + { path: '/', component: Home,meta:{title:"Home"} }, { path: '/people', component: People ,meta:{title:"People"}}, { path: '/options', component: Options,meta:{title:"Options"} }, { path: '/select', component: Select,meta:{title:"Select"} }, @@ -56,8 +77,11 @@ const router = new VueRouter({ { path: '/tabs', component: Tabs,meta:{title:"tab test",requiresAuth: true} }, { path: '/login', component: Login,meta:{title:"login"} }, { path: '/edit', component: Edit,meta:{title:"Ace editor"} }, - { path: '/stepper', component: Stepper,meta:{title:"Stepper"} }, - { path: '/files', component: Files,meta:{title:"Files"} } + { path: '/thumbnail', component: Thumbnail,meta:{title:"Thumbnail generator"} }, + { path: '/files', component: Files,meta:{title:"Files"} }, + { path: '/ping', component: Ping,meta:{title:"Ping"} }, + { path: '/settings', component: Settings,meta:{title:"Settings"} }, + { path: '/extension', component: Extension,meta:{title:"Xform"} } ], }); router.afterEach(function(route) { @@ -88,7 +112,7 @@ const app = new Vue({ q:"", status:{}, drawer:true, - title:"my title2", + title:"@TODO title", mini: false, items: [{ href: '/', @@ -136,10 +160,25 @@ const app = new Vue({ title: 'login', icon: 'account_balance' }, { - href: 'stepper', + href: 'ping', router: true, - title: 'stepper', - icon: 'touch_app' + title: 'ping', + icon: 'update' +},{ + href: 'thumbnail', + router: true, + title: 'thumbnail', + icon: 'touch_app' +},{ + href: 'settings', + router: true, + title: 'settings', + icon: 'settings' +},{ + href: 'extension', + router: true, + title: 'extension', + icon: 'extension' }] }}, diff --git a/src/vue-poc/static/perf-stat.js b/src/vue-poc/static/perf-stat.js new file mode 100644 index 0000000..c2bab19 --- /dev/null +++ b/src/vue-poc/static/perf-stat.js @@ -0,0 +1,37 @@ +// performance monitoring. of value stream +// stores max min etc +function perfStat() { + this.data={count:0,max:null,min:null,total:0,median:0,last:null}; + // add a value return updated stats + this.log=function(val){ + var data=this.data + data.last=val; + data.total+=val; + data.count+=1; + if(data.count==1){ + data.max=val; + data.min=val; + data.median=val; + }else{ + if(valdata.max)data.max=val; + }; + //https://jeremykun.com/2012/06/14/streaming-median/ + if (data.median > val) + data.median-= 1 + else if( data.median < val) + data.median += 1; + + data.avg=data.total / data.count; + // console.log("stats",data); + return data; + }; + // clear stats + this.clear=function(){ + this.data={count:0,max:null,min:null,total:0}; + }; + // return values + this.values=function(){ + return this.data; + }; +} \ No newline at end of file diff --git a/src/vue-poc/templates/edit.vue b/src/vue-poc/templates/edit.vue index 11a218a..f396dc5 100644 --- a/src/vue-poc/templates/edit.vue +++ b/src/vue-poc/templates/edit.vue @@ -97,6 +97,11 @@ load html + + + load css + + diff --git a/src/vue-poc/templates/extension.vue b/src/vue-poc/templates/extension.vue new file mode 100644 index 0000000..870b828 --- /dev/null +++ b/src/vue-poc/templates/extension.vue @@ -0,0 +1,43 @@ + + + + diff --git a/src/vue-poc/templates/files.vue b/src/vue-poc/templates/files.vue index 1581c9e..65d9873 100644 --- a/src/vue-poc/templates/files.vue +++ b/src/vue-poc/templates/files.vue @@ -30,7 +30,7 @@ {{ item.name }} - modified: {{ item.modified | formatDate}} size: {{ item.size | any}} + modified: {{ item.modified | formatDate}} size: {{ item.size | readablizeBytes}} diff --git a/src/vue-poc/templates/home.vue b/src/vue-poc/templates/home.vue index 79f33a9..d344494 100644 --- a/src/vue-poc/templates/home.vue +++ b/src/vue-poc/templates/home.vue @@ -16,6 +16,7 @@
  • vue-multiselect
  • vue-select
  • js-beautify
  • +
  • doc
  • diff --git a/src/vue-poc/templates/login.vue b/src/vue-poc/templates/login.vue index ffb47e0..a719b1a 100644 --- a/src/vue-poc/templates/login.vue +++ b/src/vue-poc/templates/login.vue @@ -23,9 +23,9 @@ label="Enter your password" hint="Enter your password" v-model="password" - :append-icon="e1 ? 'visibility' : 'visibility_off'" - :append-icon-cb="() => (e1 = !e1)" - :type="e1 ? 'password' : 'text'" + :append-icon="hidepass ? 'visibility' : 'visibility_off'" + :append-icon-cb="() => (hidepass = !hidepass)" + :type="hidepass ? 'password' : 'text'" required > @@ -41,15 +41,27 @@ diff --git a/src/vue-poc/templates/settings.vue b/src/vue-poc/templates/settings.vue new file mode 100644 index 0000000..7108f3c --- /dev/null +++ b/src/vue-poc/templates/settings.vue @@ -0,0 +1,96 @@ + + + + diff --git a/src/vue-poc/templates/stepper.vue b/src/vue-poc/templates/thumbnail.vue similarity index 91% rename from src/vue-poc/templates/stepper.vue rename to src/vue-poc/templates/thumbnail.vue index 3ae1262..fdd857e 100644 --- a/src/vue-poc/templates/stepper.vue +++ b/src/vue-poc/templates/thumbnail.vue @@ -1,5 +1,5 @@ -