initial commit

This commit is contained in:
Andy Bunce 2017-05-22 14:27:25 +01:00
parent e3e3fbf9d3
commit b1c5365bf7
36 changed files with 100477 additions and 1 deletions

22
.project Normal file
View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>vue-poc</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>de.loskutov.FileSync.FSBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,7 @@
WARNING=DO NOT MODIFY THIS FILE IF YOU DON'T UNDERSTAND
defaultDestination=C\:/Program Files (x86)/basex/webapp
defaultVariables=
eclipse.preferences.version=1
includeTeamPrivateFiles=false
map|0=src|,|,|,|,
useCurrentDateForDestinationFiles=false

View file

@ -1,2 +1,6 @@
# vue-poc # vue-poc
Playground for vue.js experiments
A test of using `vue.js` as UI
Includes:
* material design (using `vuetify`)
* ace editor

12
src/vue-poc/build.xq Normal file
View file

@ -0,0 +1,12 @@
let $head:="<head/>"
let $app:="<v-app/>"
return ``[
<!DOCTYPE html>
<html>
`{$head}`
<body>
`{$app}`
<script src="/vue-poc/ui/app.js"></script>
</body>
</html>
]``

9
src/vue-poc/cxan.xml Normal file
View file

@ -0,0 +1,9 @@
<package xmlns="http://cxan.org/ns/package" id="dotml">
<abstract>vue-poc test of vue.js. </abstract>
<author id="abunce">Andy Bunce</author>
<maintainer id="abunce">Andy Bunce</maintainer>
<home></home>
<category id="libs">Library</category>
<tag>vue</tag>
<tag>basex</tag>
</package>

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,5 @@
<package xmlns="http://expath.org/ns/pkg" name="http://expkg-zone58.github.io/ex-dotml"
abbrev="vue-poc" version="0.0.1" spec="1.0">
<title>vue-poc test of vue.js.</title>
</package>

View file

