entity allows config

This commit is contained in:
Andy Bunce 2017-08-25 22:00:59 +01:00
parent 07509ce03b
commit 65f868fae4
12 changed files with 166 additions and 112 deletions

View File

@ -0,0 +1,3 @@
<state>
<last-id>3</last-id>
</state>

View File

@ -9,15 +9,15 @@
<v-icon >{{icon}}</v-icon>
</v-btn>
<v-toolbar-title>
<v-breadcrumbs>
<v-breadcrumbs-item v-for="item in crumbs" :key="item.path" :to="{ query: { url: item.path }}">
{{ item.name }}
</v-breadcrumbs-item>
</v-breadcrumbs>
<v-breadcrumbs>
<v-breadcrumbs-item v-for="item in crumbs" :key="item.path" :to="{ query: { url: item.path }}">
{{ item.name }}
</v-breadcrumbs-item>
</v-breadcrumbs>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-text-field prepend-icon="search" label="Filter..." v-model="q" type="search"
hide-details single-line @keyup.enter="filter"></v-text-field>
<v-text-field prepend-icon="search" label="Filter..." v-model="q" type="search"
hide-details single-line @keyup.enter="setfilter"></v-text-field>
<v-btn icon @click="alert('todo')">
<v-icon>view_module</v-icon>
@ -30,7 +30,9 @@
<v-layout>
<v-flex>
<v-list v-if="!busy" two-line subheader>
<v-subheader inset>Folders</v-subheader>
<v-subheader inset >
<span >Folders ({{ folders.length }})</span>
</v-subheader>
<v-list-tile v-for="item in folders" v-bind:key="item.name" @click="folder(item)" avatar >
<v-list-tile-avatar >
<v-icon v-bind:class="[item.iconClass]">{{ item.icon }}</v-icon>
@ -47,7 +49,9 @@
</v-list-tile>
<v-divider inset></v-divider>
<v-subheader inset>Files</v-subheader>
<v-subheader inset>
<span >Files ({{ files.length }})</span>
</v-subheader>
<v-list-tile v-for="item in files" v-bind:key="item.name" >
<v-list-tile-avatar>
<v-icon v-bind:class="[item.iconClass]">{{ item.icon }}</v-icon>
@ -93,7 +97,6 @@
url: "",
folders: [],
files: [],
items: ["root"],
q: "",
busy: false,
showInfo: false,
@ -123,10 +126,8 @@
});
},
root(){
this.$router.push({ query: { url: this.url }})
},
filter(){
setfilter(){
console.log("TODO",this.q)
this.$router.push({ query: {url:this.url,q:this.q }})
},
@ -148,21 +149,24 @@
icon(){
return (this.protocol=="basexdb")?"developer_mode":"folder"
},
// array of {name:"that", path:"/this/that/"} for url
crumbs(){
var parts=this.url.split("/").filter((a)=>a.length>0)
var a=parts.map(function(v,i,a){return {name:v,
path:"/"+a.slice(0,i+1).join("/")+"/"}})
return a
var a=parts.map(
function(v,i,a){return {name:v, path:"/"+a.slice(0,i+1).join("/")+"/"}}
)
return a
}
},
watch:{
url(v){
this.$router.push({ query: { url: this.url }})
},
$route(v){
$route(vnew,vold){
//console.log("ROUTE",vnew,vold)
var url=this.$route.query.url
this.url=url?url:"/";
this.load(this.url)
if(vnew.query.url != vold.query.url) this.load(this.url)
}
},
created:function(){

View File

@ -9,9 +9,12 @@
<v-icon>play_circle_outline</v-icon>
Submit</v-btn>
<v-spacer></v-spacer>
<v-btn @click="imports()">
<v-icon>play_circle_outline</v-icon>
<v-btn @click="imports">
<v-icon>library_books</v-icon>
Imports</v-btn>
<v-btn @click="namespaces">
<v-icon>label</v-icon>
Namespaces</v-btn>
<v-menu offset-y>
<v-btn icon primary dark slot="activator"> <v-icon>more_vert</v-icon></v-btn>
<v-list>
@ -31,9 +34,7 @@
></vue-ace>
</v-flex>
</v-card-text>
<v-alert error v-bind:value="showError">
{{result}}
</v-alert>
<v-card-actions v-if="show" >
<v-chip class="primary white--text">{{jobId}}</v-chip>
@ -53,6 +54,11 @@
{{elapsed}}ms</v-chip>
</v-card-actions>
<v-card-text v-if="showError">
<v-alert error >
{{result}}
</v-alert>
</v-card-text>
<v-card-text v-if="showResult">
<v-flex xs12 style="height:200px" fill-height>
<vue-ace :content="result" mode="text" wrap="false" read-only="true"
@ -140,7 +146,7 @@
this.awaitResult(true)
HTTP.post("eval/result/"+this.jobId)
.then(r=>{
this.result=r.data.result
this.result=r.data.result+" "
})
},
hitme(){
@ -151,6 +157,9 @@
imports(){
alert("@TODO imports")
},
namespaces(){
alert("@TODO namespaces")
},
plan(){
this.awaitResult(false)
HTTP.post("eval/plan",Qs.stringify({xq:this.xq}))
@ -166,6 +175,7 @@
},
awaitResult(show){
// ace slow when setting large text while hidden
this.showError=false
this.show=show
this.result="(Please wait..)"
this.showResult=true

View File

@ -2,7 +2,8 @@ xquery version "3.1";
(:~ data locations for image feature :)
module namespace cfg = "quodatum:media.image.configure";
declare variable $cfg:DB:="vue-poc";
declare variable $cfg:DB-IMAGE:="vue-poc";
declare variable $cfg:IMAGEDIR:="P:/pictures/Pictures/";
declare variable $cfg:THUMBDIR:="C:/tmp/";

View File

@ -159,20 +159,20 @@
<script>{
data: () => ({
images:[],
query:{page:0, // current page
query: {page:0, // current page
from:null,
until:null,
keyword:null
},
total:null,
elapsed:null,
showFilter:false,
busy:false,
menu2:false,
showUntil:false,
keywords:[],
showInfo:false,
selitem:"TODO"
total: null,
elapsed: null,
showFilter: false,
busy: false,
menu2: false,
showUntil: false,
keywords: [],
showInfo: false,
selitem: "TODO"
}),
methods:{
src(item){
@ -228,8 +228,18 @@
},
deep:true
},
$route(v){
this.getImages()
},
showFilter(){
if(this.keywords.length==0){
HTTP.get("images/keywords")
.then(r=>{
this.keywords=r.data.items
})
}
}
},
created:function(){
@ -239,10 +249,7 @@
this.query.from=this.$route.query.from || this.query.from
this.query.until=this.$route.query.until || this.query.until
this.getImages()
HTTP.get("images/keywords")
.then(r=>{
this.keywords=r.data.items
})
},
mounted:function(){
console.log("images mount")

View File

@ -19,7 +19,7 @@ declare
%output:method("json")
function vue-api:id( $id as xs:integer)
{
let $image:=db:open-id("vue-poc",$id)
let $image:=db:open-id($cfg:DB-IMAGE,$id)
return <json type="object" >
<doc>{ serialize($image) }</doc>
{ vue-api:get-image($image) }
@ -72,7 +72,7 @@ declare
function vue-api:keywords()
{
let $keys:=
collection("/vue-poc/image")/image/keywords/keyword
collection($cfg:DB-IMAGE || "/image")/image/keywords/keyword
=>distinct-values()
=>sort("http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive")
return <json type="object" >
@ -87,7 +87,7 @@ declare
%rest:GET %rest:path("/vue-poc/api/images/list/{ $id }/image")
function vue-api:rawimage($id as xs:integer)
{
let $image as element(image):=db:open-id("vue-poc",$id)
let $image as element(image):=db:open-id($cfg:DB-IMAGE,$id)
let $path:=$cfg:IMAGEDIR || '../' || $vue-api:entity?access?path($image)
return (
web:response-header(map { 'media-type': web:content-type($path) }),
@ -100,8 +100,8 @@ declare
%rest:GET %rest:path("/vue-poc/api/images/list/{ $id }/meta")
function vue-api:meta($id as xs:integer)
{
let $image as element(image):=db:open-id("vue-poc",$id)
let $path:="vue-poc/meta/" || $vue-api:entity?access?path($image) || "/meta.xml"
let $image as element(image):=db:open-id($cfg:DB-IMAGE,$id)
let $path:=$cfg:DB-IMAGE || "/meta/" || $vue-api:entity?access?path($image) || "/meta.xml"
return doc($path)
};

View File

@ -5,28 +5,21 @@ module namespace bf = 'quodatum.tools.buildfields';
declare default function namespace 'quodatum.tools.buildfields';
declare namespace ent="https://github.com/Quodatum/app-doc/entity";
(:~
: write generated xquery module from entity xml
: @param efolder full path to folder with entities e.g. fn:resolve-uri("./data/models")
: @param dest full name of xqm to create e.g. fn:resolve-uri("models.xqm")
:)
declare %updating function write($efolder as xs:string,$dest as xs:string)
{
let $src:=bf:module(bf:sources($efolder))
return file:write-text($dest,$src)
};
(:~
: generate xquery module for given entities as a string
:)
declare function module($entities as element(ent:entity)*) as xs:string
declare function module($entities as element(ent:entity)*,$imports)
as xs:string
{
let $src:= <text>(: entity access maps
: auto generated from xml files in entities folder at: {fn:current-dateTime()}
:)
module namespace entity = 'quodatum.models.generated';
{bf:build-modules($entities)}
{$imports}
{bf:build-imports($entities)}
{bf:build-namespaces($entities)}
{( bf:build-describe($entities))}
@ -83,7 +76,8 @@ declare function generate($e as element(ent:entity)) as xs:string
(:~
: @return sequence of element(entity) items for definitions at path
:)
declare function sources($path as xs:string) as element(ent:entity)*
declare function entities($path as xs:string)
as element(ent:entity)*
{
let $_:=fn:trace($path,"DD")
let $p:=fn:resolve-uri($path) || "/"
@ -93,7 +87,8 @@ let $_:=fn:trace($path,"DD")
};
(:map for entity :)
declare function build-map($entity as element(ent:entity)) as xs:string
declare function build-map($entity as element(ent:entity))
as xs:string
{
let $m:=for $field in $entity/ent:fields/ent:field
order by $field/@name
@ -166,21 +161,26 @@ switch ($xsd)
};
(:~ declare any namespaces found :)
declare function build-namespaces($entities as element()*){
declare function build-namespaces($entities as element()*)
{
for $n in distinct-deep($entities/ent:namespace)
return
<text>declare namespace {$n/@prefix/fn:string()}='{$n/@uri/fn:string()}';
</text>
};
(:~ declare any namespaces found :)
declare function build-modules($entities as element()*){
(:~ import any modules found must be in repo :)
declare function build-imports($entities as element()*)
{
for $n in distinct-deep($entities/ent:module)
return
<text>import module namespace {$n/@prefix/fn:string()}='{$n/@namespace/fn:string()}';
</text>
};
declare function build-describe($entities){
declare function build-describe($entities)
as xs:string
{
let $m:=for $e in $entities
return generate($e)
return <text>
@ -191,7 +191,8 @@ declare variable $entity:list:=map {{ {fn:string-join($m,",")}
};
declare function escape($str as xs:string)
as xs:string{
as xs:string
{
fn:replace(
fn:replace($str,'"','""'),
"'","''")

View File

@ -25,7 +25,7 @@ declare variable $vue:DEST:="static/app-gen.js";
declare function vue:feature($doc,$isComp as xs:boolean)
as xs:string
{
let $p:=vue:parse($doc=>trace("feature: "))
let $p:=vue:parse($doc)
let $script:= $p?script=>substring-after("{")
return if(empty($p?id)) then
@ -67,7 +67,7 @@ declare function vue:capitalize-first
declare function vue:feature-files($proj)
as xs:string*
{
let $FEATURES:="features/"=>file:resolve-path($proj=>trace("proj:"))
let $FEATURES:="features/"=>file:resolve-path($proj)
return fw:directory-list($FEATURES,map{"include-filter":".*\.vue"})
//c:file/@name/resolve-uri(.,base-uri(.))
};

View File

@ -1,9 +1,9 @@
(: entity access maps
: auto generated from xml files in entities folder at: 2017-08-23T10:12:22.413+01:00
: auto generated from xml files in entities folder at: 2017-08-25T21:59:02.677+01:00
:)
module namespace entity = 'quodatum.models.generated';
declare namespace h='urn:quodatum:vue-poc.history';
import module namespace cfg = "quodatum:media.image.configure" at "features/images/config.xqm";declare namespace h='urn:quodatum:vue-poc.history';
declare namespace c='http://www.w3.org/ns/xproc-step';
declare variable $entity:list:=map {
@ -130,7 +130,7 @@ declare variable $entity:list:=map {
} },
"data": function() as element(image)*
{ collection("/vue-poc/image")/image },
{ collection($cfg:DB-IMAGE || "/image")/image },
"views": map{
'filter': 'name'

View File

@ -24,6 +24,6 @@
<view name="filter">name</view>
</views>
<iconclass>fa fa-file</iconclass>
<data type="element(image)">collection("/vue-poc/image")/image</data>
<data type="element(image)">collection($cfg:DB-IMAGE || "/image")/image</data>
</entity>

View File

@ -1,4 +1,4 @@
// generated 2017-08-24T18:16:31.442+01:00
// generated 2017-08-25T20:24:29.63+01:00
Vue.component('qd-link',{template:`
<a :href="href" :target="href"> {{href}}<v-icon>link</v-icon></a>
`,
@ -262,14 +262,14 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
<v-icon>{{icon}}</v-icon>
</v-btn>
<v-toolbar-title>
<v-breadcrumbs>
<v-breadcrumbs-item v-for="item in crumbs" :key="item.path" :to="{ query: { url: item.path }}">
{{ item.name }}
</v-breadcrumbs-item>
</v-breadcrumbs>
<v-breadcrumbs>
<v-breadcrumbs-item v-for="item in crumbs" :key="item.path" :to="{ query: { url: item.path }}">
{{ item.name }}
</v-breadcrumbs-item>
</v-breadcrumbs>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-text-field prepend-icon="search" label="Filter..." v-model="q" type="search" hide-details="" single-line="" @keyup.enter="filter"></v-text-field>
<v-text-field prepend-icon="search" label="Filter..." v-model="q" type="search" hide-details="" single-line="" @keyup.enter="setfilter"></v-text-field>
<v-btn icon="" @click="alert('todo')">
<v-icon>view_module</v-icon>
@ -282,7 +282,9 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
<v-layout>
<v-flex>
<v-list v-if="!busy" two-line="" subheader="">
<v-subheader inset="">Folders</v-subheader>
<v-subheader inset="">
<span>Folders ({{ folders.length }})</span>
</v-subheader>
<v-list-tile v-for="item in folders" v-bind:key="item.name" @click="folder(item)" avatar="">
<v-list-tile-avatar>
<v-icon v-bind:class="[item.iconClass]">{{ item.icon }}</v-icon>
@ -299,7 +301,9 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
</v-list-tile>
<v-divider inset=""></v-divider>
<v-subheader inset="">Files</v-subheader>
<v-subheader inset="">
<span>Files ({{ files.length }})</span>
</v-subheader>
<v-list-tile v-for="item in files" v-bind:key="item.name">
<v-list-tile-avatar>
<v-icon v-bind:class="[item.iconClass]">{{ item.icon }}</v-icon>
@ -344,7 +348,6 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
url: "",
folders: [],
files: [],
items: ["root"],
q: "",
busy: false,
showInfo: false,
@ -374,10 +377,8 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
});
},
root(){
this.$router.push({ query: { url: this.url }})
},
filter(){
setfilter(){
console.log("TODO",this.q)
this.$router.push({ query: {url:this.url,q:this.q }})
},
@ -399,21 +400,24 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
icon(){
return (this.protocol=="basexdb")?"developer_mode":"folder"
},
// array of {name:"that", path:"/this/that/"} for url
crumbs(){
var parts=this.url.split("/").filter((a)=>a.length>0)
var a=parts.map(function(v,i,a){return {name:v,
path:"/"+a.slice(0,i+1).join("/")+"/"}})
return a
var a=parts.map(
function(v,i,a){return {name:v, path:"/"+a.slice(0,i+1).join("/")+"/"}}
)
return a
}
},
watch:{
url(v){
this.$router.push({ query: { url: this.url }})
},
$route(v){
$route(vnew,vold){
//console.log("ROUTE",vnew,vold)
var url=this.$route.query.url
this.url=url?url:"/";
this.load(this.url)
if(vnew.query.url != vold.query.url) this.load(this.url)
}
},
created:function(){
@ -746,9 +750,12 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
<v-icon>play_circle_outline</v-icon>
Submit</v-btn>
<v-spacer></v-spacer>
<v-btn @click="imports()">
<v-icon>play_circle_outline</v-icon>
<v-btn @click="imports">
<v-icon>library_books</v-icon>
Imports</v-btn>
<v-btn @click="namespaces">
<v-icon>label</v-icon>
Namespaces</v-btn>
<v-menu offset-y="">
<v-btn icon="" primary="" dark="" slot="activator"> <v-icon>more_vert</v-icon></v-btn>
<v-list>
@ -766,9 +773,7 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
<vue-ace :content="xq" mode="xquery" wrap="true" v-on:change-content="onChange"></vue-ace>
</v-flex>
</v-card-text>
<v-alert error="" v-bind:value="showError">
{{result}}
</v-alert>
<v-card-actions v-if="show">
<v-chip class="primary white--text">{{jobId}}</v-chip>
@ -788,6 +793,11 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
{{elapsed}}ms</v-chip>
</v-card-actions>
<v-card-text v-if="showError">
<v-alert error="">
{{result}}
</v-alert>
</v-card-text>
<v-card-text v-if="showResult">
<v-flex xs12="" style="height:200px" fill-height="">
<vue-ace :content="result" mode="text" wrap="false" read-only="true"></vue-ace>
@ -873,7 +883,7 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
this.awaitResult(true)
HTTP.post("eval/result/"+this.jobId)
.then(r=>{
this.result=r.data.result
this.result=r.data.result+" "
})
},
hitme(){
@ -884,6 +894,9 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
imports(){
alert("@TODO imports")
},
namespaces(){
alert("@TODO namespaces")
},
plan(){
this.awaitResult(false)
HTTP.post("eval/plan",Qs.stringify({xq:this.xq}))
@ -899,6 +912,7 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
},
awaitResult(show){
// ace slow when setting large text while hidden
this.showError=false
this.show=show
this.result="(Please wait..)"
this.showResult=true
@ -1130,20 +1144,20 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
data: () => ({
images:[],
query:{page:0, // current page
query: {page:0, // current page
from:null,
until:null,
keyword:null
},
total:null,
elapsed:null,
showFilter:false,
busy:false,
menu2:false,
showUntil:false,
keywords:[],
showInfo:false,
selitem:"TODO"
total: null,
elapsed: null,
showFilter: false,
busy: false,
menu2: false,
showUntil: false,
keywords: [],
showInfo: false,
selitem: "TODO"
}),
methods:{
src(item){
@ -1199,8 +1213,18 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
},
deep:true
},
$route(v){
this.getImages()
},
showFilter(){
if(this.keywords.length==0){
HTTP.get("images/keywords")
.then(r=>{
this.keywords=r.data.items
})
}
}
},
created:function(){
@ -1210,10 +1234,7 @@ v0.0.3 </v-card-title> </v-card> </v-flex> <v-flex xs4="">
this.query.from=this.$route.query.from || this.query.from
this.query.until=this.$route.query.until || this.query.until
this.getImages()
HTTP.get("images/keywords")
.then(r=>{
this.keywords=r.data.items
})
},
mounted:function(){
console.log("images mount")

View File

@ -6,7 +6,14 @@
declare namespace task="https://github.com/Quodatum/app-doc/task";
import module namespace bf = 'quodatum.tools.buildfields' at "../lib/entity-gen.xqm";
let $efolder:="C:/Users/andy/git/vue-poc/src/vue-poc/models"
let $target:="C:/Users/andy/git/vue-poc/src/vue-poc/models.gen.xqm"
return (bf:write($efolder,$target),db:output("generated " || $target))
declare variable $efolder:="C:/Users/andy/git/vue-poc/src/vue-poc/models";
declare variable $target:="C:/Users/andy/git/vue-poc/src/vue-poc/models.gen.xqm";
let $config:='import module namespace cfg = "quodatum:media.image.configure" at "features/images/config.xqm";'
let $src:=bf:module(bf:entities($efolder),$config)
return (
file:write-text($target,$src)
,db:output("generated " || $target)
)