better edit

This commit is contained in:
Andy Bunce 2017-06-01 12:42:13 +01:00
parent f3aeff3c1c
commit ee22286a95
12 changed files with 475 additions and 124 deletions

View file

@ -1,8 +1,8 @@
<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">
abbrev="vue-poc" version="0.0.2" spec="1.0">
<title>vue-poc test of vue.js.</title>
<dependency name="ace" version="1.2.6" />
<dependency name="vuetify" version="0.12.0" />
<dependency name="vuetify" version="0.12.2" />
<dependency name="vue" version="2.3.3" />
<dependency name="vue-router" version="2.5.3" />
<dependency name="google-material" version="0.0.0" />
@ -10,5 +10,6 @@
<dependency name="axios" version="0.16.1" />
<dependency name="qs" version="6.4.0" />
<dependency name="vue-multiselect" version="2.0.0-beta.14" />
<dependency name="lodash" version="4.13.1" />
<dependency name="lodash" version="4.13.1" />
<dependency name="localforage" version="1.5.0" />
</package>

View file

@ -1,4 +1,5 @@
const Edit=Vue.extend({
// generated 2017-06-01T12:41:01.376+01:00
const Edit=Vue.extend({
template: `
<v-container fluid="">
<v-layout row="" wrap="">
@ -7,7 +8,7 @@ const Edit=Vue.extend({
<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>
{{dirty}}
</v-toolbar-title>
<v-toolbar-items>
<v-btn dark="" icon="" @click.native="acecmd('outline')">
@ -32,12 +33,12 @@ const Edit=Vue.extend({
<v-icon>keyboard</v-icon>
</v-btn>
<v-btn dark="" icon="" @click.native="save()">
<v-icon>cloud_upload</v-icon>
<v-icon>file_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-btn dark="" icon="" @click.native="clearDialog = true">
<v-icon>delete</v-icon>
</v-btn>
<v-menu bottom="" origin="top right" transition="v-scale-transition">
@ -48,22 +49,22 @@ const Edit=Vue.extend({
<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-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-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-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-title @click="fetch('/vue-poc/static/app.html')">load html</v-list-tile-title>
</v-list-tile>
</v-list-item>
</v-list>
@ -80,8 +81,8 @@ const Edit=Vue.extend({
<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-btn class="green--text darken-1" flat="flat" @click.native="reset(false)">Cancel</v-btn>
<v-btn class="green--text darken-1" flat="flat" @click.native="reset(true)">Ok</v-btn>
</v-card-row>
</v-card>
</v-dialog>
@ -105,16 +106,29 @@ const Edit=Vue.extend({
wrap:false,
busy:false,
clearDialog:false,
annotations:null
annotations:null,
dirty:false,
mimemap:{
"text/xml":"xml",
"application/xml":"xml",
"application/xquery":"xquery",
"text/ecmascript":"javascript",
"text/html":"html"
}
}
},
methods: {
reset () {
this.contentA = 'reset content for Editor A'
reset (ok) {
if(ok){
this.contentA = 'reset content for Editor A'
this.dirty=false
}
this.clearDialog=false
},
changeContentA (val) {
if (this.contentA !== val) {
this.contentA = val
this.dirty=true
}
},
// load from url
@ -123,20 +137,20 @@ const Edit=Vue.extend({
HTTP.get("raw?url="+url,axios_json)
.then(r=>{
//console.log(r)
var a=acetype(r.data.mimetype)
this.mode=a
this.mode=this.acetype(r.data.mimetype)
this.contentA=r.data.data
var a=url.split("/")
this.url=url
this.name=a.pop()
this.path=a
this.busy=false
this.dirty=false
//alert(mode)
})
.catch(error=> {
console.log(error);
this.busy=false
alert("Get query error"+url)
alert("Get query error:\n"+url)
});
},
@ -174,12 +188,31 @@ const Edit=Vue.extend({
},
annotation(counts){
this.annotations=counts
}
},
acetype(mime){
var r=this.mimemap[mime]
return r?r:"text"
},
leaving(event) {
event.returnValue = "event seems to need to be set";
//debugger;
console.log("Leaving...");
if(this.dirty)event.preventDefault();
}
},
created:function(){
created(){
//https://forum.vuejs.org/t/detect-browser-close/5001/3 @fixme
document.addEventListener('beforeunload', this.leaving);
var url=this.$route.query.url
console.log("Edit: ",url)
if(url) this.fetch(url)
},
beforeRouteLeave (to, from, next) {
// called when the route that renders this component is about to
// be navigated away from.
// has access to `this` component instance.
if(this.dirty && confirm("unsaved changes will be lost"))this.dirty=false;
next(!this.dirty);
}
}
@ -193,31 +226,32 @@ const Files=Vue.extend({
<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-item v-for="item in crumbs" :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-toolbar-title>{{ url }}</v-toolbar-title>
<v-spacer></v-spacer>
<v-icon class="mr-4">search</v-icon>
<v-text-field prepend-icon="search" label="Filter..." v-model="q" type="search" hide-details="" single-line="" dark="" @keyup.native.enter="filter"></v-text-field>
<v-icon>view_module</v-icon>
</v-toolbar>
<v-list two-line="" subheader="">
<v-progress-linear v-if="busy" v-bind:indeterminate="true"></v-progress-linear>
<v-list v-if="!busy" 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-list-tile-avatar @click="folder(item.name)">
<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 @click="folder(item.name)">
<v-list-tile-title>{{ item.name }}</v-list-tile-title>
<v-list-tile-sub-title>modified: {{ item.modified }} size: {{ item.size }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon="" ripple="">
<v-btn icon="" ripple="" @click.native="info(item.name)">
<v-icon class="grey--text text--lighten-1">info</v-icon>
</v-btn>
</v-list-tile-action>
@ -231,8 +265,8 @@ const Files=Vue.extend({
<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-title @click="file(item.name)">{{ item.name }}</v-list-tile-title>
<v-list-tile-sub-title>modified: {{ item.modified }} size: {{ item.size }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon="" ripple="">
@ -246,44 +280,67 @@ const Files=Vue.extend({
</v-container>
`,
data: function(){
return {url: ".",
return {
crumbs:[],
folders:[],
files:[],
items:["root"]
items:["root"],
q:"",
busy:false
}
},
methods:{
click (val) {
file (val) {
// with query, resulting in /register?plan=private
router.push({ path: 'edit', query: { url: this.url+"/" +val }})
router.push({ path: 'edit', query: { url: this.url+"/"+val }})
},
folder (val) {
this.url+="/"+ val
this.crumbs.push(val )
this.$router.push({ query: { url: this.url }})
this.load(this.url)
},
load(url){
this.busy=true
HTTP.get("file?url="+url,axios_json)
.then(r=>{
console.log(r)
this.folders=r.data.folders
this.files=r.data.files
this.busy=false
})
.catch(error=> {
console.log(error);
this.busy=false
alert("Get query error"+url)
});
},
root(){
this.url="."
this.crumbs=[]
this.$router.push({ query: { url: this.url }})
this.load(this.url)
},
filter(){
console.log("TODO")
},
info(){
alert("info")
}
},
computed: {
url: {
get: function () {
return '/'+ this.crumbs.join("/") ;
},
set: function(newValue){
// alert("set"+newValue)
this.crumbs=newValue.split("/").filter((a)=>a.length>0)
}
}
},
created:function(){
var url=this.$route.query.url
this.url=url?url:".";
this.url=url?url:"/";
console.log("files: ",this.$route.query.url)
this.load(this.url)
}
@ -318,6 +375,45 @@ const Home=Vue.extend({
</v-layout>
`}
);
const Login=Vue.extend({
template: `
<v-card class="grey lighten-4 elevation-0">
<v-card-row class="green darken-1">
<v-card-title>
<span class="white--text">Login</span>
</v-card-title>
</v-card-row>
<v-card-row>
<v-text-field name="input-name" label="Enter your name" hint="name??" v-model="name" required=""></v-text-field>
</v-card-row>
<v-card-row>
<v-text-field name="input-password" 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'" required=""></v-text-field>
</v-card-row>
<v-divider></v-divider>
<v-card-row actions="" class="blue-grey darken-1 mt-0">
<v-btn primary="" @click.native="go()">Continue</v-btn>
<v-spacer></v-spacer>
</v-card-row>
</v-card>
`,
data () {
return {
e1: true,
name:'',
password: ''
}
},
methods:{
go () {
alert("not yet")
}
}
}
);
const Options=Vue.extend({
template: `
@ -516,6 +612,49 @@ const Stepper=Vue.extend({
}
}
);
const Tabs=Vue.extend({
template: `
<v-tabs id="mobile-tabs-6" scroll-bars="" light="">
<v-card class="primary white--text">
<v-card-text>
<v-card-row>
<v-btn icon="" light="">
<v-icon>menu</v-icon>
</v-btn>
<v-card-title>Page Title</v-card-title>
<v-btn icon="" light="">
<v-icon>search</v-icon>
</v-btn>
<v-btn icon="" light="">
<v-icon>more_vert</v-icon>
</v-btn>
</v-card-row>
</v-card-text>
</v-card>
<v-tabs-bar slot="activators">
<v-tabs-slider></v-tabs-slider>
<v-tabs-item v-for="i in 13" :key="i" :href="'#mobile-tabs-6-' + i">
Item {{ i }}
<v-btn icon="" class="pink--text">
<v-icon>favorite</v-icon>
</v-btn>
</v-tabs-item>
</v-tabs-bar>
<v-tabs-content v-for="i in 13" :key="i" :id="'mobile-tabs-6-' + i">
<v-card flat="">
<v-card-text>{{ text }}</v-card-text>
</v-card>
</v-tabs-content>
</v-tabs>
`,
data () {
return {
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
}
}
}
);
// base -----------------------
const HTTP = axios.create({
@ -527,21 +666,14 @@ const HTTP = axios.create({
});
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.config.errorHandler = function (err, vm, info) {
// handle error
// `info` is a Vue-specific error info, e.g. which lifecycle hook
console.error(err, vm, info);
alert("vue error");
};
Vue.component('my-component', {
template: '<div>A custom component!</div>',
template: '<div>A custom <v-chip>component!</v-chip></div>',
created:function(){
console.log("my-component");
},
@ -559,6 +691,8 @@ const router = new VueRouter({
{ path: '/options', component: Options,meta:{title:"Options"} },
{ path: '/select', component: Select,meta:{title:"Select"} },
{ path: '/search', component: Search,meta:{title:"Search"} },
{ path: '/tabs', component: Tabs,meta:{title:"tab test"} },
{ 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"} }
@ -573,7 +707,9 @@ const app = new Vue({
router,
data:function(){return {
q:"",
user:{},
drawer:true,
title:"my title",
mini: false,
items: [{
href: '/',
@ -610,13 +746,23 @@ const app = new Vue({
router: true,
title: 'options',
icon: 'domain'
}, {
href: 'tabs',
router: true,
title: 'tabs',
icon: 'switch_camera'
}, {
href: 'login',
router: true,
title: 'login',
icon: 'account_balance'
}, {
href: 'stepper',
router: true,
title: 'stepper',
icon: 'picture_in_picture'
icon: 'touch_app'
}]
}},
methods: {

View file

@ -9,7 +9,7 @@
<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.12.0/dist/vuetify.min.css" rel="stylesheet" type="text/css">
<link href="https://unpkg.com/vuetify@0.12.2/dist/vuetify.min.css" rel="stylesheet" type="text/css">
<link href="https://unpkg.com/vue-multiselect@2.0.0-beta.15/dist/vue-multiselect.min.css" rel="stylesheet" type="text/css">
<link href="/vue-poc/ui/app.css" rel="stylesheet" type="text/css">
@ -19,7 +19,7 @@
<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.12.0/dist/vuetify.min.js"></script>
<script src="https://unpkg.com/vuetify@0.12.2/dist/vuetify.min.js"></script>
<script src="https://unpkg.com/vue-multiselect@2.0.0-beta.15/dist/vue-multiselect.min.js"></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>
@ -27,21 +27,21 @@
<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://cdnjs.cloudflare.com/ajax/libs/localforage/1.5.0/localforage.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" >
<v-navigation-drawer persistent light :mini-variant.sync="mini" v-model="drawer">
<v-navigation-drawer persistent light :mini-variant.sync="mini" v-model="drawer" class="grey lighten-4 pb-0">
<v-list class="pa-0">
<v-list-item>
<v-list-tile avatar tag="div">
<v-list-tile-avatar>
<img src="https://randomuser.me/api/portraits/men/85.jpg" />
<img src="/vue-poc/ui/quodatum.gif" />
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title>Random name</v-list-tile-title>
<v-list-tile-title>Vue PoC</v-list-tile-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon @click.native.stop="mini = !mini">
@ -69,9 +69,10 @@
</v-list-item>
</v-list>
</v-navigation-drawer>
<v-toolbar class="blue" >
<v-toolbar-side-icon @click.native.stop="drawer = !drawer" ></v-toolbar-side-icon>
<v-toolbar-title class="hidden-sm-and-down">Vue PoC</v-toolbar-title>
<v-toolbar-title class="hidden-sm-and-down">{{title}}</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>

View file

@ -8,21 +8,14 @@ const HTTP = axios.create({
});
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.config.errorHandler = function (err, vm, info) {
// handle error
// `info` is a Vue-specific error info, e.g. which lifecycle hook
console.error(err, vm, info);
alert("vue error");
};
Vue.component('my-component', {
template: '<div>A custom component!</div>',
template: '<div>A custom <v-chip>component!</v-chip></div>',
created:function(){
console.log("my-component");
},
@ -40,6 +33,8 @@ const router = new VueRouter({
{ path: '/options', component: Options,meta:{title:"Options"} },
{ path: '/select', component: Select,meta:{title:"Select"} },
{ path: '/search', component: Search,meta:{title:"Search"} },
{ path: '/tabs', component: Tabs,meta:{title:"tab test"} },
{ 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"} }
@ -54,7 +49,9 @@ const app = new Vue({
router,
data:function(){return {
q:"",
user:{},
drawer:true,
title:"my title",
mini: false,
items: [{
href: '/',
@ -91,13 +88,23 @@ const app = new Vue({
router: true,
title: 'options',
icon: 'domain'
}, {
href: 'tabs',
router: true,
title: 'tabs',
icon: 'switch_camera'
}, {
href: 'login',
router: true,
title: 'login',
icon: 'account_balance'
}, {
href: 'stepper',
router: true,
title: 'stepper',
icon: 'picture_in_picture'
icon: 'touch_app'
}]
}},
methods: {

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -7,7 +7,7 @@
<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>
{{dirty}}
</v-toolbar-title>
<v-toolbar-items>
<v-btn dark icon @click.native="acecmd('outline')">
@ -32,12 +32,12 @@
<v-icon>keyboard</v-icon>
</v-btn>
<v-btn dark icon @click.native="save()">
<v-icon>cloud_upload</v-icon>
<v-icon>file_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-btn dark icon @click.native="clearDialog = true">
<v-icon>delete</v-icon>
</v-btn>
<v-menu bottom origin="top right" transition="v-scale-transition">
@ -48,22 +48,22 @@
<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-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-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-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-title @click="fetch('/vue-poc/static/app.html')">load html</v-list-tile-title>
</v-list-tile>
</v-list-item>
</v-list>
@ -80,8 +80,8 @@
<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-btn class="green--text darken-1" flat="flat" @click.native="reset(false)">Cancel</v-btn>
<v-btn class="green--text darken-1" flat="flat" @click.native="reset(true)">Ok</v-btn>
</v-card-row>
</v-card>
</v-dialog>
@ -110,16 +110,29 @@ v-on:annotation="annotation"></vue-ace>
wrap:false,
busy:false,
clearDialog:false,
annotations:null
annotations:null,
dirty:false,
mimemap:{
"text/xml":"xml",
"application/xml":"xml",
"application/xquery":"xquery",
"text/ecmascript":"javascript",
"text/html":"html"
}
}
},
methods: {
reset () {
this.contentA = 'reset content for Editor A'
reset (ok) {
if(ok){
this.contentA = 'reset content for Editor A'
this.dirty=false
}
this.clearDialog=false
},
changeContentA (val) {
if (this.contentA !== val) {
this.contentA = val
this.dirty=true
}
},
// load from url
@ -128,20 +141,20 @@ v-on:annotation="annotation"></vue-ace>
HTTP.get("raw?url="+url,axios_json)
.then(r=>{
//console.log(r)
var a=acetype(r.data.mimetype)
this.mode=a
this.mode=this.acetype(r.data.mimetype)
this.contentA=r.data.data
var a=url.split("/")
this.url=url
this.name=a.pop()
this.path=a
this.busy=false
this.dirty=false
//alert(mode)
})
.catch(error=> {
console.log(error);
this.busy=false
alert("Get query error"+url)
alert("Get query error:\n"+url)
});
},
@ -179,12 +192,31 @@ v-on:annotation="annotation"></vue-ace>
},
annotation(counts){
this.annotations=counts
}
},
acetype(mime){
var r=this.mimemap[mime]
return r?r:"text"
},
leaving(event) {
event.returnValue = "event seems to need to be set";
//debugger;
console.log("Leaving...");
if(this.dirty)event.preventDefault();
}
},
created:function(){
created(){
//https://forum.vuejs.org/t/detect-browser-close/5001/3 @fixme
document.addEventListener('beforeunload', this.leaving);
var url=this.$route.query.url
console.log("Edit: ",url)
if(url) this.fetch(url)
},
beforeRouteLeave (to, from, next) {
// called when the route that renders this component is about to
// be navigated away from.
// has access to `this` component instance.
if(this.dirty && confirm("unsaved changes will be lost"))this.dirty=false;
next(!this.dirty);
}
}
</script>

View file

@ -7,31 +7,33 @@
<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-item v-for="item in crumbs" :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-toolbar-title>{{ url }}</v-toolbar-title>
<v-spacer></v-spacer>
<v-icon class="mr-4">search</v-icon>
<v-text-field prepend-icon="search" label="Filter..." v-model="q" type="search"
hide-details single-line dark @keyup.native.enter="filter"></v-text-field>
<v-icon>view_module</v-icon>
</v-toolbar>
<v-list two-line subheader>
<v-progress-linear v-if="busy" v-bind:indeterminate="true" ></v-progress-linear>
<v-list v-if="!busy" 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-list-tile avatar >
<v-list-tile-avatar @click="folder(item.name)">
<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 @click="folder(item.name)">
<v-list-tile-title>{{ item.name }}</v-list-tile-title>
<v-list-tile-sub-title>modified: {{ item.modified }} size: {{ item.size }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon ripple>
<v-btn icon ripple @click.native="info(item.name)">
<v-icon class="grey--text text--lighten-1">info</v-icon>
</v-btn>
</v-list-tile-action>
@ -45,8 +47,8 @@
<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-title @click="file(item.name)">{{ item.name }}</v-list-tile-title>
<v-list-tile-sub-title>modified: {{ item.modified }} size: {{ item.size }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon ripple>
@ -63,44 +65,67 @@
<script>{
template: '#files',
data: function(){
return {url: ".",
return {
crumbs:[],
folders:[],
files:[],
items:["root"]
items:["root"],
q:"",
busy:false
}
},
methods:{
click (val) {
file (val) {
// with query, resulting in /register?plan=private
router.push({ path: 'edit', query: { url: this.url+"/" +val }})
router.push({ path: 'edit', query: { url: this.url+"/"+val }})
},
folder (val) {
this.url+="/"+ val
this.crumbs.push(val )
this.$router.push({ query: { url: this.url }})
this.load(this.url)
},
load(url){
this.busy=true
HTTP.get("file?url="+url,axios_json)
.then(r=>{
console.log(r)
this.folders=r.data.folders
this.files=r.data.files
this.busy=false
})
.catch(error=> {
console.log(error);
this.busy=false
alert("Get query error"+url)
});
},
root(){
this.url="."
this.crumbs=[]
this.$router.push({ query: { url: this.url }})
this.load(this.url)
},
filter(){
console.log("TODO")
},
info(){
alert("info")
}
},
computed: {
url: {
get: function () {
return '/'+ this.crumbs.join("/") ;
},
set: function(newValue){
// alert("set"+newValue)
this.crumbs=newValue.split("/").filter((a)=>a.length>0)
}
}
},
created:function(){
var url=this.$route.query.url
this.url=url?url:".";
this.url=url?url:"/";
console.log("files: ",this.$route.query.url)
this.load(this.url)
}

View file

@ -0,0 +1,56 @@
<!DOCTYPE html>
<template id="login">
<v-card class="grey lighten-4 elevation-0">
<v-card-row class="green darken-1">
<v-card-title>
<span class="white--text">Login</span>
</v-card-title>
</v-card-row>
<v-card-row>
<v-text-field
name="input-name"
label="Enter your name"
hint="name??"
v-model="name"
required
></v-text-field>
</v-card-row>
<v-card-row>
<v-text-field
name="input-password"
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'"
required
></v-text-field>
</v-card-row>
<v-divider></v-divider>
<v-card-row actions class="blue-grey darken-1 mt-0">
<v-btn primary @click.native="go()">Continue</v-btn>
<v-spacer></v-spacer>
</v-card-row>
</v-card>
</template>
<script>{
template: '#login',
data () {
return {
e1: true,
name:'',
password: ''
}
},
methods:{
go () {
alert("not yet")
}
}
}
</script>

View file

@ -0,0 +1,53 @@
<!DOCTYPE html>
<template id="tabs">
<v-tabs id="mobile-tabs-6" scroll-bars light>
<v-card class="primary white--text">
<v-card-text>
<v-card-row>
<v-btn icon light>
<v-icon>menu</v-icon>
</v-btn>
<v-card-title>Page Title</v-card-title>
<v-btn icon light>
<v-icon>search</v-icon>
</v-btn>
<v-btn icon light>
<v-icon>more_vert</v-icon>
</v-btn>
</v-card-row>
</v-card-text>
</v-card>
<v-tabs-bar slot="activators">
<v-tabs-slider></v-tabs-slider>
<v-tabs-item
v-for="i in 13"
:key="i"
:href="'#mobile-tabs-6-' + i"
>
Item {{ i }}
<v-btn icon class="pink--text">
<v-icon>favorite</v-icon>
</v-btn>
</v-tabs-item>
</v-tabs-bar>
<v-tabs-content
v-for="i in 13"
:key="i"
:id="'mobile-tabs-6-' + i"
>
<v-card flat>
<v-card-text>{{ text }}</v-card-text>
</v-card>
</v-tabs-content>
</v-tabs>
</template>
<script>{
template: '#tabs',
data () {
return {
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
}
}
}
</script>

View file

@ -73,7 +73,7 @@ declare
%output:method("json")
function vue-api:file($url as xs:string)
{
let $path := vue-api:web( $url)=>trace("path ")
let $path := vue-api:web( $url)=>trace("vue-api:web ")
return if( file:exists($path))then
@ -86,6 +86,8 @@ function vue-api:file($url as xs:string)
return <_ type="object">
<name>{$f/@name/string()}</name>
<icon>folder</icon>
<modified>{$f/@last-modified/string()}</modified>
<size type="number">{$f/@size/string()}</size>
</_>
}
</folders>
@ -95,6 +97,8 @@ function vue-api:file($url as xs:string)
return <_ type="object">
<name>{$f/@name/string()}</name>
<icon>insert_drive_file</icon>
<modified>{$f/@last-modified/string()}</modified>
<size type="number">{$f/@size/string()}</size>
</_>
}
</files>
@ -105,12 +109,18 @@ function vue-api:file($url as xs:string)
(:~
: resolve path relative to basex webpath
: file("fred")=>C:\Program Files (x86)\BaseX\webapp\fred
: file("/fred")=>C:\Program Files (x86)\BaseX\webapp\fred
:)
declare function vue-api:web($file)
declare function vue-api:web($file as xs:string)
as xs:string
{
file:resolve-path($file,db:system()/globaloptions/webpath/fn:concat(.,"/"))
let $file:=if(starts-with($file,"/")) then
substring($file,2)
else
error(xs:QName('vue-api:badpath'),"leading slash")
let $webroot:=db:system()/globaloptions/webpath/concat(.,"/")
return file:resolve-path($file,$webroot)
};
(:~

View file

@ -7,23 +7,23 @@ 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
: generate javascript vue call from vue files in source folder and core.js
:)
declare function local:process($doc)
{
let $tempNode:= Document:getElementsByTagName($doc,"template")=>list:get(xs:int(0))
let $tempNode:= html5:getElementFirstByTagName($doc,"template")
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 $script:= html5:getElementFirstByTagName($doc,"script")
let $tempfix:=replace($template,"\$","\\\$")
let $s:= Node:getInnerHTML($script)=>replace('[''"]#' || $id || '[''"]','`' ||$tempfix ||'`')
@ -38,7 +38,9 @@ declare function functx:capitalize-first
{
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(.))
//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))))
let $comment:="// generated " || current-dateTime() || "&#xA;&#xD;"
return file:write-text($DEST,string-join(($comment,$docs,fetch:text($CORE))))

View file

@ -1,3 +1,5 @@
module namespace html5="text.html5";
declare namespace Document="java:ch.digitalfondue.jfiveparse.Document";
declare namespace Element="java:ch.digitalfondue.jfiveparse.Element";
@ -6,14 +8,18 @@ declare namespace Parser="java:ch.digitalfondue.jfiveparse.Parser";
declare namespace Selector="java:ch.digitalfondue.jfiveparse.Selector";
declare namespace list="java:java.util.ArrayList";
(:~
: parse html text string into jfiveparse.Document
:)
declare function html5:doc($text as xs:string)
{
let $p:=Parser:new()
return Parser:parse($p,$text)
};
(:~
: apply function $fn to each jfiveparse.Node
:)
declare function html5:for-each($nodes,$fn as function(*))
{
for $index in 0 to list:size($nodes)-1
@ -21,6 +27,18 @@ declare function html5:for-each($nodes,$fn as function(*))
return $fn($a)
};
(:~
: first element with given name
:)
declare function html5:getElementFirstByTagName($doc,$tag as xs:string)
{
Document:getElementsByTagName($doc,$tag)
=>list:get(xs:int(0))
};
(:~
: @return matcher for given element and attribute with value
:)
declare function html5:selector()
{
Selector:select()