@ -0,0 +1,319 @@
const Home = Vue.extend({ template: '#home'});
const Options = Vue.extend({
template: '#heart',
data: function(){
return {
snackbar:false
}
}
});
const Select = Vue.extend({
template: '#select',
components: { multiselect: VueMultiselect.Multiselect},
data: function(){
return {
value: null,
value2: null,
options: [],
isLoading: false
}
},
created:function(){
this.asyncFind("")
},
methods: {
asyncFind: function(query){
this.isLoading = true
that=this;
HTTP.get("test-select?q="+query,axios_json)
.then(function(r){
that.isLoading = false
that.options=r.data.items;
})
.catch(function (error) {
console.log(error);
this.isLoading = false
alert("Get query error")
});
}
}
});
const People = Vue.extend({
template: '#people',
data: function(){
return {message: 'Hello Vue.js!'}
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
});
const Search = Vue.extend({
template: '#search',
data: function(){
return {
message: 'Hello Vue.js!',
q:this.$route.query.q
}
},
created:function(){
console.log("Serch",this.$route.query.q)
}
});
const Edit = Vue.extend({
template: '#edit',
data () {
return {
contentA: 'declare function local:query($q as xs:string)\n{\n<json type="object" >}',
mode:'xquery',
url:'',
name:'',
path:[],
wrap:false,
busy:false,
clearDialog:false,
annotations:null
}
},
methods: {
reset () {
this.contentA = 'reset content for Editor A'
},
changeContentA (val) {
if (this.contentA !== val) {
this.contentA = val
}
},
// load from url
fetch(url){
this.busy=true
HTTP.get("raw?url="+url,axios_json)
.then(r=>{
//console.log(r)
var a=acetype(r.data.mimetype)
this.mode=a
this.contentA=r.data.data
var a=url.split("/")
this.url=url
this.name=a.pop()
this.path=a
this.busy=false
//alert(mode)
})
.catch(error=> {
console.log(error);
this.busy=false
alert("Get query error"+url)
});
},
acecmd(cmd){
Events.$emit('eventFired',cmd);
},
fold(){
Events.$emit('eventFired',"foldall");
},
save(){
alert("TODO save: "+this.path.join("/"));
},
showfiles(){
router.push({ path: 'files', query: { url: this.path.join("/") }})
},
beautify(){
this.busy=true
var a=this.contentA
switch(this.mode) {
case "html":
case "xml":
a=html_beautify(a, { indent_size: 3 ,indent_inner_html:true})
break;
case "javascript":
a=js_beautify(a, { indent_size: 2 })
break;
case "css":
a=css_beautify(a, { indent_size: 2 })
break;
default:
alert("beaut: " + this.mode)
}
this.contentA=a
this.busy=false
},
annotation(counts){
this.annotations=counts
}
},
created:function(){
var url=this.$route.query.url
console.log("Edit: ",url)
if(url) this.fetch(url)
}
});
const Files = Vue.extend({
template: '#files',
data: function(){
return {url: ".",
folders:[],
files:[],
items:["root"]
}
},
methods:{
click (val) {
// with query, resulting in /register?plan=private
router.push({ path: 'edit', query: { url: this.url+"/" +val }})
},
folder (val) {
this.url+="/"+ val
this.$router.push({ query: { url: this.url }})
this.load(this.url)
},
load(url){
HTTP.get("file?url="+url,axios_json)
.then(r=>{
console.log(r)
this.folders=r.data.folders
this.files=r.data.files
})
.catch(error=> {
console.log(error);
alert("Get query error"+url)
});
},
root(){
this.url="."
this.$router.push({ query: { url: this.url }})
this.load(this.url)
}
},
created:function(){
var url=this.$route.query.url
this.url=url?url:".";
console.log("files: ",this.$route.query.url)
this.load(this.url)
}
});
const Stepper = Vue.extend({
template: '#stepper',
data: function(){
return {e6: 0}
}
});
// base -----------------------
const HTTP = axios.create({
baseURL: "/vue-poc/api/",
headers: {
'X-Custom-Header': 'vue-poc',
accept: 'application/json'
}
});
const axios_json={ headers: {accept: 'application/json'}};
function acetype(mime){
const mimemap={
"text/xml":"xml",
"application/xml":"xml",
"application/xquery":"xquery",
"text/ecmascript":"javascript",
"text/html":"html"
};
var r=mimemap[mime]
return r?r:"text"
};
Vue.component('my-component', {
template: '<div>A custom component!</div>',
created:function(){
console.log("my-component");
},
});
var Events = new Vue({});
const router = new VueRouter({
base:"/vue-poc/ui/",
mode: 'history',
routes: [
{ path: '/', component: Home },
{ path: '/people', component: People ,meta:{title:"People"}},
{ path: '/options', component: Options,meta:{title:"Options"} },
{ path: '/select', component: Select,meta:{title:"Select"} },
{ path: '/search', component: Search,meta:{title:"Search"} },
{ path: '/edit', component: Edit,meta:{title:"Ace editor"} },
{ path: '/stepper', component: Stepper,meta:{title:"Stepper"} },
{ path: '/files', component: Files,meta:{title:"Files"} }
],
});
router.afterEach(function(route) {
document.title = (route.meta.title?route.meta.title:"") + " VUE-Poc";
});
Vue.use(Vuetify);
const app = new Vue({
router,
data:function(){return {
q:"",
sidebar:false,
items: [{
href: '/',
router: true,
title: 'Home',
icon: 'home'
}, {
href: 'files',
router: true,
title: 'files',
icon: 'folder'
}, {
href: 'edit',
router: true,
title: 'edit',
icon: 'mode_edit'
}, {
href: 'search',
router: true,
title: 'search',
icon: 'search'
}, {
href: 'people',
router: true,
title: 'People',
icon: 'person'
}, {
href: 'select',
router: true,
title: 'select',
icon: 'extension'
}, {
href: 'options',
router: true,
title: 'options',
icon: 'domain'
}, {
href: 'stepper',
router: true,
title: 'stepper',
icon: 'picture_in_picture'
}]
}},
methods: {
openSidebar() {
this.sidebar = !this.sidebar;
},
search(){
this.$router.push({path: 'search',query: { q: this.q }})
}
}
}).$mount('#app');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,622 @@
const Edit=Vue.extend({
template: `
<v-container fluid="">
<v-toolbar class="green">
<v-toolbar-side-icon></v-toolbar-side-icon>
<v-toolbar-title>
<v-btn @click.native="showfiles()" small="" icon=""><v-icon>folder</v-icon></v-btn>
<span>{{ name }}</span> <v-chip small="" class="primary white--text">{{ mode }}</v-chip>
</v-toolbar-title>
<v-toolbar-items>
<v-btn dark="" icon="" @click.native="acecmd('outline')">
<v-icon>star</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="acecmd('goToPreviousError')">
<v-icon>navigate_before</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="acecmd('goToNextError')">
<v-icon>navigate_next</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="acecmd('foldall')">
<v-icon>vertical_align_center</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="acecmd('showSettingsMenu')">
<v-icon>settings</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="wrap=!wrap">
<v-icon>wrap_text</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="acecmd('showKeyboardShortcuts')">
<v-icon>keyboard</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="save()">
<v-icon>cloud_upload</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="beautify()">
<v-icon>format_align_center</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="d2 = true">
<v-icon>delete</v-icon>
</v-btn>
<v-menu bottom="" origin="top right" transition="v-scale-transition">
<v-btn dark="" icon="" slot="activator">
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/vue-poc.xqm')">load xquery</v-list-tile-title>
</v-list-tile>
</v-list-item>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/data/vue-poc/ch4d1.xml')">load xml</v-list-tile-title>
</v-list-tile>
</v-list-item>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/static/app.js')">load js</v-list-tile-title>
</v-list-tile>
</v-list-item>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/static/app.html')">load html</v-list-tile-title>
</v-list-tile>
</v-list-item>
</v-list>
</v-menu>
</v-toolbar-items>
</v-toolbar>
<v-progress-linear v-if="busy" v-bind:indeterminate="true"></v-progress-linear>
<v-dialog v-model="clearDialog">
<v-card>
<v-card-row>
<v-card-title>Clear?</v-card-title>
</v-card-row>
<v-card-row>
<v-card-text>clear text.</v-card-text>
</v-card-row>
<v-card-row actions="">
<v-btn class="green--text darken-1" flat="flat" @click.native="clearDialog = false">Cancel</v-btn>
<v-btn class="green--text darken-1" flat="flat" @click.native="reset()">Ok</v-btn>
</v-card-row>
</v-card>
</v-dialog>
<div v-if="!busy" style="height:70vh">
<vue-ace editor-id="editorA" :content="contentA" :mode="mode" :wrap="wrap" v-on:change-content="changeContentA" v-on:annotation="annotation"></vue-ace>
</div>
</v-container>
`,
data () {
return {
contentA: 'declare function local:query($q as xs:string)\n{\n<json type="object" >}',
mode:'xquery',
url:'',
name:'',
path:[],
wrap:false,
busy:false,
clearDialog:false,
annotations:null
}
},
methods: {
reset () {
this.contentA = 'reset content for Editor A'
},
changeContentA (val) {
if (this.contentA !== val) {
this.contentA = val
}
},
// load from url
fetch(url){
this.busy=true
HTTP.get("raw?url="+url,axios_json)
.then(r=>{
//console.log(r)
var a=acetype(r.data.mimetype)
this.mode=a
this.contentA=r.data.data
var a=url.split("/")
this.url=url
this.name=a.pop()
this.path=a
this.busy=false
//alert(mode)
})
.catch(error=> {
console.log(error);
this.busy=false
alert("Get query error"+url)
});
},
acecmd(cmd){
Events.$emit('eventFired',cmd);
},
fold(){
Events.$emit('eventFired',"foldall");
},
save(){
alert("TODO save: "+this.path.join("/"));
},
showfiles(){
router.push({ path: 'files', query: { url: this.path.join("/") }})
},
beautify(){
this.busy=true
var a=this.contentA
switch(this.mode) {
case "html":
case "xml":
a=html_beautify(a, { indent_size: 3 ,indent_inner_html:true})
break;
case "javascript":
a=js_beautify(a, { indent_size: 2 })
break;
case "css":
a=css_beautify(a, { indent_size: 2 })
break;
default:
alert("beaut: " + this.mode)
}
this.contentA=a
this.busy=false
},
annotation(counts){
this.annotations=counts
}
},
created:function(){
var url=this.$route.query.url
console.log("Edit: ",url)
if(url) this.fetch(url)
}
}
);
const Files=Vue.extend({
template: `
<v-container fluid="">
<v-card>
<v-toolbar class="green">
<v-menu offset-y="">
<v-btn primary="" icon="" dark="" slot="activator"><v-icon>folder</v-icon></v-btn>
<v-list>
<v-list-item v-for="item in items" :key="item">
<v-list-tile>
<v-list-tile-title @click="root()">{{ item }}</v-list-tile-title>
</v-list-tile>
</v-list-item>
</v-list>
</v-menu>
<v-toolbar-title>URL: <v-chip class="primary white--text" @click="root()">{{ url }}</v-chip></v-toolbar-title>
<v-spacer></v-spacer>
<v-icon class="mr-4">search</v-icon>
<v-icon>view_module</v-icon>
</v-toolbar>
<v-list two-line="" subheader="">
<v-subheader inset="">Folders</v-subheader>
<v-list-item v-for="item in folders" v-bind:key="item.name">
<v-list-tile avatar="">
<v-list-tile-avatar>
<v-icon v-bind:class="[item.iconClass]">{{ item.icon }}</v-icon>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title @dblclick="folder(item.name)">{{ item.name }}</v-list-tile-title>
<v-list-tile-sub-title>{{ item.subtitle }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon="" ripple="">
<v-icon class="grey--text text--lighten-1">info</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile>
</v-list-item>
<v-divider inset=""></v-divider>
<v-subheader inset="">Files</v-subheader>
<v-list-item v-for="item in files" v-bind:key="item.name">
<v-list-tile>
<v-list-tile-avatar>
<v-icon v-bind:class="[item.iconClass]">{{ item.icon }}</v-icon>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title @dblclick="click(item.name)">{{ item.name }}</v-list-tile-title>
<v-list-tile-sub-title>{{ item.subtitle }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon="" ripple="">
<v-icon class="grey--text text--lighten-1">info</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile>
</v-list-item>
</v-list>
</v-card>
</v-container>
`,
data: function(){
return {url: ".",
folders:[],
files:[],
items:["root"]
}
},
methods:{
click (val) {
// with query, resulting in /register?plan=private
router.push({ path: 'edit', query: { url: this.url+"/" +val }})
},
folder (val) {
this.url+="/"+ val
this.$router.push({ query: { url: this.url }})
this.load(this.url)
},
load(url){
HTTP.get("file?url="+url,axios_json)
.then(r=>{
console.log(r)
this.folders=r.data.folders
this.files=r.data.files
})
.catch(error=> {
console.log(error);
alert("Get query error"+url)
});
},
root(){
this.url="."
this.$router.push({ query: { url: this.url }})
this.load(this.url)
}
},
created:function(){
var url=this.$route.query.url
this.url=url?url:".";
console.log("files: ",this.$route.query.url)
this.load(this.url)
}
}
);
const Home=Vue.extend({
template: `
<v-row class="ma-5">
<v-col xs4="">
<v-card hover="" raised="">
<v-card-row height="200px" class="pa-5 green lighten-1">
<div class="display-1 white--text text-xs-center">VUE-POC</div>
v0.0.1
</v-card-row>
</v-card>
</v-col>
<v-col xs4="">
<p>This is a experiment in using <code>vue.js</code>.</p>
<ul>
<li><a href="https://vuetifyjs.com/" target="new">vuetifyjs</a></li>
<li><a href="https://github.com/monterail/vue-multiselect">vue-multiselect</a></li>
<li><a href="https://github.com/sagalbot/vue-select"><s>vue-select</s></a></li>
<li><a href="https://github.com/beautify-web/js-beautify">js-beautify</a></li>
</ul>
</v-col>
<v-btn floating="floating">
<v-icon>add</v-icon>
</v-btn>
<my-component>REPLACED</my-component>
</v-row>
`}
);
const Options=Vue.extend({
template: `
<v-row>
<v-col xs2="">
<v-card class="blue darken-4 white--text">
<v-card-row height="200px">
<v-card-title>
Featured Event: <br>
May 24, 2016 <br>
7-11pm
</v-card-title>
</v-card-row>
<v-card-row actions="">
<v-btn flat="" class="white--text" @click.native="snackbar = true">Add to <br>Calendar</v-btn>
<v-spacer></v-spacer>
<v-btn icon="" dark="" @click.native="snackbar = true">
<v-icon>event</v-icon>
</v-btn>
</v-card-row>
</v-card>
</v-col>
<v-col xs6="">
<v-text-field name="url" label="Image location" :required="true" :full-width="false"></v-text-field>
</v-col>
<v-col xs4="">
<v-card-row img="music.jpg" height="300px"></v-card-row>
<v-btn block="" primary="" @click.native="snackbar = true" dark="">Show Snackbar</v-btn>
<v-btn class="white--text" @click.native="snackbar = true">Snackbar?</v-btn>
</v-col>
<v-snackbar v-model="snackbar">
Hello, I'm a snackbar
<v-btn flat="" class="pink--text" @click.native="snackbar = false">
<v-icon>highlight_off</v-icon>
</v-btn>
</v-snackbar>
</v-row>
`,
data: function(){
return {
snackbar:false
}
}
}
);
const People=Vue.extend({
template: `
<v-container fluid="">
<v-row>Look at all the people who work here!
<v-btn light="" default="" v-on:click.native="reverseMessage">Reverse Message</v-btn>
<p>{{ message }}</p>
</v-row>
<v-row>
<v-col xs5="">
<v-card-row img="music.jpg" height="300px"></v-card-row>
</v-col>
<v-col xs5="">
<v-card-row img="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" height="300px"></v-card-row>
</v-col>
</v-row>
</v-container>
`,
data: function(){
return {message: 'Hello Vue.js!'}
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
}
);
const Search=Vue.extend({
template: `
<v-container fluid="">
<v-text-field label="Search..." v-model="q"></v-text-field>
</v-container>
`,
data: function(){
return {
message: 'Hello Vue.js!',
q:this.$route.query.q
}
},
created:function(){
console.log("Serch",this.$route.query.q)
}
}
);
const Select=Vue.extend({
template: `
<v-container fluid="">
<v-card>
<v-card-row class="green darken-1">
<v-card-title>
<span class="white--text">Selection</span>
</v-card-title>
</v-card-row>
<v-card-text>
<v-card-row>
<v-col xs6="">
<p>some text</p>
<multiselect v-model="value" :options="options" @search-change="asyncFind" :loading="isLoading" placeholder="select one"></multiselect>
<pre>{{$data.value }}</pre>
</v-col>
<v-col xs6="">
<p>multi select</p>
<multiselect v-model="value2" :options="options" multiple="" placeholder="Select many"></multiselect>
<pre>{{$data.value2 }}</pre>
</v-col>
</v-card-row>
</v-card-text>
<v-card>
</v-card></v-card></v-container>
`,
components: { multiselect: VueMultiselect.Multiselect},
data: function(){
return {
value: null,
value2: null,
options: [],
isLoading: false
}
},
created:function(){
this.asyncFind("")
},
methods: {
asyncFind: function(query){
this.isLoading = true
that=this;
HTTP.get("test-select?q="+query,axios_json)
.then(function(r){
that.isLoading = false
that.options=r.data.items;
})
.catch(function (error) {
console.log(error);
this.isLoading = false
alert("Get query error")
});
}
}
}
);
const Stepper=Vue.extend({
template: `
<v-container fluid="">
<v-stepper v-model="e6" vertical="">
<v-stepper-step step="1" v-bind:complete="e6 > 1">
Select an image location
<small>http or server file</small>
</v-stepper-step>
<v-stepper-content step="1">
<v-card class="grey lighten-1 z-depth-1 mb-5" height="200px">
url
</v-card>
<v-btn primary="" @click.native="e6 = 2">Continue</v-btn>
<v-btn flat="">Cancel</v-btn>
</v-stepper-content>
<v-stepper-step step="2" v-bind:complete="e6 > 2">Configure analytics for this app</v-stepper-step>
<v-stepper-content step="2">
<v-card class="grey lighten-1 z-depth-1 mb-5" height="200px">
<v-btn primary="" @click.native="e6 = 3">Continue</v-btn>
<v-btn flat="" @click.native="e6 -= 1">Back</v-btn>
</v-card></v-stepper-content>
<v-stepper-step step="3">Select an ad format and name ad unit</v-stepper-step>
<v-stepper-content step="3">
<v-card class="grey lighten-1 z-depth-1 mb-5" height="200px">
<v-btn primary="" @click.native="e6 = 4">Continue</v-btn>
<v-btn flat="" @click.native="e6 -= 1">Back</v-btn>
</v-card></v-stepper-content>
<v-stepper-step step="4">View setup instructions</v-stepper-step>
<v-stepper-content step="4">
<v-card class="grey lighten-1 z-depth-1 mb-5" height="200px">
<v-btn primary="" @click.native="e6 = 1">Continue</v-btn>
<v-btn flat="" @click.native="e6 -= 1">Back</v-btn>
</v-card></v-stepper-content>
</v-stepper>
</v-container>
`,
data: function(){
return {e6: 0}
}
}
);
// base -----------------------
const HTTP = axios.create({
baseURL: "/vue-poc/api/",
headers: {
'X-Custom-Header': 'vue-poc',
accept: 'application/json'
}
});
const axios_json={ headers: {accept: 'application/json'}};
function acetype(mime){
const mimemap={
"text/xml":"xml",
"application/xml":"xml",
"application/xquery":"xquery",
"text/ecmascript":"javascript",
"text/html":"html"
};
var r=mimemap[mime]
return r?r:"text"
};
Vue.component('my-component', {
template: '<div>A custom component!</div>',
created:function(){
console.log("my-component");
},
});
var Events = new Vue({});
const router = new VueRouter({
base:"/vue-poc/ui/",
mode: 'history',
routes: [
{ path: '/', component: Home },
{ path: '/people', component: People ,meta:{title:"People"}},
{ path: '/options', component: Options,meta:{title:"Options"} },
{ path: '/select', component: Select,meta:{title:"Select"} },
{ path: '/search', component: Search,meta:{title:"Search"} },
{ path: '/edit', component: Edit,meta:{title:"Ace editor"} },
{ path: '/stepper', component: Stepper,meta:{title:"Stepper"} },
{ path: '/files', component: Files,meta:{title:"Files"} }
],
});
router.afterEach(function(route) {
document.title = (route.meta.title?route.meta.title:"") + " VUE-Poc";
});
Vue.use(Vuetify);
const app = new Vue({
router,
data:function(){return {
q:"",
sidebar:false,
items: [{
href: '/',
router: true,
title: 'Home',
icon: 'home'
}, {
href: 'files',
router: true,
title: 'files',
icon: 'folder'
}, {
href: 'edit',
router: true,
title: 'edit',
icon: 'mode_edit'
}, {
href: 'search',
router: true,
title: 'search',
icon: 'search'
}, {
href: 'people',
router: true,
title: 'People',
icon: 'person'
}, {
href: 'select',
router: true,
title: 'select',
icon: 'extension'
}, {
href: 'options',
router: true,
title: 'options',
icon: 'domain'
}, {
href: 'stepper',
router: true,
title: 'stepper',
icon: 'picture_in_picture'
}]
}},
methods: {
openSidebar() {
this.sidebar = !this.sidebar;
},
search(){
this.$router.push({path: 'search',query: { q: this.q }})
}
}
}).$mount('#app');

View file

@ -0,0 +1,53 @@
/* app.css */
.fade-enter-active, .fade-leave-active {
transition-property: opacity;
transition-duration: .25s;
}
.fade-enter-active {
transition-delay: .25s;
}
.fade-enter, .fade-leave-active {
opacity: 0
}
.child-view {
position: absolute;
transition: all .5s cubic-bezier(.55,0,.1,1);
}
.slide-left-enter, .slide-right-leave-active {
opacity: 0;
-webkit-transform: translate(30px, 0);
transform: translate(30px, 0);
}
.slide-left-leave-active, .slide-right-enter {
opacity: 0;
-webkit-transform: translate(-30px, 0);
transform: translate(-30px, 0);
}
/*
.ace_editor { height: 200px; }
*/
.acewrap{
top:0px;
left:0px;
bottom:0px;
right:0px;
height:100%;
}
.ace_gutter-cell.ace_breakpoint{
border-radius: 20px 0px 0px 20px;
box-shadow: 0px 0px 1px 1px red inset;
}
.ace_editor_wrapper {
height: 100%
}
.ace_editor {
height: 100%;
}

View file

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Vue poc" />
<meta name="author" content="andy bunce." />
<title>Vue Router Test</title>
<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 href="https://unpkg.com/vuetify@0.11.1/dist/vuetify.min.css" rel="stylesheet" type="text/css">
<link href="https://unpkg.com/vue-multiselect@2.0.0-beta.14/dist/vue-multiselect.min.css" rel="stylesheet" type="text/css">
<link href="/vue-poc/ui/app.css" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="/vue-poc/ui/icon.png"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/2.5.3/vue-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.1/axios.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.4.0/qs.js"></script>
<script src="https://unpkg.com/vuetify@0.11.1/dist/vuetify.min.js"></script>
<script src="https://unpkg.com/vue-multiselect@2.0.0-beta.14"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ext-language_tools.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.6.12/beautify.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.6.12/beautify-css.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.6.12/beautify-html.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.js"></script>
<script src="/vue-poc/ui/vue-ace.js"></script>
</head>
<body>
<v-app id="app" top-toolbar left-fixed-sidebar sidebar-under-toolbar>
<v-toolbar class="blue" >
<v-toolbar-side-icon @click.native.stop="openSidebar()" ></v-toolbar-side-icon>
<v-toolbar-title class="hidden-sm-and-down">Vue PoC</v-toolbar-title>
<v-spacer></v-spacer>
<v-text-field prepend-icon="search" label="Search..." v-model="q"
hide-details single-line dark @keyup.native.enter="search"></v-text-field>
</v-toolbar>
<main>
<v-sidebar fixed class="white--text" v-model="sidebar">
<div class="px-3">
<h3 class="white--text mt-3">Sidebar</h3>
<p>This is just an example sidebar.</p>
</div>
<v-list>
<v-list-tile v-for="(item, i) in items" :href="item.href" :router="item.router" avatar key="i">
<v-list-tile-avatar>
<v-icon>{{item.icon}}</v-icon>
</v-list-tile-avatar>
<v-list-tile-content>
{{ item.title }}
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-sidebar>
<v-content class="pt-0">
<v-container fluid>
<transition name="fade" mode="out-in">
<router-view class="view ma-3"></router-view>
</transition>
</v-container>
</v-content>
</main>
</v-app>
<script src="/vue-poc/ui/app-gen.js"></script>
</body>
</html>

413
src/vue-poc/static/app.js Normal file
View file

@ -0,0 +1,413 @@
const Home = Vue.extend({ template: '#home'});
const Options = Vue.extend({
template: '#heart',
data: function(){
return {
snackbar:false
}
}
});
const Select = Vue.extend({
template: '#select',
components: { multiselect: VueMultiselect.Multiselect},
data: function(){
return {
value: null,
value2: null,
options: [],
isLoading: false
}
},
created:function(){
this.asyncFind("")
},
methods: {
asyncFind: function(query){
this.isLoading = true
that=this;
HTTP.get("test-select?q="+query,axios_json)
.then(function(r){
that.isLoading = false
that.options=r.data.items;
})
.catch(function (error) {
console.log(error);
this.isLoading = false
alert("Get query error")
});
}
}
});
const People = Vue.extend({
template: '#people',
data: function(){
return {message: 'Hello Vue.js!'}
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
});
const Search = Vue.extend({
template: '#search',
data: function(){
return {
message: 'Hello Vue.js!',
q:this.$route.query.q
}
},
created:function(){
console.log("Serch",this.$route.query.q)
}
});
const Edit=Vue.extend({
template: `
<v-container fluid="">
<v-toolbar class="green">
<v-toolbar-side-icon></v-toolbar-side-icon>
<v-toolbar-title>
<v-btn @click.native="showfiles()" small="" icon=""><v-icon>folder</v-icon></v-btn>
<span>{{ name }}</span> <v-chip small="" class="primary white--text">{{ mode }}</v-chip>
</v-toolbar-title>
<v-toolbar-items>
<v-btn dark="" icon="" @click.native="acecmd('outline')">
<v-icon>star</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="acecmd('goToPreviousError')">
<v-icon>navigate_before</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="acecmd('goToNextError')">
<v-icon>navigate_next</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="acecmd('foldall')">
<v-icon>vertical_align_center</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="acecmd('showSettingsMenu')">
<v-icon>settings</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="wrap=!wrap">
<v-icon>wrap_text</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="acecmd('showKeyboardShortcuts')">
<v-icon>keyboard</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="save()">
<v-icon>cloud_upload</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="beautify()">
<v-icon>format_align_center</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="d2 = true">
<v-icon>delete</v-icon>
</v-btn>
<v-menu bottom="" origin="top right" transition="v-scale-transition">
<v-btn dark="" icon="" slot="activator">
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/vue-poc.xqm')">load xquery</v-list-tile-title>
</v-list-tile>
</v-list-item>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/data/vue-poc/ch4d1.xml')">load xml</v-list-tile-title>
</v-list-tile>
</v-list-item>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/static/app.js')">load js</v-list-tile-title>
</v-list-tile>
</v-list-item>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/static/app.html')">load html</v-list-tile-title>
</v-list-tile>
</v-list-item>
</v-list>
</v-menu>
</v-toolbar-items>
</v-toolbar>
<v-progress-linear v-if="busy" v-bind:indeterminate="true"></v-progress-linear>
<v-dialog v-model="clearDialog">
<v-card>
<v-card-row>
<v-card-title>Clear?</v-card-title>
</v-card-row>
<v-card-row>
<v-card-text>clear text.</v-card-text>
</v-card-row>
<v-card-row actions="">
<v-btn class="green--text darken-1" flat="flat" @click.native="clearDialog = false">Cancel</v-btn>
<v-btn class="green--text darken-1" flat="flat" @click.native="reset()">Ok</v-btn>
</v-card-row>
</v-card>
</v-dialog>
<div v-if="!busy" style="height:70vh">
<vue-ace editor-id="editorA" :content="contentA" :mode="mode" :wrap="wrap" v-on:change-content="changeContentA" v-on:annotation="annotation"></vue-ace>
</div>
</v-container>
`,
data () {
return {
contentA: 'declare function local:query($q as xs:string)\n{\n<json type="object" >}',
mode:'xquery',
url:'',
name:'',
path:[],
wrap:false,
busy:false,
clearDialog:false,
annotations:null
}
},
methods: {
reset () {
this.contentA = 'reset content for Editor A'
},
changeContentA (val) {
if (this.contentA !== val) {
this.contentA = val
}
},
// load from url
fetch(url){
this.busy=true
HTTP.get("raw?url="+url,axios_json)
.then(r=>{
//console.log(r)
var a=acetype(r.data.mimetype)
this.mode=a
this.contentA=r.data.data
var a=url.split("/")
this.url=url
this.name=a.pop()
this.path=a
this.busy=false
//alert(mode)
})
.catch(error=> {
console.log(error);
this.busy=false
alert("Get query error"+url)
});
},
acecmd(cmd){
Events.$emit('eventFired',cmd);
},
fold(){
Events.$emit('eventFired',"foldall");
},
save(){
alert("TODO save: "+this.path.join("/"));
},
showfiles(){
router.push({ path: 'files', query: { url: this.path.join("/") }})
},
beautify(){
this.busy=true
var a=this.contentA
switch(this.mode) {
case "html":
case "xml":
a=html_beautify(a, { indent_size: 3 ,indent_inner_html:true})
break;
case "javascript":
a=js_beautify(a, { indent_size: 2 })
break;
case "css":
a=css_beautify(a, { indent_size: 2 })
break;
default:
alert("beaut: " + this.mode)
}
this.contentA=a
this.busy=false
},
annotation(counts){
this.annotations=counts
}
},
created:function(){
var url=this.$route.query.url
console.log("Edit: ",url)
if(url) this.fetch(url)
}
}
);
const Files = Vue.extend({
template: '#files',
data: function(){
return {url: ".",
folders:[],
files:[],
items:["root"]
}
},
methods:{
click (val) {
// with query, resulting in /register?plan=private
router.push({ path: 'edit', query: { url: this.url+"/" +val }})
},
folder (val) {
this.url+="/"+ val
this.$router.push({ query: { url: this.url }})
this.load(this.url)
},
load(url){
HTTP.get("file?url="+url,axios_json)
.then(r=>{
console.log(r)
this.folders=r.data.folders
this.files=r.data.files
})
.catch(error=> {
console.log(error);
alert("Get query error"+url)
});
},
root(){
this.url="."
this.$router.push({ query: { url: this.url }})
this.load(this.url)
}
},
created:function(){
var url=this.$route.query.url
this.url=url?url:".";
console.log("files: ",this.$route.query.url)
this.load(this.url)
}
});
const Stepper = Vue.extend({
template: '#stepper',
data: function(){
return {e6: 0}
}
});
// base -----------------------
const HTTP = axios.create({
baseURL: "/vue-poc/api/",
headers: {
'X-Custom-Header': 'vue-poc',
accept: 'application/json'
}
});
const axios_json={ headers: {accept: 'application/json'}};
function acetype(mime){
const mimemap={
"text/xml":"xml",
"application/xml":"xml",
"application/xquery":"xquery",
"text/ecmascript":"javascript",
"text/html":"html"
};
var r=mimemap[mime]
return r?r:"text"
};
Vue.component('my-component', {
template: '<div>A custom component!</div>',
created:function(){
console.log("my-component");
},
});
var Events = new Vue({});
const router = new VueRouter({
base:"/vue-poc/ui/",
mode: 'history',
routes: [
{ path: '/', component: Home },
{ path: '/people', component: People ,meta:{title:"People"}},
{ path: '/options', component: Options,meta:{title:"Options"} },
{ path: '/select', component: Select,meta:{title:"Select"} },
{ path: '/search', component: Search,meta:{title:"Search"} },
{ path: '/edit', component: Edit,meta:{title:"Ace editor"} },
{ path: '/stepper', component: Stepper,meta:{title:"Stepper"} },
{ path: '/files', component: Files,meta:{title:"Files"} }
],
});
router.afterEach(function(route) {
document.title = (route.meta.title?route.meta.title:"") + " VUE-Poc";
});
Vue.use(Vuetify);
const app = new Vue({
router,
data:function(){return {
q:"",
sidebar:false,
items: [{
href: '/',
router: true,
title: 'Home',
icon: 'home'
}, {
href: 'files',
router: true,
title: 'files',
icon: 'folder'
}, {
href: 'edit',
router: true,
title: 'edit',
icon: 'mode_edit'
}, {
href: 'search',
router: true,
title: 'search',
icon: 'search'
}, {
href: 'people',
router: true,
title: 'People',
icon: 'person'
}, {
href: 'select',
router: true,
title: 'select',
icon: 'extension'
}, {
href: 'options',
router: true,
title: 'options',
icon: 'domain'
}, {
href: 'stepper',
router: true,
title: 'stepper',
icon: 'picture_in_picture'
}]
}},
methods: {
openSidebar() {
this.sidebar = !this.sidebar;
},
search(){
this.$router.push({path: 'search',query: { q: this.q }})
}
}
}).$mount('#app');

109
src/vue-poc/static/core.js Normal file
View file

@ -0,0 +1,109 @@
// base -----------------------
const HTTP = axios.create({
baseURL: "/vue-poc/api/",
headers: {
'X-Custom-Header': 'vue-poc',
accept: 'application/json'
}
});
const axios_json={ headers: {accept: 'application/json'}};
function acetype(mime){
const mimemap={
"text/xml":"xml",
"application/xml":"xml",
"application/xquery":"xquery",
"text/ecmascript":"javascript",
"text/html":"html"
};
var r=mimemap[mime]
return r?r:"text"
};
Vue.component('my-component', {
template: '<div>A custom component!</div>',
created:function(){
console.log("my-component");
},
});
var Events = new Vue({});
const router = new VueRouter({
base:"/vue-poc/ui/",
mode: 'history',
routes: [
{ path: '/', component: Home },
{ path: '/people', component: People ,meta:{title:"People"}},
{ path: '/options', component: Options,meta:{title:"Options"} },
{ path: '/select', component: Select,meta:{title:"Select"} },
{ path: '/search', component: Search,meta:{title:"Search"} },
{ path: '/edit', component: Edit,meta:{title:"Ace editor"} },
{ path: '/stepper', component: Stepper,meta:{title:"Stepper"} },
{ path: '/files', component: Files,meta:{title:"Files"} }
],
});
router.afterEach(function(route) {
document.title = (route.meta.title?route.meta.title:"") + " VUE-Poc";
});
Vue.use(Vuetify);
const app = new Vue({
router,
data:function(){return {
q:"",
sidebar:false,
items: [{
href: '/',
router: true,
title: 'Home',
icon: 'home'
}, {
href: 'files',
router: true,
title: 'files',
icon: 'folder'
}, {
href: 'edit',
router: true,
title: 'edit',
icon: 'mode_edit'
}, {
href: 'search',
router: true,
title: 'search',
icon: 'search'
}, {
href: 'people',
router: true,
title: 'People',
icon: 'person'
}, {
href: 'select',
router: true,
title: 'select',
icon: 'extension'
}, {
href: 'options',
router: true,
title: 'options',
icon: 'domain'
}, {
href: 'stepper',
router: true,
title: 'stepper',
icon: 'picture_in_picture'
}]
}},
methods: {
openSidebar() {
this.sidebar = !this.sidebar;
},
search(){
this.$router.push({path: 'search',query: { q: this.q }})
}
}
}).$mount('#app');

BIN
src/vue-poc/static/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

View file

@ -0,0 +1,103 @@
// ace editor for vue.js
//https://jsfiddle.net/bc_rikko/gbpw2q9x/3/
Vue.component('vue-ace', {
template: '<div :id="editorId" style="width: 100%; height: 100%;"></div>',
props: ['editorId', 'content', 'mode', 'theme','wrap','readOnly'],
data () {
return {
editor: Object,
beforeContent: '',
annots:{error:0,warning:0,info:0}
}
},
watch: {
'content' (value) {
if (this.beforeContent !== value) {
this.editor.setValue(value, 1)
}
},
'mode' (value) {
var session=this.editor.getSession()
session.setMode(`ace/mode/${value}`)
},
'wrap' (value) {
var session=this.editor.getSession()
session.setUseWrapMode(value)
}
},
methods:{
command(cmd){
//alert("fold")
var cm = this.editor.commands
//console.log(cm.commands)
cm.exec(cmd, this.editor)
},
set(){
this.editor.getSession().setAnnotations([{
row: 1,
column: 0,
text: "Strange error",
type: "error" // also warning and information
}]);
}
},
mounted () {
const mode = this.mode || 'text'
const theme = this.theme || 'github'
const wrap = this.wrap || false
const readOnly = this.readOnly || false
ace.config.set("workerPath", "/vue-poc/ui/ace-workers")
this.editor = window.ace.edit(this.editorId)
this.editor.$blockScrolling = Infinity
this.editor.setValue(this.content, 1)
// mode-xxx.js or theme-xxx.jsがある場合のみ有効
var session=this.editor.getSession()
session.setMode(`ace/mode/${mode}`)
session.setUseWrapMode(wrap)
this.editor.setTheme(`ace/theme/${theme}`)
this.editor.setOptions({ readOnly:this.readOnly,
enableSnippets : true,
enableBasicAutocompletion : true,
enableLiveAutocompletion : true
});
this.editor.commands.addCommand({
name: "showKeyboardShortcuts",
bindKey: {win: "Ctrl-Alt-h", mac: "Command-Alt-h"},
exec: function(editor) {
ace.config.loadModule("ace/ext/keybinding_menu", function(module) {
module.init(editor);
editor.showKeyboardShortcuts()
})
}
})
this.editor.on('change', () => {
this.beforeContent = this.editor.getValue()
this.$emit('change-content', this.editor.getValue())
});
this.editor.getSession().on("changeAnnotation", ()=>{
var annot = this.editor.getSession().getAnnotations();
this.annots={error:0,warning:0,info:0};
for (var key in annot){
if (annot.hasOwnProperty(key)){
this.annots[annot[key].type]+=1;
//console.log("[" + annot[key].row + " , " + annot[key].column + "] - \t" + annot[key].type+ "# " +annot[key].text);
}
}
//console.log(this.annots)
this.$emit('annotation',this.annots)
});
Events.$on('eventFired', (cmd) => {
if(cmd=="outline"){
var row = this.editor.selection.getCursor().row
var toks=this.editor.session.getTokens(row).filter(function(t) {
return true
})
console.log(toks);
}else this.command(cmd);
});
}
})

View file

@ -0,0 +1,185 @@
<!DOCTYPE html>
<template id="edit">
<v-container fluid>
<v-toolbar class="green">
<v-toolbar-side-icon></v-toolbar-side-icon>
<v-toolbar-title>
<v-btn @click.native="showfiles()" small icon><v-icon>folder</v-icon></v-btn>
<span >{{ name }}</span> <v-chip small class="primary white--text">{{ mode }}</v-chip>
</v-toolbar-title>
<v-toolbar-items>
<v-btn dark icon @click.native="acecmd('outline')">
<v-icon>star</v-icon>
</v-btn>
<v-btn dark icon @click.native="acecmd('goToPreviousError')" >
<v-icon>navigate_before</v-icon>
</v-btn>
<v-btn dark icon @click.native="acecmd('goToNextError')">
<v-icon>navigate_next</v-icon>
</v-btn>
<v-btn dark icon @click.native="acecmd('foldall')">
<v-icon>vertical_align_center</v-icon>
</v-btn>
<v-btn dark icon @click.native="acecmd('showSettingsMenu')">
<v-icon>settings</v-icon>
</v-btn>
<v-btn dark icon @click.native="wrap=!wrap">
<v-icon>wrap_text</v-icon>
</v-btn>
<v-btn dark icon @click.native="acecmd('showKeyboardShortcuts')">
<v-icon>keyboard</v-icon>
</v-btn>
<v-btn dark icon @click.native="save()">
<v-icon>cloud_upload</v-icon>
</v-btn>
<v-btn dark icon @click.native="beautify()">
<v-icon>format_align_center</v-icon>
</v-btn>
<v-btn dark icon @click.native="d2 = true">
<v-icon>delete</v-icon>
</v-btn>
<v-menu bottom origin="top right" transition="v-scale-transition">
<v-btn dark icon slot="activator">
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/vue-poc.xqm')">load xquery</v-list-tile-title>
</v-list-tile>
</v-list-item>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/data/vue-poc/ch4d1.xml')">load xml</v-list-tile-title>
</v-list-tile>
</v-list-item>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/static/app.js')">load js</v-list-tile-title>
</v-list-tile>
</v-list-item>
<v-list-item>
<v-list-tile>
<v-list-tile-title @click="fetch('vue-poc/static/app.html')">load html</v-list-tile-title>
</v-list-tile>
</v-list-item>
</v-list>
</v-menu>
</v-toolbar-items>
</v-toolbar>
<v-progress-linear v-if="busy" v-bind:indeterminate="true" ></v-progress-linear>
<v-dialog v-model="clearDialog" >
<v-card>
<v-card-row>
<v-card-title>Clear?</v-card-title>
</v-card-row>
<v-card-row>
<v-card-text>clear text.</v-card-text>
</v-card-row>
<v-card-row actions>
<v-btn class="green--text darken-1" flat="flat" @click.native="clearDialog = false">Cancel</v-btn>
<v-btn class="green--text darken-1" flat="flat" @click.native="reset()">Ok</v-btn>
</v-card-row>
</v-card>
</v-dialog>
<div v-if="!busy" style="height:70vh">
<vue-ace editor-id="editorA" :content="contentA" :mode="mode" :wrap="wrap"
v-on:change-content="changeContentA"
v-on:annotation="annotation"></vue-ace>
</div>
</v-container>
</template>
<script>{
template: '#edit',
data () {
return {
contentA: 'declare function local:query($q as xs:string)\n{\n<json type="object" >}',
mode:'xquery',
url:'',
name:'',
path:[],
wrap:false,
busy:false,
clearDialog:false,
annotations:null
}
},
methods: {
reset () {
this.contentA = 'reset content for Editor A'
},
changeContentA (val) {
if (this.contentA !== val) {
this.contentA = val
}
},
// load from url
fetch(url){
this.busy=true
HTTP.get("raw?url="+url,axios_json)
.then(r=>{
//console.log(r)
var a=acetype(r.data.mimetype)
this.mode=a
this.contentA=r.data.data
var a=url.split("/")
this.url=url
this.name=a.pop()
this.path=a
this.busy=false
//alert(mode)
})
.catch(error=> {
console.log(error);
this.busy=false
alert("Get query error"+url)
});
},
acecmd(cmd){
Events.$emit('eventFired',cmd);
},
fold(){
Events.$emit('eventFired',"foldall");
},
save(){
alert("TODO save: "+this.path.join("/"));
},
showfiles(){
router.push({ path: 'files', query: { url: this.path.join("/") }})
},
beautify(){
this.busy=true
var a=this.contentA
switch(this.mode) {
case "html":
case "xml":
a=html_beautify(a, { indent_size: 3 ,indent_inner_html:true})
break;
case "javascript":
a=js_beautify(a, { indent_size: 2 })
break;
case "css":
a=css_beautify(a, { indent_size: 2 })
break;
default:
alert("beaut: " + this.mode)
}
this.contentA=a
this.busy=false
},
annotation(counts){
this.annotations=counts
}
},
created:function(){
var url=this.$route.query.url
console.log("Edit: ",url)
if(url) this.fetch(url)
}
}
</script>

View file

@ -0,0 +1,108 @@
<!DOCTYPE html>
<template id="files">
<v-container fluid>
<v-card>
<v-toolbar class="green">
<v-menu offset-y>
<v-btn primary icon dark slot="activator"><v-icon >folder</v-icon></v-btn>
<v-list>
<v-list-item v-for="item in items" :key="item">
<v-list-tile>
<v-list-tile-title @click="root()">{{ item }}</v-list-tile-title>
</v-list-tile>
</v-list-item>
</v-list>
</v-menu>
<v-toolbar-title>URL: <v-chip class="primary white--text" @click="root()">{{ url }}</v-chip></v-toolbar-title>
<v-spacer></v-spacer>
<v-icon class="mr-4">search</v-icon>
<v-icon>view_module</v-icon>
</v-toolbar>
<v-list two-line subheader>
<v-subheader inset>Folders</v-subheader>
<v-list-item v-for="item in folders" v-bind:key="item.name" >
<v-list-tile avatar>
<v-list-tile-avatar>
<v-icon v-bind:class="[item.iconClass]">{{ item.icon }}</v-icon>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title @dblclick="folder(item.name)">{{ item.name }}</v-list-tile-title>
<v-list-tile-sub-title>{{ item.subtitle }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon ripple>
<v-icon class="grey--text text--lighten-1">info</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile>
</v-list-item>
<v-divider inset></v-divider>
<v-subheader inset>Files</v-subheader>
<v-list-item v-for="item in files" v-bind:key="item.name">
<v-list-tile>
<v-list-tile-avatar>
<v-icon v-bind:class="[item.iconClass]">{{ item.icon }}</v-icon>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title @dblclick="click(item.name)">{{ item.name }}</v-list-tile-title>
<v-list-tile-sub-title>{{ item.subtitle }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon ripple>
<v-icon class="grey--text text--lighten-1">info</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile>
</v-list-item>
</v-list>
</v-card>
</v-container>
</template>
<script>{
template: '#files',
data: function(){
return {url: ".",
folders:[],
files:[],
items:["root"]
}
},
methods:{
click (val) {
// with query, resulting in /register?plan=private
router.push({ path: 'edit', query: { url: this.url+"/" +val }})
},
folder (val) {
this.url+="/"+ val
this.$router.push({ query: { url: this.url }})
this.load(this.url)
},
load(url){
HTTP.get("file?url="+url,axios_json)
.then(r=>{
console.log(r)
this.folders=r.data.folders
this.files=r.data.files
})
.catch(error=> {
console.log(error);
alert("Get query error"+url)
});
},
root(){
this.url="."
this.$router.push({ query: { url: this.url }})
this.load(this.url)
}
},
created:function(){
var url=this.$route.query.url
this.url=url?url:".";
console.log("files: ",this.$route.query.url)
this.load(this.url)
}
}
</script>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<template id="home">
<v-row class="ma-5">
<v-col xs4>
<v-card hover raised>
<v-card-row height="200px" class="pa-5 green lighten-1">
<div class="display-1 white--text text-xs-center">VUE-POC</div>
v0.0.1
</v-card-row>
</v-card>
</v-col>
<v-col xs4>
<p>This is a experiment in using <code>vue.js</code>.</p>
<ul>
<li><a href="https://vuetifyjs.com/" target="new">vuetifyjs</a></li>
<li><a href="https://github.com/monterail/vue-multiselect">vue-multiselect</a></li>
<li><a href="https://github.com/sagalbot/vue-select"><s>vue-select</s></a></li>
<li><a href="https://github.com/beautify-web/js-beautify">js-beautify</a></li>
</ul>
</v-col>
<v-btn floating="floating">
<v-icon>add</v-icon>
</v-btn>
<my-component>REPLACED</my-component>
</v-row>
</template>
<script>{
template: '#home'}
</script>

View file

@ -0,0 +1,52 @@
<!DOCTYPE html>
<template id="options">
<v-row >
<v-col xs2>
<v-card class="blue darken-4 white--text">
<v-card-row height="200px">
<v-card-title>
Featured Event: <br>
May 24, 2016 <br>
7-11pm
</v-card-title>
</v-card-row>
<v-card-row actions>
<v-btn flat class="white--text" @click.native="snackbar = true" >Add to <br>Calendar</v-btn>
<v-spacer></v-spacer>
<v-btn icon dark @click.native="snackbar = true" >
<v-icon>event</v-icon>
</v-btn>
</v-card-row>
</v-card>
</v-col>
<v-col xs6>
<v-text-field
name="url"
label="Image location" :required=true :full-width=false
></v-text-field>
</v-col>
<v-col xs4>
<v-card-row img="music.jpg" height="300px"></v-card-row>
<v-btn block primary @click.native="snackbar = true" dark>Show Snackbar</v-btn>
<v-btn class="white--text" @click.native="snackbar = true">Snackbar?</v-btn>
</v-col>
<v-snackbar v-model="snackbar">
Hello, I'm a snackbar
<v-btn flat class="pink--text" @click.native="snackbar = false">
<v-icon>highlight_off</v-icon>
</v-btn>
</v-snackbar>
</v-row>
</template>
<script>{
template: '#options',
data: function(){
return {
snackbar:false
}
}
}
</script>

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<template id="people">
<v-container fluid>
<v-row >Look at all the people who work here!
<v-btn light default v-on:click.native="reverseMessage">Reverse Message</v-btn>
<p>{{ message }}</p>
</v-row>
<v-row>
<v-col xs5>
<v-card-row img="music.jpg" height="300px"></v-card-row>
</v-col>
<v-col xs5>
<v-card-row img="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" height="300px"></v-card-row>
</v-col>
</v-row>
</v-container>
</template>
<script>{
template: '#people',
data: function(){
return {message: 'Hello Vue.js!'}
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
}
</script>

View file

@ -0,0 +1,19 @@
<template >
<div class="example">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style>
.example {
font-weight: bold;
}
</style>

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<template id="search">
<v-container fluid>
<v-text-field label="Search..." v-model="q"></v-text-field>
</v-container>
</template>
<script>{
template: '#search',
data: function(){
return {
message: 'Hello Vue.js!',
q:this.$route.query.q
}
},
created:function(){
console.log("Serch",this.$route.query.q)
}
}
</script>

View file

@ -0,0 +1,64 @@
<!DOCTYPE html>
<template id="select">
<v-container fluid>
<v-card>
<v-card-row class="green darken-1">
<v-card-title>
<span class="white--text">Selection</span>
</v-card-title>
</v-card-row>
<v-card-text>
<v-card-row>
<v-col xs6>
<p>some text</p>
<multiselect v-model="value" :options="options" @search-change="asyncFind" :loading="isLoading"
placeholder="select one"></multiselect>
<pre>{{$data.value }}</pre>
</v-col>
<v-col xs6 >
<p>multi select</p>
<multiselect v-model="value2" :options="options" multiple
placeholder="Select many"></multiselect>
<pre>{{$data.value2 }}</pre>
</v-col>
</v-card-row>
</v-card-text>
<v-card>
</v-container>
</template>
<script>{
template: '#select',
components: { multiselect: VueMultiselect.Multiselect},
data: function(){
return {
value: null,
value2: null,
options: [],
isLoading: false
}
},
created:function(){
this.asyncFind("")
},
methods: {
asyncFind: function(query){
this.isLoading = true
that=this;
HTTP.get("test-select?q="+query,axios_json)
.then(function(r){
that.isLoading = false
that.options=r.data.items;
})
.catch(function (error) {
console.log(error);
this.isLoading = false
alert("Get query error")
});
}
}
}
</script>

View file

@ -0,0 +1,44 @@
<!DOCTYPE html>
<template id="stepper">
<v-container fluid>
<v-stepper v-model="e6" vertical>
<v-stepper-step step="1" v-bind:complete="e6 > 1">
Select an image location
<small>http or server file</small>
</v-stepper-step>
<v-stepper-content step="1">
<v-card class="grey lighten-1 z-depth-1 mb-5" height="200px" >
url
</v-card>
<v-btn primary @click.native="e6 = 2">Continue</v-btn>
<v-btn flat>Cancel</v-btn>
</v-stepper-content>
<v-stepper-step step="2" v-bind:complete="e6 > 2">Configure analytics for this app</v-stepper-step>
<v-stepper-content step="2">
<v-card class="grey lighten-1 z-depth-1 mb-5" height="200px" />
<v-btn primary @click.native="e6 = 3">Continue</v-btn>
<v-btn flat @click.native="e6 -= 1">Back</v-btn>
</v-stepper-content>
<v-stepper-step step="3">Select an ad format and name ad unit</v-stepper-step>
<v-stepper-content step="3">
<v-card class="grey lighten-1 z-depth-1 mb-5" height="200px" />
<v-btn primary @click.native="e6 = 4">Continue</v-btn>
<v-btn flat @click.native="e6 -= 1">Back</v-btn>
</v-stepper-content>
<v-stepper-step step="4">View setup instructions</v-stepper-step>
<v-stepper-content step="4">
<v-card class="grey lighten-1 z-depth-1 mb-5" height="200px" />
<v-btn primary @click.native="e6 = 1">Continue</v-btn>
<v-btn flat @click.native="e6 -= 1">Back</v-btn>
</v-stepper-content>
</v-stepper>
</v-container>
</template>
<script>{
template: '#stepper',
data: function(){
return {e6: 0}
}
}
</script>

157
src/vue-poc/vue-api2.xqm Normal file
View file

@ -0,0 +1,157 @@
(:~
: vue-poc api.
:
: @author Andy Bunce may-2017
:)
module namespace vue-api = 'quodatum:vue.api';
import module namespace rest = "http://exquery.org/ns/restxq";
import module namespace fw="quodatum:file.walker";
declare namespace c="http://www.w3.org/ns/xproc-step";
declare namespace wadl="http://wadl.dev.java.net/2009/02";
declare namespace MediaType='java:org.basex.util.http.MediaType';
declare variable $vue-api:index:=file:base-dir() || 'static/' || "app.html";
(:~
: Returns a query result.
:)
declare
%rest:path("/vue-poc/api/test-select")
%rest:query-param("q", "{$q}")
%rest:produces("application/json")
%output:method("json")
function vue-api:test-select($q )
{
<json type="object" >
<items type="array">
{(1 to 100)!(<_>A{.}</_>)}
</items>
</json>
};
(:~
: Returns wadl.
:)
declare
%rest:path("/vue-poc/api")
function vue-api:wadl()
{
rest:wadl()
};
(:~
: Returns a file content.
:)
declare
%rest:path("/vue-poc/api/raw")
%rest:query-param("url", "{$url}")
%rest:produces("application/json")
%output:method("json")
function vue-api:raw($url as xs:string)
{
let $path := vue-api:web( $url)=>trace("path ")
return if( file:exists($path))then
let $type:=vue-api:type($path)
let $fetch:=vue-api:fetch-fn($type("treat-as"))
return <json type="object" >
<url>{$url}</url>
<mimetype>{$type?type}</mimetype>
<data>{$fetch($path)}</data>
</json>
else
error(xs:QName('vue-api:raw'),$path)
};
(:~
: Returns folder info.
:)
declare
%rest:path("/vue-poc/api/file")
%rest:query-param("url", "{$url}")
%rest:produces("application/json")
%output:method("json")
function vue-api:file($url as xs:string)
{
let $path := vue-api:web( $url)=>trace("path ")
return if( file:exists($path))then
let $items:=fw:directory-list($path,map{"max-depth":1,"include-info":true()})
return <json type="object" >
<folders type="array">
{for $f in $items/c:directory
order by $f/@name/lower-case(.)
return <_ type="object">
<name>{$f/@name/string()}</name>
<icon>folder</icon>
</_>
}
</folders>
<files type="array">
{for $f in $items/c:file
order by $f/@name/lower-case(.)
return <_ type="object">
<name>{$f/@name/string()}</name>
<icon>insert_drive_file</icon>
</_>
}
</files>
</json>
else
error(xs:QName('vue-api:raw'),$path)
};
(:~
: resolve path relative to basex webpath
: file("fred")=>C:\Program Files (x86)\BaseX\webapp\fred
:)
declare function vue-api:web($file)
as xs:string
{
file:resolve-path($file,db:system()/globaloptions/webpath/fn:concat(.,"/"))
};
(:~
: fetch function for given data type "text","xml","binary"
: @return function()
:)
declare function vue-api:fetch-fn($treat as xs:string)
as function(*)
{
switch ($treat)
case "text"
return fetch:text(?)
case "xml"
return fetch:text(?)
default
return fetch:binary(?)
};
(:~ classify file as binary/text/xml
:)
declare function vue-api:type($filepath as xs:string)
as map(*)
{
let $f:=vue-api:base-ext($filepath)
let $a:=MediaType:get($f)
let $type:= if(MediaType:isXML($a)) then
"xml"
else if(MediaType:isText($a) or MediaType:isXQuery($a))then
"text"
else
"binary"
return map{"type":MediaType:type($a) ,"treat-as":$type}
};
(:~ change file to have baseextension
:)
declare function vue-api:base-ext($filepath as xs:string)
{
let $ext:=replace ($filepath,'^.*\.','')
let $ext:=if(contains($filepath,"/"))then '' else $ext
let $types:=map{"vue":".html"}
return if($types($ext)) then $types($ext) else $filepath
};

53
src/vue-poc/vue-poc.xqm Normal file
View file

@ -0,0 +1,53 @@
(:~
: vue-poc application.
:
: @author Andy Bunce may-2017
:)
module namespace vue-poc = 'quodatum:vue.poc';
declare variable $vue-poc:index:=file:base-dir() || 'static/' || "app.html";
(:~
: Redirects to the start page.
:)
declare
%rest:path("/vue-poc")
function vue-poc:redirect()
as element(rest:response)
{
web:redirect("/vue-poc/ui")
};
(:~ display home page :)
declare
%rest:GET %rest:path("/vue-poc/ui")
function vue-poc:main()
{
vue-poc:get-file("app.html")
};
(:~
: Returns a file.
: @param $file file or unknown path
: @return rest response and binary file
:)
declare
%rest:path("/vue-poc/ui/{$file=.+}")
function vue-poc:file(
$file as xs:string
) as item()+
{
vue-poc:get-file($file)
};
declare function vue-poc:get-file($file)
{
let $path := file:base-dir() || 'static/' || $file
let $path:=if(file:exists($path))then $path else $vue-poc:index
return (
web:response-header(map { 'media-type': web:content-type($path) }),
file:read-binary($path)
)
};

44
tools/compile.xq Normal file
View file

@ -0,0 +1,44 @@
(:~
: create app.js from vue files
:)
import module namespace html5="text.html5" at "html5parse.xqm";
import module namespace fw="quodatum:file.walker";
declare namespace c="http://www.w3.org/ns/xproc-step";
declare namespace Document="java:ch.digitalfondue.jfiveparse.Document";
declare namespace Element="java:ch.digitalfondue.jfiveparse.Element";
declare namespace Node="java:ch.digitalfondue.jfiveparse.Node";
declare namespace list="java:java.util.ArrayList";
declare namespace functx = "http://www.functx.com";
declare variable $SRC:="C:/Users/andy/git/vue-poc/src/vue-poc/templates/";
declare variable $CORE:="C:/Users/andy/git/vue-poc/src/vue-poc/static/core.js";
declare variable $DEST:="C:/Users/andy/git/vue-poc/src/vue-poc/static/app-gen.js";
(:~
: generate javascript vue call from vue file
:)
declare function local:process($doc)
{
let $tempNode:= Document:getElementsByTagName($doc,"template")=>list:get(xs:int(0))
let $template:= Node:getInnerHTML($tempNode)
let $id:= Element:getAttribute($tempNode,"id")
let $name:=functx:capitalize-first($id)=>trace("ID")
let $script:= Document:getElementsByTagName($doc,"script")=>list:get(xs:int(0))
let $tempfix:=replace($template,"\$","\\\$")
let $s:= Node:getInnerHTML($script)=>replace('[''"]#' || $id || '[''"]','`' ||$tempfix ||'`')
let $js:= ``[const `{$name}`=Vue.extend(`{$s}`
);
]``
return if($id="") then () else $js
};
declare function functx:capitalize-first
( $arg as xs:string? ) as xs:string?
{
concat(upper-case(substring($arg,1,1)), substring($arg,2))
};
let $files:= fw:directory-list($SRC,map{"include-filter":".*\.vue"})
//c:file/@name/resolve-uri(.,base-uri(.))
let $docs:=$files!(fetch:text(.)=>html5:doc()=>local:process())
return file:write-text($DEST,string-join(($docs,fetch:text($CORE))))

30
tools/html5parse.xqm Normal file
View file

@ -0,0 +1,30 @@
module namespace html5="text.html5";
declare namespace Document="java:ch.digitalfondue.jfiveparse.Document";
declare namespace Element="java:ch.digitalfondue.jfiveparse.Element";
declare namespace Node="java:ch.digitalfondue.jfiveparse.Node";
declare namespace Parser="java:ch.digitalfondue.jfiveparse.Parser";
declare namespace Selector="java:ch.digitalfondue.jfiveparse.Selector";
declare namespace list="java:java.util.ArrayList";
declare function html5:doc($text as xs:string)
{
let $p:=Parser:new()
return Parser:parse($p,$text)
};
declare function html5:for-each($nodes,$fn as function(*))
{
for $index in 0 to list:size($nodes)-1
let $a:=list:get($nodes,xs:int($index))
return $fn($a)
};
declare function html5:selector()
{
Selector:select()
=>Selector:element("script")
=>Selector:attrValEq("type", "text/x-template")
=>Selector:toMatcher()
};

30
tools/split.xq Normal file
View file

@ -0,0 +1,30 @@
(:~
: create vue files from app.html
:)
import module namespace html5="text.html5" at "html5parse.xqm";
declare namespace Document="java:ch.digitalfondue.jfiveparse.Document";
declare namespace Element="java:ch.digitalfondue.jfiveparse.Element";
declare namespace Node="java:ch.digitalfondue.jfiveparse.Node";
declare variable $DEST:="C:/Users/andy/git/vue-poc/src/vue-poc/templates/";
declare variable $SRC:="C:/Users/andy/git/vue-poc/src/vue-poc/static/app.html";
declare function local:process($node)
{
let $id:= Element:getAttribute($node,"id")
let $html:=Node:getInnerHTML($node)
let $name:=$DEST || $id || ".vue"
let $out:=``[<!DOCTYPE html>
<template id="`{$id}`">`{$html}`</template>
<script>
</script>
]``
return file:write-text($name,$out)
};
let $doc:=$SRC=>fetch:text()=>html5:doc()
let $matcher:=html5:selector()
let $nodes:= Document:getAllNodesMatching($doc,$matcher)
return $nodes=>html5:for-each(local:process#1)