vuetify 1.0.4

This commit is contained in:
Andy Bunce 2018-03-04 21:40:33 +00:00
parent 37a81d74cd
commit b7604ddcfa
34 changed files with 997 additions and 145 deletions

View file

@ -50,6 +50,22 @@ function vue-api:search($q )
return dice:response($items,$entity,web:dice()) return dice:response($items,$entity,web:dice())
}; };
(:~
: Returns data results
:)
declare
%rest:path("/vue-poc/api/data/{$entity}")
%rest:query-param("q", "{$q}")
%rest:produces("application/json")
%output:method("json")
function vue-api:data($entity as xs:string,$q )
{
let $entity:=$entity:list($entity)
let $items:=$entity("data")()
return dice:response($items,$entity,web:dice())
};
(:~ (:~
: Returns test list for select. : Returns test list for select.
:) :)

View file

@ -34,7 +34,7 @@
</v-list-tile> </v-list-tile>
</v-list> </v-list>
<qd-navlist :items="items"></qd-navlist> <qd-navlist :items="items" :mini="mini"></qd-navlist>
</v-navigation-drawer> </v-navigation-drawer>
<v-toolbar class="indigo" app dark > <v-toolbar class="indigo" app dark >
@ -43,19 +43,7 @@
<vp-favorite :frmfav.sync="frmfav"></vp-favorite> <vp-favorite :frmfav.sync="frmfav"></vp-favorite>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-select <qd-search></qd-search>
placeholder="Search..." prepend-icon="search"
autocomplete
:loading="loading"
combobox
clearable
cache-items
:items="items2"
@keyup.enter="goSearch"
:search-input.sync="si"
v-model="q"
></v-select>
<v-spacer></v-spacer> <v-spacer></v-spacer>
@ -75,13 +63,25 @@
</v-list> </v-list>
</v-menu> </v-menu>
<qd-fullscreen></qd-fullscreen>
<v-btn @click.stop="showNotifications = ! showNotifications" icon flat title="Notifications"> <v-btn @click.stop="showNotifications = ! showNotifications" icon flat title="Notifications">
<v-badge overlap color="orange"> <v-badge overlap color="orange">
<span slot="badge" v-if=" $notification.unseen" >{{ $notification.unseen }}</span> <span slot="badge" v-if=" $notification.unseen" >{{ $notification.unseen }}</span>
<v-icon>notifications</v-icon> <v-icon>notifications</v-icon>
</v-badge> </v-badge>
</v-btn> </v-btn>
<v-menu bottom left min-width="300px">
<v-btn icon slot="activator" dark>
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<v-list-tile >
<v-list-tile-title><qd-fullscreen></qd-fullscreen> Full screen</v-list-tile-title>
</v-list-tile>
<v-list-tile >
<v-list-tile-title><v-switch label="Dark theme" v-model="dark"></v-switch></v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</v-toolbar> </v-toolbar>
<v-content> <v-content>
@ -99,8 +99,7 @@
<script>{ <script>{
router, router,
data:function(){return { data:function(){return {
q: "",
loading: false,
searchItems:[], searchItems:[],
si: '', si: '',
items2:["todo","set","search"], items2:["todo","set","search"],
@ -132,6 +131,7 @@
children: [ children: [
{href: '/database', text: 'Databases',icon: 'developer_mode' }, {href: '/database', text: 'Databases',icon: 'developer_mode' },
{href: '/files', text: 'File system',icon: 'folder' }, {href: '/files', text: 'File system',icon: 'folder' },
{href: '/history',text: 'history',icon: 'history'} {href: '/history',text: 'history',icon: 'history'}
]}, ]},
{ {
@ -139,6 +139,7 @@
text: 'Models' , text: 'Models' ,
model: false, model: false,
children: [ children: [
{href: '/documentation', text: 'Documentation',icon: 'library_books' },
{href: '/namespace', text: 'Namespaces',icon: 'label' }, {href: '/namespace', text: 'Namespaces',icon: 'label' },
{href: '/entity', text: 'Entities',icon: 'redeem' }, {href: '/entity', text: 'Entities',icon: 'redeem' },
]}, ]},
@ -177,6 +178,7 @@
{href: '/puzzle',text: 'Puzzle',icon: 'extension'}, {href: '/puzzle',text: 'Puzzle',icon: 'extension'},
{href: '/svg',text: 'SVG',icon: 'extension'}, {href: '/svg',text: 'SVG',icon: 'extension'},
{href: '/form',text: 'Forms',icon: 'format_list_bulleted' }, {href: '/form',text: 'Forms',icon: 'format_list_bulleted' },
{href: '/form2',text: 'Forms 2',icon: 'format_list_bulleted' },
{href: '/tabs',text: 'Tabs',icon: 'switch_camera'} {href: '/tabs',text: 'Tabs',icon: 'switch_camera'}
]}, ]},
@ -186,21 +188,12 @@
}}, }},
methods: { methods: {
querySelections (v) {
this.loading = true
// Simulated ajax query
setTimeout(() => {
this.items2 = ["aa","bb",this.si],
this.loading = false
}, 500)
},
session(){ session(){
this.$router.push({path: '/session'}) this.$router.push({path: '/session'})
}, },
goSearch(){
this.$router.push({path: '/search',query: { q: this.q }})
},
logout(){ logout(){
HTTP.get("logout").then(r=>{ HTTP.get("logout").then(r=>{
alert("logout") alert("logout")
@ -219,13 +212,7 @@
console.log("showNotifications",val); console.log("showNotifications",val);
if(!val)this.$notification.unseen=0; if(!val)this.$notification.unseen=0;
}, },
search (val) {
val && this.querySelections(val)
},
si:function(val){
console.log("si: ",val);
this.querySelections();
}
}, },
created(){ created(){

View file

@ -16,7 +16,7 @@ for nav drawer
</v-list-tile-content> </v-list-tile-content>
</v-list-tile> </v-list-tile>
<v-list-tile v-for="subItem in item.children" v-bind:key="subItem.text" <v-list-tile v-if="!mini" v-for="subItem in item.children" v-bind:key="subItem.text"
:prepend-icon="subItem.icon" :prepend-icon="subItem.icon"
:to="subItem.href" avatar ripple > :to="subItem.href" avatar ripple >
<v-list-tile-avatar> <v-list-tile-avatar>
@ -42,6 +42,6 @@ for nav drawer
</template> </template>
<script>{ <script>{
props: ['items'] props: ['items','mini']
} }
</script> </script>

View file

@ -0,0 +1,49 @@
<!DOCTYPE html>
<!--
search
-->
<template id="qd-search">
<v-select
placeholder="Search..." prepend-icon="search"
autocomplete
:loading="loading"
combobox
clearable
cache-items
:items="items2"
@keyup.enter="goSearch"
:search-input.sync="si"
v-model="q"
></v-select>
</template>
<script>{
data:function(){return {
q: "",
loading: false,
searchItems:[],
si: '',
items2:["todo","set","search"]
}
},
methods: {
querySelections (v) {
this.loading = true
// Simulated ajax query
setTimeout(() => {
this.items2 = ["aa","bb",this.si],
this.loading = false
}, 500)
},
goSearch(){
this.$router.push({path: '/search',query: { q: this.q }})
},
},
watch: {
si:function(val){
console.log("si: ",val);
this.querySelections();
}
}
}</script>

View file

@ -23,7 +23,7 @@
class="elevation-1" class="elevation-1"
no-data-text="No users found @todo" no-data-text="No users found @todo"
> >
<template slot="items" scope="props"> <template slot="items" slot-scope="props">
<slot></slot> <slot></slot>
</template> </template>
</v-data-table> </v-data-table>

View file

@ -3,16 +3,15 @@
display button that invokes a save favorite form display button that invokes a save favorite form
--> -->
<template id="vp-favorite"> <template id="vp-favorite">
<v-menu <v-menu :close-on-click="false"
offset-x offset-x
:close-on-content-click="false" :close-on-content-click="false"
:nudge-width="200" :nudge-width="200"
v-model="frmfav" v-model="frmfav"
> >
<v-btn slot="activator" @click="set(!frmfav)" icon flat title="Bookmark this page"> <v-btn slot="activator" @click.stop="set(!frmfav)" icon flat title="Bookmark this page">
<v-icon>star_border</v-icon> <v-icon>star_border</v-icon>
</v-btn> </v-btn>
<v-card style="width:400px;"> <v-card style="width:400px;">
<v-toolbar class="green"> <v-toolbar class="green">
<v-card-title> <v-card-title>

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<!--
Files picker
-->
<template id="vp-filepicker">
<v-layout>
<v-flex>
<slot name="body"></slot>
</v-flex>
<v-flex v-if="show" xs4 grey lighten-3>
<slot name="aside"></slot>
</v-flex>
</v-layout>
</template>
<script>{
props: ['show'],
created:function(){
console.log("vp-filepicker");
}
}
</script>

View file

@ -26,7 +26,7 @@
<v-list-tile-sub-title v-html="msg.text"></v-list-tile-sub-title> <v-list-tile-sub-title v-html="msg.text"></v-list-tile-sub-title>
</v-list-tile-content> </v-list-tile-content>
<v-list-tile-action> <v-list-tile-action>
<v-list-tile-action-text>{{ msg.index }}</v-list-tile-action-text> <v-list-tile-action-text>#{{ msg.index }}</v-list-tile-action-text>
</v-list-tile-action> </v-list-tile-action>
</v-list-tile> </v-list-tile>
</template> </template>

View file

@ -100,6 +100,16 @@ localforage.config({
// https://vuejs.org/v2/guide/state-management.html // https://vuejs.org/v2/guide/state-management.html
var settings = { var settings = {
debug: false, debug: false,
defaults:{
"settings/ace": {
theme: "github",
keybinding: "ace",
fontsize: 16,
enableSnippets:true,
enableBasicAutocompletion:true,
enableLiveAutocompletion:true
},
},
getItem (key) { getItem (key) {
if (this.debug) console.log('getItem',key); if (this.debug) console.log('getItem',key);
return localforage.getItem(key) return localforage.getItem(key)
@ -209,6 +219,9 @@ Vue.use(Fullscreen);
//Vue.component('v-map', Vue2Leaflet.Map); //Vue.component('v-map', Vue2Leaflet.Map);
//Vue.component('v-tilelayer', Vue2Leaflet.TileLayer); //Vue.component('v-tilelayer', Vue2Leaflet.TileLayer);
//Vue.component('v-marker', Vue2Leaflet.Marker); //Vue.component('v-marker', Vue2Leaflet.Marker);
//function install (Vue) {
// Vue.component('form-schema', window["vue-json-schema"].default);
//};
//Vue.use({ install: install });
Vue.use(Vuetify); Vue.use(Vuetify);
new Vuepoc().$mount('#app') new Vuepoc().$mount('#app')

View file

@ -29,7 +29,7 @@
no-data-text="No logs found" no-data-text="No logs found"
v-bind:pagination.sync="pagination" v-bind:pagination.sync="pagination"
> >
<template slot="items" scope="props"> <template slot="items" slot-scope="props">
<td class="text-xs-right">{{ props.item.time }}</td> <td class="text-xs-right">{{ props.item.time }}</td>
<td class="text-xs-right">{{ props.item.user }}</td> <td class="text-xs-right">{{ props.item.user }}</td>
<td class="text-xs-right">{{ props.item.type }}</td> <td class="text-xs-right">{{ props.item.type }}</td>

View file

@ -2,6 +2,7 @@
<template id="brutusin"> <template id="brutusin">
<v-container fluid> <v-container fluid>
<v-card> <v-card>
<v-card-title>vue-form-generator</v-card-title>
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator> <vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
</v-card> </v-card>
</v-container> </v-container>

View file

@ -26,12 +26,25 @@ function vue-api:history( )
return dice:response($items,$entity,web:dice()) return dice:response($items,$entity,web:dice())
}; };
(:~
: xqdoc list
:)
declare
%rest:GET %rest:path("/vue-poc/api/xqdoc")
%rest:produces("application/json")
%output:method("json")
function vue-api:xqdoc( )
{
let $entity:=$entity:list("xqdoc")
let $items:= $entity("data")()
return dice:response($items,$entity,web:dice())
};
(:~ (:~
: Returns folder info. : Returns folder info.
:) :)
declare declare
%rest:path("/vue-poc/api/collection") %rest:GET %rest:path("/vue-poc/api/collection")
%rest:query-param("url", "{$url}") %rest:query-param("url", "{$url}")
%rest:query-param("protocol", "{$protocol}","webfile") %rest:query-param("protocol", "{$protocol}","webfile")
%rest:produces("application/json") %rest:produces("application/json")

View file

@ -124,7 +124,7 @@
</v-card> </v-card>
<v-progress-linear v-if="busy" v-bind:indeterminate="true" height="2"></v-progress-linear> <v-progress-linear v-if="busy" v-bind:indeterminate="true" height="2"></v-progress-linear>
<v-navigation-drawer left absolute v-model="showInfo" :disable-route-watcher="true"> <v-navigation-drawer left app v-model="showInfo" :disable-route-watcher="true">
<v-card flat tile> <v-card flat tile>
<v-toolbar > <v-toolbar >
<v-card-title >{{ selection[0] && selection[0].name }}</v-card-title> <v-card-title >{{ selection[0] && selection[0].name }}</v-card-title>

View file

@ -0,0 +1,67 @@
<!DOCTYPE html>
<template id="formsjson">
<v-container fluid>
<v-card>
<v-card-title>vue-json-schema@1.1.0 https://github.com/formschema/native</v-card-title>
<form-schema ref="formSchema" :schema="schema" v-model="model" >
<v-btn color="success" @click.stop="submit">Subscribe</v-btn>
</form-schema>
</v-card>
</v-container>
</template>
<script>{
components: {
"form-schema": window["vue-json-schema"].default
},
data: () => ({
schema: {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"title": "Newsletter Subscription",
"properties": {
"name": {
"type": "string",
"minLength": 8,
"maxLength": 80,
"attrs": {
"placeholder": "Full Name",
"title": "Please enter your full name"
}
},
"email": {
"type": "string",
"maxLength": 120,
"attrs": {
"type": "email",
"placeholder": "Email"
}
},
"lists": {
"type": "string",
"enum": ["Daily New", "Promotion"]
},
"arrayInput": {
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false,
"required": ["name", "email", "lists"]
},
model: {}
}),
methods: {
submit (e) {
// this.model contains the valid data according your JSON Schema.
// You can submit your model to the server here
console.log(this.model);
alert("hi")
}
}
}
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -37,7 +37,7 @@
class="elevation-1" class="elevation-1"
no-data-text="No Jobs currently running" no-data-text="No Jobs currently running"
> >
<template slot="items" scope="props"> <template slot="items" slot-scope="props">
<td class="vtop"> <td class="vtop">
<v-checkbox <v-checkbox
primary primary

View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<template id="documentation">
<v-container fluid>
<v-list>
<v-list-tile v-for="item in items" v-bind:key="item.title" @click="doEdit(item)" avatar>
<v-list-tile-action>
<v-chip v-text="item.protocol">Example Chip</v-chip>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title @click="doEdit(item)" v-text="item.url"></v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-container>
</template>
<script>{
data: function(){
return {
message: 'Hello Vue.js!',
items:[]
}
},
methods:{
get() {
HTTP.get('xqdoc')
.then((res) => {
this.items = res.data.items;
console.log("items",this.items)
});
},
doEdit(item){
console.log("history: ",item)
router.push({ path: 'edit', query: { url:item.url, protocol:item.protocol }})
}
},
created:function(){
this.get()
console.log("history")
}
}
</script>

View file

@ -8,6 +8,7 @@
:loading="loading" :loading="loading"
:disabled="loading" :disabled="loading"
>Refresh</v-btn> >Refresh</v-btn>
Text
</v-toolbar> </v-toolbar>
<v-container fluid grid-list-md> <v-container fluid grid-list-md>
@ -16,6 +17,7 @@
content-tag="v-layout" content-tag="v-layout"
row row
wrap wrap
:loading="loading"
:items="items" :items="items"
:rows-per-page-items="rowsPerPageItems" :rows-per-page-items="rowsPerPageItems"
:pagination.sync="pagination" :pagination.sync="pagination"
@ -30,25 +32,24 @@
md4 md4
lg3 lg3
> >
<v-card> <v-card hover="true" active-class="default-class qd-active" >
<v-card-title>
<router-link :to="{path:'entity/'+ props.item.name}">
<h4>
<v-icon>{{ props.item.iconclass }}</v-icon> {{ props.item.name }}
</h4>
</router-link>
</v-card-title>
<v-toolbar color="amber">
<v-card-title >
<router-link :to="{path:'entity/'+ props.item.name}">
<h3>
<v-icon>{{ props.item.iconclass }}</v-icon> {{ props.item.name }}
</h3>
</router-link>
</v-card-title>
</v-toolbar>
<v-card-text>{{ props.item.description }}</<v-card-text> <v-card-text>{{ props.item.description }}</<v-card-text>
<v-card-actions> <v-card-text>
<v-list dense> <v-badge color="red">
<v-list-tile> <span slot="badge">{{ props.item.nfields }}</span>
<v-list-tile-content>Fields:</v-list-tile-content> Fields
<v-list-tile-content class="align-end">{{ props.item.nfields }}</v-list-tile-content> </v-badge>
</v-list-tile> </v-card-text>
</v-list>
</v-card-actions>
</v-card> </v-card>
</v-flex> </v-flex>
</v-data-iterator> </v-data-iterator>

View file

@ -1,18 +1,89 @@
<!DOCTYPE html> <!DOCTYPE html>
<template id="namespace"> <template id="namespace">
<v-container fluid> <v-container fluid grid-list-md>
namespaces <v-toolbar >
<v-toolbar-title>Namespaces</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn @click="load"
:loading="loading"
:disabled="loading"
>Refresh</v-btn>
Text
</v-toolbar>
<v-data-iterator
content-tag="v-layout"
row
wrap
:loading="loading"
:items="items"
:rows-per-page-items="rowsPerPageItems"
:pagination.sync="pagination"
select-all
:value="selected"
>
<v-flex
slot="item"
slot-scope="props"
xs12
sm6
md4
lg3
>
<v-card hover="true" active-class="default-class qd-active" height="200px">
<v-toolbar color="amber">
<v-card-title >
<router-link :to="{path:'entity/'+ props.item.name}">
<h3>
<v-icon>star</v-icon> {{ props.item.xmlns }}
</h3>
</router-link>
</v-card-title>
</v-toolbar>
<v-card-text>{{ props.item.description }}</<v-card-text>
<v-card-text>
<v-badge color="red">
<span slot="badge">{{ props.item.prefix }}</span>
Fields
</v-badge>
</v-card-text>
</v-card>
</v-flex>
</v-data-iterator>
</v-container> </v-container>
</template> </template>
<script>{ <script>{
data: function(){ data: function(){
return { return {
items: [],
loading: false,
q: "",
message: 'bad route!' message: 'bad route!'
} }
}, },
methods: {
load(){
this.loading= true
HTTP.get("data/namespace",{params:{}})
.then(r=>{
this.items= r.data.items
this.q= null
this.loading= false
})
.catch(error=> {
console.log(error);
this.loading= false
alert("Get query error"+url)
});
},
},
created:function(){ created:function(){
console.log("notfound",this.$route.query.q) this.q=this.$route.query.q || this.q;
this.load();
console.log("namespaces")
} }
} }
</script> </script>

View file

@ -9,7 +9,7 @@
</v-toolbar> </v-toolbar>
<v-card-text> <v-card-text>
<p>Read or increment a database value. This measures round trip times browser-database-browser.</p> <p>Read or increment a database value. This measures round trip times browser-database-browser.</p>
<p>Counter:{{counter}}</p> <h3>Counter: <v-chip color="amber" text-color="white">{{counter}}</v-chip></h3>
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>

View file

@ -21,7 +21,7 @@
class="elevation-1" class="elevation-1"
no-data-text="No repo found @todo" no-data-text="No repo found @todo"
> >
<template slot="items" scope="props"> <template slot="items" slot-scope="props">
<td class="vtop"> <td class="vtop">
<v-checkbox <v-checkbox
primary primary

View file

@ -12,7 +12,7 @@
item-value="suburb" item-value="suburb"
@selected="handleSelected" @selected="handleSelected"
strict="Unknown"> strict="Unknown">
<template slot="item" scope="data"> <template slot="item" slot-scope="data">
<v-list-tile-content> <v-list-tile-content>
<v-list-tile-title>{{data.item.suburb}}</v-list-tile-title> <v-list-tile-title>{{data.item.suburb}}</v-list-tile-title>
<template v-if="!data.item.generatedItem"> <template v-if="!data.item.generatedItem">

View file

@ -0,0 +1,188 @@
<!DOCTYPE html>
<template id="svg2">
<v-container fluid>
<!-- UI controls that can are used to manipulate the display of the chart -->
<div class="controls">
<div>
<label>Chart width</label>
<input type="range" v-model="settings.width" min="0" max="1000" />
</div>
<div>
<label>Stroke color</label>
<input type="color" v-model="settings.strokeColor" />
</div>
<div>
<label>Search…</label>
<input type="text" v-model="search" />
</div>
<button v-on:click="add">Add node</button>
<div>
Selected: {{ selected }}
</div>
</div>
<!-- SVG that renders the chart based on the "width" and "height" setting from the Vue instances data object -->
<svg v-bind:width="settings.width" v-bind:height="settings.height">
<!-- In contrast to D3s "select" methods, we define the graphical elements explicitely here and use the template syntax to loop through collections and bind properties such as "d" or "r" to those elements. -->
<transition-group tag="g" name="line" >
<!-- Links are represented as paths -->
<path v-for="link in links" class="link" v-bind:key="link.id" v-bind:d="link.d" v-bind:style="link.style"></path>
</transition-group>
<!-- We can now also use events to elements that will call respective methods on the Vue instance -->
<transition-group tag="g" name="list">
<g class="node" v-on:click="select(index, node)" v-for="(node, index) in nodes" v-bind:key="node.id" v-bind:style="node.style" v-bind:class="[node.className, {'highlight': node.highlight}]">
<!-- Circles for each node -->
<circle v-bind:r="node.r" v-bind:style="{'fill': index == selected ? '#ff0000' : '#bfbfbf'}"></circle>
<!-- Finally, text labels -->
<text v-bind:dx="node.textpos.x" v-bind:dy="node.textpos.y" v-bind:style="node.textStyle">{{ node.text }}</text>
</g>
</transition-group>
</svg>
</v-container>
</template>
<script>{
data: function() {
return {
csv: null,
selected: null,
search: "force",
settings: {
strokeColor: "#19B5FF",
width: 960,
height: 2000
}
};
},
mounted: function() {
var that = this;
d3.csv("flare.csv",
function(error, data) {
if (error) throw error;
// Load the CSV data
// After the CSV has been loaded, the computed properties will automatically re-compute (root, tree, and then nodes & links…)
that.csv = data;
}
);
},
computed: {
// once we have the CSV loaded, the "root" will be calculated
root: function() {
var that = this;
if (this.csv) {
var stratify = d3.stratify().parentId(function(d) {
return d.id.substring(0, d.id.lastIndexOf("."));
});
// attach the tree to the Vue data object
return this.tree(
stratify(that.csv).sort(function(a, b) {
return a.height - b.height || a.id.localeCompare(b.id);
})
);
}
},
// the "tree" is also a computed property so that it is always up to date when the width and height settings change
tree: function() {
return d3
.cluster()
.size([this.settings.height, this.settings.width - 160]);
},
// Instead of enter, update, exit, we mainly use computed properties and instead of "d3.data()" we can use array.map to create objects that hold class names, styles, and other attributes for each datum
nodes: function() {
var that = this;
if (this.root) {
return this.root.descendants().map(function(d) {
return {
id: d.id,
r: 2.5,
className: "node" +
(d.children ? " node--internal" : " node--leaf"),
text: d.id.substring(d.id.lastIndexOf(".") + 1),
highlight: d.id.toLowerCase().indexOf(that.search.toLowerCase()) != -1 && that.search != "",
style: {
transform: "translate(" + d.y + "px," + d.x + "px)"
},
textpos: {
x: d.children ? -8 : 8,
y: 3
},
textStyle: {
textAnchor: d.children ? "end" : "start"
}
};
});
}
},
// Instead of enter, update, exit, we mainly use computed properties and instead of "d3.data()" we can use array.map to create objects that hold class names, styles, and other attributes for each datum
links: function() {
var that = this;
if (this.root) {
// here well calculate the "d" attribute for each path that is then used in the template where we use "v-for" to loop through all of the links to create <path> elements
return this.root.descendants().slice(1).map(function(d) {
return {
id: d.id,
d: "M" + d.y + "," + d.x + "C" + (d.parent.y + 100) + "," + d.x + " " + (d.parent.y + 100) + "," + d.parent.x + " " + d.parent.y + "," + d.parent.x,
// here we could of course calculate colors depending on data but for now all links share the same color from the settings object that we can manipulate using UI controls and v-model
style: {
stroke: that.settings.strokeColor
}
};
});
}
}
},
methods: {
add: function () {
this.csv.push({
id: "flare.physics.Dummy",
value: 0
})
},
select: function(index, node) {
this.selected = index;
}
}
}
</script>

View file

@ -16,6 +16,11 @@
<description>Generate XQdoc as html</description> <description>Generate XQdoc as html</description>
</task> </task>
<task name="tasks/xqdoc">
<title>XQdoc to db</title>
<description>Generate XQdoc to save</description>
</task>
<task name="tasks/vuecompile"> <task name="tasks/vuecompile">
<title>vue compile</title> <title>vue compile</title>
</task> </task>

View file

@ -19,13 +19,13 @@ function tx:xslt($xml,$xslt) {
let $result:=try{ let $result:=try{
let $x:=fn:parse-xml($xml) let $x:=fn:parse-xml($xml)
let $s:=fn:parse-xml($xslt) let $s:=fn:parse-xml($xslt)
let $t:=fn:trace($xml,"xml") let $params:=map{}
let $t:=fn:trace($xslt,"xml") let $opts:=map{"cache":true()}
let $r:=xslt:transform($x,$s) let $r:=xslt:transform-text($x,$s,$params,$opts)
return return
<json objects="json"> <json objects="json">
<rc>0</rc> <rc>0</rc>
<result>{fn:serialize($r)}</result> <result>{$r}</result>
</json> </json>
} }
catch *{ catch *{

View file

@ -1,5 +1,5 @@
(: entity access maps (: entity access maps
: auto generated from xml files in entities folder at: 2018-02-12T09:42:15.78Z : auto generated from xml files in entities folder at: 2018-03-01T21:54:58.72Z
:) :)
module namespace entity = 'quodatum.models.generated'; module namespace entity = 'quodatum.models.generated';
@ -248,7 +248,7 @@ declare variable $entity:list:=map {
} }, } },
"data": function() as element(namespace)* "data": function() as element(namespace)*
{ collection("vuepoc")/namespaces/namespace { collection("vue-poc")/namespaces/namespace
}, },
"views": map{ "views": map{
@ -437,6 +437,34 @@ declare variable $entity:list:=map {
"views": map{ "views": map{
'filter': 'name' 'filter': 'name'
}
},
"xqdoc": map{
"name": "xqdoc",
"description": "XQuery documentation set ",
"access": map{
"root": function($_ as element()) as xs:string {$_/@root },
"time": function($_ as element()) as xs:string {$_/@time } },
"filter": function($item,$q) as xs:boolean{
some $e in ( ) satisfies
fn:contains($e,$q, 'http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive')
},
"json": map{
"root": function($_ as element()) as element(root)? {
(: xs:string :)
fn:data($_/@root)!element root { .}
},
"time": function($_ as element()) as element(time)? {
(: xs:string :)
fn:data($_/@time)!element time { .}
} },
"data": function() as element(entry)*
{ () },
"views": map{
} }
} }
}; };

View file

@ -19,6 +19,6 @@
<view name="filter">xmlns description</view> <view name="filter">xmlns description</view>
</views> </views>
<iconclass>label</iconclass> <iconclass>label</iconclass>
<data type="element(namespace)">collection("vuepoc")/namespaces/namespace <data type="element(namespace)">collection("vue-poc")/namespaces/namespace
</data> </data>
</entity> </entity>

View file

@ -0,0 +1,18 @@
<entity name="xqdoc" xmlns="https://github.com/Quodatum/app-doc/entity">
<description>XQuery documentation set </description>
<fields>
<field name="time" type="xs:string">
<description>time of generation</description>
<xpath>@time</xpath>
</field>
<field name="root" type="xs:string">
<description>root folder to scan</description>
<xpath>@root</xpath>
</field>
</fields>
<views>
</views>
<iconclass>fa fa-calendar</iconclass>
<data type="element(entry)">()</data>
</entity>

View file

@ -26,6 +26,7 @@ const router = new VueRouter({
{ path: '/images/dates', component: Dates, meta:{title:"Image dates"} }, { path: '/images/dates', component: Dates, meta:{title:"Image dates"} },
{ path: '/images/people', component: People, meta:{title:"Image people"} }, { path: '/images/people', component: People, meta:{title:"Image people"} },
{ path: '/documentation', component: Documentation, meta:{title:"documentation"} },
{ path: '/entity', component: Entity, meta:{title:"Entities"} }, { path: '/entity', component: Entity, meta:{title:"Entities"} },
{ path: '/namespace', component: Namespace, meta:{title:"Namespaces"} }, { path: '/namespace', component: Namespace, meta:{title:"Namespaces"} },
{ path: '/select', component: Select, meta:{title:"Select"} }, { path: '/select', component: Select, meta:{title:"Select"} },
@ -43,6 +44,7 @@ const router = new VueRouter({
{ path: '/history', component: History, meta:{title:"File History"} }, { path: '/history', component: History, meta:{title:"File History"} },
{ path: '/puzzle', component: Puzzle, meta:{title:"Jigsaw"} }, { path: '/puzzle', component: Puzzle, meta:{title:"Jigsaw"} },
{ path: '/svg', component: Svg, meta:{title:"SVG"} }, { path: '/svg', component: Svg, meta:{title:"SVG"} },
/* { path: '/svg2', component: Svg2, meta:{title:"SVG2"} }, */
{ path: '/transform', component: Transform, meta:{title:"XSLT2 Transform"} }, { path: '/transform', component: Transform, meta:{title:"XSLT2 Transform"} },
{ path: '/validate', component: Validate, meta:{title:"Validate"} }, { path: '/validate', component: Validate, meta:{title:"Validate"} },
{ path: '/eval', component: Eval, meta:{title:"Evaluate XQuery"} }, { path: '/eval', component: Eval, meta:{title:"Evaluate XQuery"} },
@ -56,7 +58,8 @@ const router = new VueRouter({
{ path: '/jobs/:job', name:"jobShow", component: Job, props: true, meta:{title:"Job Status"} }, { path: '/jobs/:job', name:"jobShow", component: Job, props: true, meta:{title:"Job Status"} },
{ path: '/timeline', component: Timeline,meta:{title:"timeline"} }, { path: '/timeline', component: Timeline,meta:{title:"timeline"} },
{ path: '/map', component: Map,meta:{title:"map"} }, { path: '/map', component: Map,meta:{title:"map"} },
{ path: '/form', component: Brutusin,meta:{title:"Form demo"} }, { path: '/form', component: Brutusin, meta:{title:"Form demo"} },
{ path: '/form2', component: Formsjson, meta:{title:"Form schema"} },
{ path: '/about', component: About,meta:{title:"About Vue-poc"} }, { path: '/about', component: About,meta:{title:"About Vue-poc"} },
{ path: '*', component: Notfound,meta:{title:"Page not found"} } { path: '*', component: Notfound,meta:{title:"Page not found"} }
], ],

View file

@ -1,4 +1,4 @@
// generated 2018-02-15T22:49:15.318Z // generated 2018-03-04T18:03:42.736Z
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/qd-confirm.vue // src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/qd-confirm.vue
Vue.component('qd-confirm',{template:` Vue.component('qd-confirm',{template:`
@ -72,7 +72,7 @@ Vue.component('qd-navlist',{template:`
</v-list-tile-content> </v-list-tile-content>
</v-list-tile> </v-list-tile>
<v-list-tile v-for="subItem in item.children" v-bind:key="subItem.text" :prepend-icon="subItem.icon" :to="subItem.href" avatar="" ripple=""> <v-list-tile v-if="!mini" v-for="subItem in item.children" v-bind:key="subItem.text" :prepend-icon="subItem.icon" :to="subItem.href" avatar="" ripple="">
<v-list-tile-avatar> <v-list-tile-avatar>
<v-icon>{{ subItem.icon }}</v-icon> <v-icon>{{ subItem.icon }}</v-icon>
</v-list-tile-avatar> </v-list-tile-avatar>
@ -95,7 +95,7 @@ Vue.component('qd-navlist',{template:`
</v-list> </v-list>
`, `,
props: ['items'] props: ['items','mini']
} }
); );
@ -121,6 +121,42 @@ Vue.component('qd-panel',{template:`
); );
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/qd-search.vue
Vue.component('qd-search',{template:`
<v-select placeholder="Search..." prepend-icon="search" autocomplete="" :loading="loading" combobox="" clearable="" cache-items="" :items="items2" @keyup.enter="goSearch" :search-input.sync="si" v-model="q"></v-select>
`,
data:function(){return {
q: "",
loading: false,
searchItems:[],
si: '',
items2:["todo","set","search"]
}
},
methods: {
querySelections (v) {
this.loading = true
// Simulated ajax query
setTimeout(() => {
this.items2 = ["aa","bb",this.si],
this.loading = false
}, 500)
},
goSearch(){
this.$router.push({path: '/search',query: { q: this.q }})
},
},
watch: {
si:function(val){
console.log("si: ",val);
this.querySelections();
}
}
}
);
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/qd-table.vue // src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/qd-table.vue
Vue.component('qd-table',{template:` Vue.component('qd-table',{template:`
<v-container fluid=""> <v-container fluid="">
@ -131,7 +167,7 @@ Vue.component('qd-table',{template:`
<v-btn @click="getData">Refresh</v-btn> <v-btn @click="getData">Refresh</v-btn>
</v-toolbar> </v-toolbar>
<v-data-table :headers="headers" :items="items" :search="search" v-model="selected" select-all="" class="elevation-1" no-data-text="No users found @todo"> <v-data-table :headers="headers" :items="items" :search="search" v-model="selected" select-all="" class="elevation-1" no-data-text="No users found @todo">
<template slot="items" scope="props"> <template slot="items" slot-scope="props">
<slot></slot> <slot></slot>
</template> </template>
</v-data-table> </v-data-table>
@ -212,11 +248,10 @@ Vue.component('vis-time-line',{template:`
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/vp-favorite.vue // src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/vp-favorite.vue
Vue.component('vp-favorite',{template:` Vue.component('vp-favorite',{template:`
<v-menu offset-x="" :close-on-content-click="false" :nudge-width="200" v-model="frmfav"> <v-menu :close-on-click="false" offset-x="" :close-on-content-click="false" :nudge-width="200" v-model="frmfav">
<v-btn slot="activator" @click="set(!frmfav)" icon="" flat="" title="Bookmark this page"> <v-btn slot="activator" @click.stop="set(!frmfav)" icon="" flat="" title="Bookmark this page">
<v-icon>star_border</v-icon> <v-icon>star_border</v-icon>
</v-btn> </v-btn>
<v-card style="width:400px;"> <v-card style="width:400px;">
<v-toolbar class="green"> <v-toolbar class="green">
<v-card-title> <v-card-title>
@ -264,6 +299,27 @@ Vue.component('vp-favorite',{template:`
} }
); );
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/vp-filepick.vue
Vue.component('vp-filepicker',{template:`
<v-layout>
<v-flex>
<slot name="body"></slot>
</v-flex>
<v-flex v-if="show" xs4="" grey="" lighten-3="">
<slot name="aside"></slot>
</v-flex>
</v-layout>
`,
props: ['show'],
created:function(){
console.log("vp-filepicker");
}
}
);
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/vp-job.vue // src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/components/vp-job.vue
Vue.component('vp-job',{template:` Vue.component('vp-job',{template:`
<v-card> <v-card>
@ -356,7 +412,7 @@ Vue.component('vp-notifications',{template:`
<v-list-tile-sub-title v-html="msg.text"></v-list-tile-sub-title> <v-list-tile-sub-title v-html="msg.text"></v-list-tile-sub-title>
</v-list-tile-content> </v-list-tile-content>
<v-list-tile-action> <v-list-tile-action>
<v-list-tile-action-text>{{ msg.index }}</v-list-tile-action-text> <v-list-tile-action-text>#{{ msg.index }}</v-list-tile-action-text>
</v-list-tile-action> </v-list-tile-action>
</v-list-tile> </v-list-tile>
</template> </template>
@ -652,7 +708,7 @@ const Log=Vue.extend({template:`
</v-toolbar> </v-toolbar>
<v-data-table :headers="headers" :items="items" :search="search" class="elevation-1" no-data-text="No logs found" v-bind:pagination.sync="pagination"> <v-data-table :headers="headers" :items="items" :search="search" class="elevation-1" no-data-text="No logs found" v-bind:pagination.sync="pagination">
<template slot="items" scope="props"> <template slot="items" slot-scope="props">
<td class="text-xs-right">{{ props.item.time }}</td> <td class="text-xs-right">{{ props.item.time }}</td>
<td class="text-xs-right">{{ props.item.user }}</td> <td class="text-xs-right">{{ props.item.user }}</td>
<td class="text-xs-right">{{ props.item.type }}</td> <td class="text-xs-right">{{ props.item.type }}</td>
@ -715,6 +771,7 @@ const Log=Vue.extend({template:`
const Brutusin=Vue.extend({template:` const Brutusin=Vue.extend({template:`
<v-container fluid=""> <v-container fluid="">
<v-card> <v-card>
<v-card-title>vue-form-generator</v-card-title>
<vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator> <vue-form-generator :schema="schema" :model="model" :options="formOptions"></vue-form-generator>
</v-card> </v-card>
</v-container> </v-container>
@ -943,7 +1000,7 @@ const Files=Vue.extend({template:`
</v-card> </v-card>
<v-progress-linear v-if="busy" v-bind:indeterminate="true" height="2"></v-progress-linear> <v-progress-linear v-if="busy" v-bind:indeterminate="true" height="2"></v-progress-linear>
<v-navigation-drawer left="" absolute="" v-model="showInfo" :disable-route-watcher="true"> <v-navigation-drawer left="" app="" v-model="showInfo" :disable-route-watcher="true">
<v-card flat="" tile=""> <v-card flat="" tile="">
<v-toolbar> <v-toolbar>
<v-card-title>{{ selection[0] &amp;&amp; selection[0].name }}</v-card-title> <v-card-title>{{ selection[0] &amp;&amp; selection[0].name }}</v-card-title>
@ -1691,6 +1748,74 @@ const Eval=Vue.extend({template:`
); );
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/form/formschema.vue
const Formsjson=Vue.extend({template:`
<v-container fluid="">
<v-card>
<v-card-title>vue-json-schema@1.1.0 https://github.com/formschema/native</v-card-title>
<form-schema ref="formSchema" :schema="schema" v-model="model">
<v-btn color="success" @click.stop="submit">Subscribe</v-btn>
</form-schema>
</v-card>
</v-container>
`,
components: {
"form-schema": window["vue-json-schema"].default
},
data: () => ({
schema: {
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"title": "Newsletter Subscription",
"properties": {
"name": {
"type": "string",
"minLength": 8,
"maxLength": 80,
"attrs": {
"placeholder": "Full Name",
"title": "Please enter your full name"
}
},
"email": {
"type": "string",
"maxLength": 120,
"attrs": {
"type": "email",
"placeholder": "Email"
}
},
"lists": {
"type": "string",
"enum": ["Daily New", "Promotion"]
},
"arrayInput": {
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false,
"required": ["name", "email", "lists"]
},
model: {}
}),
methods: {
submit (e) {
// this.model contains the valid data according your JSON Schema.
// You can submit your model to the server here
console.log(this.model);
alert("hi")
}
}
}
);
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/home.vue // src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/home.vue
const Home=Vue.extend({template:` const Home=Vue.extend({template:`
@ -2411,7 +2536,7 @@ const Jobs=Vue.extend({template:`
</v-btn> </v-btn>
</v-toolbar> </v-toolbar>
<v-data-table :headers="headers" :items="items" :search="search" v-model="selected" select-all="" class="elevation-1" no-data-text="No Jobs currently running"> <v-data-table :headers="headers" :items="items" :search="search" v-model="selected" select-all="" class="elevation-1" no-data-text="No Jobs currently running">
<template slot="items" scope="props"> <template slot="items" slot-scope="props">
<td class="vtop"> <td class="vtop">
<v-checkbox primary="" hide-details="" v-model="props.selected"></v-checkbox> <v-checkbox primary="" hide-details="" v-model="props.selected"></v-checkbox>
</td> </td>
@ -2551,6 +2676,49 @@ const Login=Vue.extend({template:`
); );
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/model/documentation.vue
const Documentation=Vue.extend({template:`
<v-container fluid="">
<v-list>
<v-list-tile v-for="item in items" v-bind:key="item.title" @click="doEdit(item)" avatar="">
<v-list-tile-action>
<v-chip v-text="item.protocol">Example Chip</v-chip>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title @click="doEdit(item)" v-text="item.url"></v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-container>
`,
data: function(){
return {
message: 'Hello Vue.js!',
items:[]
}
},
methods:{
get() {
HTTP.get('xqdoc')
.then((res) => {
this.items = res.data.items;
console.log("items",this.items)
});
},
doEdit(item){
console.log("history: ",item)
router.push({ path: 'edit', query: { url:item.url, protocol:item.protocol }})
}
},
created:function(){
this.get()
console.log("history")
}
}
);
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/model/entity.vue // src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/model/entity.vue
const Entity=Vue.extend({template:` const Entity=Vue.extend({template:`
<v-card> <v-card>
@ -2558,31 +2726,31 @@ const Entity=Vue.extend({template:`
<v-toolbar-title>Entities</v-toolbar-title> <v-toolbar-title>Entities</v-toolbar-title>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn @click="getItems" :loading="loading" :disabled="loading">Refresh</v-btn> <v-btn @click="getItems" :loading="loading" :disabled="loading">Refresh</v-btn>
Text
</v-toolbar> </v-toolbar>
<v-container fluid="" grid-list-md=""> <v-container fluid="" grid-list-md="">
<v-data-iterator content-tag="v-layout" row="" wrap="" :items="items" :rows-per-page-items="rowsPerPageItems" :pagination.sync="pagination" select-all="" :value="selected"> <v-data-iterator content-tag="v-layout" row="" wrap="" :loading="loading" :items="items" :rows-per-page-items="rowsPerPageItems" :pagination.sync="pagination" select-all="" :value="selected">
<v-flex slot="item" slot-scope="props" xs12="" sm6="" md4="" lg3=""> <v-flex slot="item" slot-scope="props" xs12="" sm6="" md4="" lg3="">
<v-card> <v-card hover="true" active-class="default-class qd-active">
<v-card-title>
<router-link :to="{path:'entity/'+ props.item.name}">
<h4>
<v-icon>{{ props.item.iconclass }}</v-icon> {{ props.item.name }}
</h4>
</router-link>
</v-card-title>
<v-toolbar color="amber">
<v-card-title>
<router-link :to="{path:'entity/'+ props.item.name}">
<h3>
<v-icon>{{ props.item.iconclass }}</v-icon> {{ props.item.name }}
</h3>
</router-link>
</v-card-title>
</v-toolbar>
<v-card-text>{{ props.item.description }}<!--<v-card-text--> <v-card-text>{{ props.item.description }}<!--<v-card-text-->
<v-card-actions> <v-card-text>
<v-list dense=""> <v-badge color="red">
<v-list-tile> <span slot="badge">{{ props.item.nfields }}</span>
<v-list-tile-content>Fields:</v-list-tile-content> Fields
<v-list-tile-content class="align-end">{{ props.item.nfields }}</v-list-tile-content> </v-badge>
</v-list-tile> </v-card-text>
</v-list>
</v-card-actions>
</v-card-text></v-card> </v-card-text></v-card>
</v-flex> </v-flex>
</v-data-iterator> </v-data-iterator>
@ -2623,18 +2791,69 @@ const Entity=Vue.extend({template:`
// src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/namespace.vue // src: file:///C:/Users/andy/git/vue-poc/src/vue-poc/features/namespace.vue
const Namespace=Vue.extend({template:` const Namespace=Vue.extend({template:`
<v-container fluid=""> <v-container fluid="" grid-list-md="">
namespaces <v-toolbar>
<v-toolbar-title>Namespaces</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn @click="load" :loading="loading" :disabled="loading">Refresh</v-btn>
Text
</v-toolbar>
<v-data-iterator content-tag="v-layout" row="" wrap="" :loading="loading" :items="items" :rows-per-page-items="rowsPerPageItems" :pagination.sync="pagination" select-all="" :value="selected">
<v-flex slot="item" slot-scope="props" xs12="" sm6="" md4="" lg3="">
<v-card hover="true" active-class="default-class qd-active" height="200px">
<v-toolbar color="amber">
<v-card-title>
<router-link :to="{path:'entity/'+ props.item.name}">
<h3>
<v-icon>star</v-icon> {{ props.item.xmlns }}
</h3>
</router-link>
</v-card-title>
</v-toolbar>
<v-card-text>{{ props.item.description }}<!--<v-card-text-->
<v-card-text>
<v-badge color="red">
<span slot="badge">{{ props.item.prefix }}</span>
Fields
</v-badge>
</v-card-text>
</v-card-text></v-card>
</v-flex>
</v-data-iterator>
</v-container> </v-container>
`, `,
data: function(){ data: function(){
return { return {
items: [],
loading: false,
q: "",
message: 'bad route!' message: 'bad route!'
} }
}, },
methods: {
load(){
this.loading= true
HTTP.get("data/namespace",{params:{}})
.then(r=>{
this.items= r.data.items
this.q= null
this.loading= false
})
.catch(error=> {
console.log(error);
this.loading= false
alert("Get query error"+url)
});
},
},
created:function(){ created:function(){
console.log("notfound",this.$route.query.q) this.q=this.$route.query.q || this.q;
this.load();
console.log("namespaces")
} }
} }
@ -2651,7 +2870,7 @@ const Ping=Vue.extend({template:`
</v-toolbar> </v-toolbar>
<v-card-text> <v-card-text>
<p>Read or increment a database value. This measures round trip times browser-database-browser.</p> <p>Read or increment a database value. This measures round trip times browser-database-browser.</p>
<p>Counter:{{counter}}</p> <h3>Counter: <v-chip color="amber" text-color="white">{{counter}}</v-chip></h3>
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
@ -2887,7 +3106,7 @@ const Repo=Vue.extend({template:`
<v-spacer></v-spacer> <v-spacer></v-spacer>
</v-toolbar> </v-toolbar>
<v-data-table :headers="headers" :items="items" :search="search" v-model="selected" select-all="" class="elevation-1" no-data-text="No repo found @todo"> <v-data-table :headers="headers" :items="items" :search="search" v-model="selected" select-all="" class="elevation-1" no-data-text="No repo found @todo">
<template slot="items" scope="props"> <template slot="items" slot-scope="props">
<td class="vtop"> <td class="vtop">
<v-checkbox primary="" hide-details="" v-model="props.selected"></v-checkbox> <v-checkbox primary="" hide-details="" v-model="props.selected"></v-checkbox>
</td> </td>
@ -3103,7 +3322,7 @@ const Session=Vue.extend({template:`
item-value="suburb" item-value="suburb"
@selected="handleSelected" @selected="handleSelected"
strict="Unknown"> strict="Unknown">
<template slot="item" scope="data"> <template slot="item" slot-scope="data">
<v-list-tile-content> <v-list-tile-content>
<v-list-tile-title>{{data.item.suburb}}</v-list-tile-title> <v-list-tile-title>{{data.item.suburb}}</v-list-tile-title>
<template v-if="!data.item.generatedItem"> <template v-if="!data.item.generatedItem">
@ -4189,6 +4408,7 @@ const router = new VueRouter({
{ path: '/images/dates', component: Dates, meta:{title:"Image dates"} }, { path: '/images/dates', component: Dates, meta:{title:"Image dates"} },
{ path: '/images/people', component: People, meta:{title:"Image people"} }, { path: '/images/people', component: People, meta:{title:"Image people"} },
{ path: '/documentation', component: Documentation, meta:{title:"documentation"} },
{ path: '/entity', component: Entity, meta:{title:"Entities"} }, { path: '/entity', component: Entity, meta:{title:"Entities"} },
{ path: '/namespace', component: Namespace, meta:{title:"Namespaces"} }, { path: '/namespace', component: Namespace, meta:{title:"Namespaces"} },
{ path: '/select', component: Select, meta:{title:"Select"} }, { path: '/select', component: Select, meta:{title:"Select"} },
@ -4206,6 +4426,7 @@ const router = new VueRouter({
{ path: '/history', component: History, meta:{title:"File History"} }, { path: '/history', component: History, meta:{title:"File History"} },
{ path: '/puzzle', component: Puzzle, meta:{title:"Jigsaw"} }, { path: '/puzzle', component: Puzzle, meta:{title:"Jigsaw"} },
{ path: '/svg', component: Svg, meta:{title:"SVG"} }, { path: '/svg', component: Svg, meta:{title:"SVG"} },
/* { path: '/svg2', component: Svg2, meta:{title:"SVG2"} }, */
{ path: '/transform', component: Transform, meta:{title:"XSLT2 Transform"} }, { path: '/transform', component: Transform, meta:{title:"XSLT2 Transform"} },
{ path: '/validate', component: Validate, meta:{title:"Validate"} }, { path: '/validate', component: Validate, meta:{title:"Validate"} },
{ path: '/eval', component: Eval, meta:{title:"Evaluate XQuery"} }, { path: '/eval', component: Eval, meta:{title:"Evaluate XQuery"} },
@ -4219,7 +4440,8 @@ const router = new VueRouter({
{ path: '/jobs/:job', name:"jobShow", component: Job, props: true, meta:{title:"Job Status"} }, { path: '/jobs/:job', name:"jobShow", component: Job, props: true, meta:{title:"Job Status"} },
{ path: '/timeline', component: Timeline,meta:{title:"timeline"} }, { path: '/timeline', component: Timeline,meta:{title:"timeline"} },
{ path: '/map', component: Map,meta:{title:"map"} }, { path: '/map', component: Map,meta:{title:"map"} },
{ path: '/form', component: Brutusin,meta:{title:"Form demo"} }, { path: '/form', component: Brutusin, meta:{title:"Form demo"} },
{ path: '/form2', component: Formsjson, meta:{title:"Form schema"} },
{ path: '/about', component: About,meta:{title:"About Vue-poc"} }, { path: '/about', component: About,meta:{title:"About Vue-poc"} },
{ path: '*', component: Notfound,meta:{title:"Page not found"} } { path: '*', component: Notfound,meta:{title:"Page not found"} }
], ],
@ -4273,7 +4495,7 @@ const Vuepoc=Vue.extend({template:`
</v-list-tile> </v-list-tile>
</v-list> </v-list>
<qd-navlist :items="items"></qd-navlist> <qd-navlist :items="items" :mini="mini"></qd-navlist>
</v-navigation-drawer> </v-navigation-drawer>
<v-toolbar class="indigo" app="" dark=""> <v-toolbar class="indigo" app="" dark="">
@ -4282,8 +4504,7 @@ const Vuepoc=Vue.extend({template:`
<vp-favorite :frmfav.sync="frmfav"></vp-favorite> <vp-favorite :frmfav.sync="frmfav"></vp-favorite>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-select placeholder="Search..." prepend-icon="search" autocomplete="" :loading="loading" combobox="" clearable="" cache-items="" :items="items2" @keyup.enter="goSearch" :search-input.sync="si" v-model="q"></v-select> <qd-search></qd-search>
<v-spacer></v-spacer> <v-spacer></v-spacer>
@ -4303,13 +4524,25 @@ const Vuepoc=Vue.extend({template:`
</v-list> </v-list>
</v-menu> </v-menu>
<qd-fullscreen></qd-fullscreen>
<v-btn @click.stop="showNotifications = ! showNotifications" icon="" flat="" title="Notifications"> <v-btn @click.stop="showNotifications = ! showNotifications" icon="" flat="" title="Notifications">
<v-badge overlap="" color="orange"> <v-badge overlap="" color="orange">
<span slot="badge" v-if=" $notification.unseen">{{ $notification.unseen }}</span> <span slot="badge" v-if=" $notification.unseen">{{ $notification.unseen }}</span>
<v-icon>notifications</v-icon> <v-icon>notifications</v-icon>
</v-badge> </v-badge>
</v-btn> </v-btn>
<v-menu bottom="" left="" min-width="300px">
<v-btn icon="" slot="activator" dark="">
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<v-list-tile>
<v-list-tile-title><qd-fullscreen></qd-fullscreen> Full screen</v-list-tile-title>
</v-list-tile>
<v-list-tile>
<v-list-tile-title><v-switch label="Dark theme" v-model="dark"></v-switch></v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</v-toolbar> </v-toolbar>
<v-content> <v-content>
@ -4326,8 +4559,7 @@ const Vuepoc=Vue.extend({template:`
router, router,
data:function(){return { data:function(){return {
q: "",
loading: false,
searchItems:[], searchItems:[],
si: '', si: '',
items2:["todo","set","search"], items2:["todo","set","search"],
@ -4359,6 +4591,7 @@ const Vuepoc=Vue.extend({template:`
children: [ children: [
{href: '/database', text: 'Databases',icon: 'developer_mode' }, {href: '/database', text: 'Databases',icon: 'developer_mode' },
{href: '/files', text: 'File system',icon: 'folder' }, {href: '/files', text: 'File system',icon: 'folder' },
{href: '/history',text: 'history',icon: 'history'} {href: '/history',text: 'history',icon: 'history'}
]}, ]},
{ {
@ -4366,6 +4599,7 @@ const Vuepoc=Vue.extend({template:`
text: 'Models' , text: 'Models' ,
model: false, model: false,
children: [ children: [
{href: '/documentation', text: 'Documentation',icon: 'library_books' },
{href: '/namespace', text: 'Namespaces',icon: 'label' }, {href: '/namespace', text: 'Namespaces',icon: 'label' },
{href: '/entity', text: 'Entities',icon: 'redeem' }, {href: '/entity', text: 'Entities',icon: 'redeem' },
]}, ]},
@ -4404,6 +4638,7 @@ const Vuepoc=Vue.extend({template:`
{href: '/puzzle',text: 'Puzzle',icon: 'extension'}, {href: '/puzzle',text: 'Puzzle',icon: 'extension'},
{href: '/svg',text: 'SVG',icon: 'extension'}, {href: '/svg',text: 'SVG',icon: 'extension'},
{href: '/form',text: 'Forms',icon: 'format_list_bulleted' }, {href: '/form',text: 'Forms',icon: 'format_list_bulleted' },
{href: '/form2',text: 'Forms 2',icon: 'format_list_bulleted' },
{href: '/tabs',text: 'Tabs',icon: 'switch_camera'} {href: '/tabs',text: 'Tabs',icon: 'switch_camera'}
]}, ]},
@ -4413,21 +4648,12 @@ const Vuepoc=Vue.extend({template:`
}}, }},
methods: { methods: {
querySelections (v) {
this.loading = true
// Simulated ajax query
setTimeout(() => {
this.items2 = ["aa","bb",this.si],
this.loading = false
}, 500)
},
session(){ session(){
this.$router.push({path: '/session'}) this.$router.push({path: '/session'})
}, },
goSearch(){
this.$router.push({path: '/search',query: { q: this.q }})
},
logout(){ logout(){
HTTP.get("logout").then(r=>{ HTTP.get("logout").then(r=>{
alert("logout") alert("logout")
@ -4446,13 +4672,7 @@ const Vuepoc=Vue.extend({template:`
console.log("showNotifications",val); console.log("showNotifications",val);
if(!val)this.$notification.unseen=0; if(!val)this.$notification.unseen=0;
}, },
search (val) {
val && this.querySelections(val)
},
si:function(val){
console.log("si: ",val);
this.querySelections();
}
}, },
created(){ created(){
@ -4600,6 +4820,16 @@ localforage.config({
// https://vuejs.org/v2/guide/state-management.html // https://vuejs.org/v2/guide/state-management.html
var settings = { var settings = {
debug: false, debug: false,
defaults:{
"settings/ace": {
theme: "github",
keybinding: "ace",
fontsize: 16,
enableSnippets:true,
enableBasicAutocompletion:true,
enableLiveAutocompletion:true
},
},
getItem (key) { getItem (key) {
if (this.debug) console.log('getItem',key); if (this.debug) console.log('getItem',key);
return localforage.getItem(key) return localforage.getItem(key)
@ -4709,7 +4939,10 @@ Vue.use(Fullscreen);
//Vue.component('v-map', Vue2Leaflet.Map); //Vue.component('v-map', Vue2Leaflet.Map);
//Vue.component('v-tilelayer', Vue2Leaflet.TileLayer); //Vue.component('v-tilelayer', Vue2Leaflet.TileLayer);
//Vue.component('v-marker', Vue2Leaflet.Marker); //Vue.component('v-marker', Vue2Leaflet.Marker);
//function install (Vue) {
// Vue.component('form-schema', window["vue-json-schema"].default);
//};
//Vue.use({ install: install });
Vue.use(Vuetify); Vue.use(Vuetify);
new Vuepoc().$mount('#app') new Vuepoc().$mount('#app')

View file

@ -124,6 +124,9 @@ height: 100%;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.qd-active {
background-color: green;
}
.canvas { .canvas {
overflow: hidden; overflow: hidden;
} }

View file

@ -10,7 +10,7 @@
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic"/> <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic"/>
<link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons"/> <link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons"/>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css"/> <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css"/>
<link href="https://unpkg.com/vuetify@1.0.0-beta.6/dist/vuetify.min.css" rel="stylesheet" type="text/css"/> <link href="https://unpkg.com/vuetify@1.0.4/dist/vuetify.min.css" rel="stylesheet" type="text/css"/>
<link rel="stylesheet" href="https://unpkg.com/vue-form-generator@2.1.0/dist/vfg.css"/> <link rel="stylesheet" href="https://unpkg.com/vue-form-generator@2.1.0/dist/vfg.css"/>
<link href="/vue-poc/ui/app.css" rel="stylesheet" type="text/css"/> <link href="/vue-poc/ui/app.css" rel="stylesheet" type="text/css"/>
@ -37,7 +37,7 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.4.0/qs.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.4.0/qs.js"></script>
<script src="https://unpkg.com/vuetify@1.0.0-beta.6/dist/vuetify.min.js"></script> <script src="https://unpkg.com/vuetify@1.0.4/dist/vuetify.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.3.1/ace.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.3.1/ace.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.3.1/ext-language_tools.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.3.1/ext-language_tools.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script> <script src="https://d3js.org/d3.v4.min.js"></script>
@ -49,7 +49,7 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.20.1/vis-timeline-graph2d.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.20.1/vis-timeline-graph2d.min.js"></script>
<script src="https://unpkg.com/vue-form-generator@2.1.1/dist/vfg.js"></script> <script src="https://unpkg.com/vue-form-generator@2.1.1/dist/vfg.js"></script>
<script src="https://unpkg.com/vue-json-schema@1.1.0/dist/vue-json-schema.js"></script>
<script src="/vue-poc/ui/svg-pan-zoom.js"></script> <script src="/vue-poc/ui/svg-pan-zoom.js"></script>
<script src="/vue-poc/ui/perf-stat.js"></script> <script src="/vue-poc/ui/perf-stat.js"></script>

View file

@ -0,0 +1,62 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>https://shkspr.mobi/svg/calendar.svg</title><link rel="stylesheet" type="text/css" href="https%20_shkspr.mobi_svg_calendar_files/viewsource.css" /></head><body id="viewsource" class="highlight" style="-moz-tab-size: 4" contextmenu="actions"><pre id="line1"><span></span><span>&lt;<span class="start-tag">svg</span> <span class="attribute-name">onload</span>="<a class="attribute-value">init(evt)</a>" <span class="attribute-name">xmlns</span>="<a class="attribute-value">http://www.w3.org/2000/svg</a>"
<span id="line2"></span><span class="attribute-name">aria-label</span>="<a class="attribute-value">Calendar</a>" <span class="attribute-name">role</span>="<a class="attribute-value">img</a>"
<span id="line3"></span><span class="attribute-name">viewBox</span>="<a class="attribute-value">0 0 512 512</a>"&gt;</span><span>
<span id="line4"></span></span><span>&lt;<span class="start-tag">script</span> <span class="attribute-name">type</span>="<a class="attribute-value">text/ecmascript</a>"&gt;</span><span></span><span class="cdata">&lt;![CDATA[
<span id="line5"></span>function init(evt) {
<span id="line6"></span> var time = new Date();
<span id="line7"></span> var locale = "en-gb";
<span id="line8"></span> var DD = time.getDate();
<span id="line9"></span> var DDD = time.toLocaleString(locale, { weekday: "short" });
<span id="line10"></span> var DDDD = time.toLocaleString(locale, { weekday: "long" });
<span id="line11"></span> var MM = time.getMonth() + 1;
<span id="line12"></span> var MMM = time.toLocaleString(locale, {month: "short"});
<span id="line13"></span> var MMMM = time.toLocaleString(locale, {month: "long"});
<span id="line14"></span> var YYYY = time.getFullYear();
<span id="line15"></span>
<span id="line16"></span> var svgDocument = evt.target.ownerDocument;
<span id="line17"></span> var dayNode = svgDocument.createTextNode(DD);
<span id="line18"></span> svgDocument.getElementById("day").appendChild(dayNode);
<span id="line19"></span> var weekdayNode = svgDocument.createTextNode(DDDD);
<span id="line20"></span> svgDocument.getElementById("weekday").appendChild(weekdayNode);
<span id="line21"></span> var monthNode = svgDocument.createTextNode(MMM.toUpperCase());
<span id="line22"></span> svgDocument.getElementById("month").appendChild(monthNode);
<span id="line23"></span>
<span id="line24"></span>}
<span id="line25"></span>]]&gt;</span><span></span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>
<span id="line26"></span>
<span id="line27"></span></span><span>&lt;<span class="start-tag">path</span> <span class="attribute-name">d</span>="<a class="attribute-value">M512 455c0 32-25 57-57 57H57c-32 0-57-25-57-57V128c0-31 25-57 57-57h398c32 0 57 26 57 57z</a>" <span class="attribute-name">fill</span>="<a class="attribute-value">#e0e7ec</a>"<span>/</span>&gt;</span><span>
<span id="line28"></span></span><span>&lt;<span class="start-tag">path</span> <span class="attribute-name">d</span>="<a class="attribute-value">M484 0h-47c2 4 4 9 4 14a28 28 0 1 1-53-14H124c3 4 4 9 4 14A28 28 0 1 1 75 0H28C13 0 0 13 0 28v157h512V28c0-15-13-28-28-28z</a>" <span class="attribute-name">fill</span>="<a class="attribute-value">#dd2f45</a>"<span>/</span>&gt;</span><span>
<span id="line29"></span>
<span id="line30"></span></span><span>&lt;<span class="start-tag">g</span> <span class="attribute-name">fill</span>="<a class="attribute-value">#f3aab9</a>"&gt;</span><span>
<span id="line31"></span> </span><span>&lt;<span class="start-tag">circle</span> <span class="attribute-name">cx</span>="<a class="attribute-value">470</a>" <span class="attribute-name">cy</span>="<a class="attribute-value">142</a>" <span class="attribute-name">r</span>="<a class="attribute-value">14</a>"<span>/</span>&gt;</span><span>
<span id="line32"></span> </span><span>&lt;<span class="start-tag">circle</span> <span class="attribute-name">cx</span>="<a class="attribute-value">470</a>" <span class="attribute-name">cy</span>="<a class="attribute-value">100</a>" <span class="attribute-name">r</span>="<a class="attribute-value">14</a>"<span>/</span>&gt;</span><span>
<span id="line33"></span> </span><span>&lt;<span class="start-tag">circle</span> <span class="attribute-name">cx</span>="<a class="attribute-value">427</a>" <span class="attribute-name">cy</span>="<a class="attribute-value">142</a>" <span class="attribute-name">r</span>="<a class="attribute-value">14</a>"<span>/</span>&gt;</span><span>
<span id="line34"></span> </span><span>&lt;<span class="start-tag">circle</span> <span class="attribute-name">cx</span>="<a class="attribute-value">427</a>" <span class="attribute-name">cy</span>="<a class="attribute-value">100</a>" <span class="attribute-name">r</span>="<a class="attribute-value">14</a>"<span>/</span>&gt;</span><span>
<span id="line35"></span> </span><span>&lt;<span class="start-tag">circle</span> <span class="attribute-name">cx</span>="<a class="attribute-value">384</a>" <span class="attribute-name">cy</span>="<a class="attribute-value">142</a>" <span class="attribute-name">r</span>="<a class="attribute-value">14</a>"<span>/</span>&gt;</span><span>
<span id="line36"></span> </span><span>&lt;<span class="start-tag">circle</span> <span class="attribute-name">cx</span>="<a class="attribute-value">384</a>" <span class="attribute-name">cy</span>="<a class="attribute-value">100</a>" <span class="attribute-name">r</span>="<a class="attribute-value">14</a>"<span>/</span>&gt;</span><span>
<span id="line37"></span></span><span>&lt;/<span class="end-tag">g</span>&gt;</span><span>
<span id="line38"></span>
<span id="line39"></span></span><span>&lt;<span class="start-tag">text</span> <span class="attribute-name">id</span>="<a class="attribute-value">month</a>"
<span id="line40"></span> <span class="attribute-name">x</span>="<a class="attribute-value">32</a>"
<span id="line41"></span> <span class="attribute-name">y</span>="<a class="attribute-value">164</a>"
<span id="line42"></span> <span class="attribute-name">fill</span>="<a class="attribute-value">#fff</a>"
<span id="line43"></span> <span class="attribute-name">font-family</span>="<a class="attribute-value">monospace</a>"
<span id="line44"></span> <span class="attribute-name">font-size</span>="<a class="attribute-value">140px</a>"
<span id="line45"></span> <span class="attribute-name">style</span>="<a class="attribute-value">text-anchor: left</a>"&gt;</span><span></span><span>&lt;/<span class="end-tag">text</span>&gt;</span><span>
<span id="line46"></span></span><span>&lt;<span class="start-tag">text</span> <span class="attribute-name">id</span>="<a class="attribute-value">day</a>"
<span id="line47"></span> <span class="attribute-name">x</span>="<a class="attribute-value">256</a>"
<span id="line48"></span> <span class="attribute-name">y</span>="<a class="attribute-value">400</a>"
<span id="line49"></span> <span class="attribute-name">fill</span>="<a class="attribute-value">#66757f</a>"
<span id="line50"></span> <span class="attribute-name">font-family</span>="<a class="attribute-value">monospace</a>"
<span id="line51"></span> <span class="attribute-name">font-size</span>="<a class="attribute-value">256px</a>"
<span id="line52"></span> <span class="attribute-name">style</span>="<a class="attribute-value">text-anchor: middle</a>"&gt;</span><span></span><span>&lt;/<span class="end-tag">text</span>&gt;</span><span>
<span id="line53"></span></span><span>&lt;<span class="start-tag">text</span> <span class="attribute-name">id</span>="<a class="attribute-value">weekday</a>"
<span id="line54"></span> <span class="attribute-name">x</span>="<a class="attribute-value">256</a>"
<span id="line55"></span> <span class="attribute-name">y</span>="<a class="attribute-value">480</a>"
<span id="line56"></span> <span class="attribute-name">fill</span>="<a class="attribute-value">#66757f</a>"
<span id="line57"></span> <span class="attribute-name">font-family</span>="<a class="attribute-value">monospace</a>"
<span id="line58"></span> <span class="attribute-name">font-size</span>="<a class="attribute-value">64px</a>"
<span id="line59"></span> <span class="attribute-name">style</span>="<a class="attribute-value">text-anchor: middle</a>"&gt;</span><span></span><span>&lt;/<span class="end-tag">text</span>&gt;</span><span>
<span id="line60"></span>
<span id="line61"></span></span><span>&lt;/<span class="end-tag">svg</span>&gt;</span><span></span></pre><menu type="context" id="actions"><menuitem id="goToLine" label="Go to Line…" accesskey="L"></menuitem><menuitem id="wrapLongLines" label="Wrap Long Lines" type="checkbox"></menuitem><menuitem id="highlightSyntax" label="Syntax Highlighting" type="checkbox" checked="true"></menuitem></menu></body></html>

View file

@ -0,0 +1,30 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"title": "Newsletter Subscription",
"properties": {
"name": {
"type": "string",
"minLength": 8,
"maxLength": 80,
"attrs": {
"placeholder": "Full Name",
"title": "Please enter your full name"
}
},
"email": {
"type": "string",
"maxLength": 120,
"attrs": {
"type": "email",
"placeholder": "Email"
}
},
"lists": {
"type": "string",
"enum": ["Daily New", "Promotion"]
}
},
"additionalProperties": false,
"required": ["name", "email", "lists"]
}