+ textbox for addtional descriptions is now a textarea with 3 rows and 40 cols

+ openstreetmap for basemap
+ author table is now sortable (vuedraggable)
This commit is contained in:
Arno Kaimbacher 2019-07-19 17:41:57 +02:00
parent ad2e1ce378
commit 77b59fc33b
31 changed files with 648 additions and 385 deletions

View file

@ -0,0 +1,128 @@
<template>
<table class="pure-table pure-table-horizontal" v-if="list.length">
<thead class="thead-dark">
<tr>
<th scope="col">Sort Order</th>
<th scope="col">First Name</th>
<th scope="col">Last Name</th>
<th scope="col">Email</th>
<th scope="col">Orcid</th>
<th></th>
</tr>
</thead>
<draggable v-bind:list="list" tag="tbody" v-on:start="isDragging=true" v-on:end="isDragging=false">
<tr
v-for="(item, index) in list"
v-bind:key="item.id"
v-bind:class="[item.status==1 ? 'activeClass' : 'inactiveClass']"
>
<td scope="row">{{ index + 1 }}</td>
<td>
<input
name="first_name"
class="form-control"
placeholder="[FIRST NAME]"
v-model="item.first_name"
v-bind:readonly="item.status==1"
v-validate="'required'"
data-vv-scope="step-1"
/>
</td>
<td>
<input
name="last_name"
class="form-control"
placeholder="[LAST NAME]"
v-model="item.last_name"
v-bind:readonly="item.status==1"
v-validate="'required'"
data-vv-scope="step-1"
/>
</td>
<td>
<input
name="email"
class="form-control"
placeholder="[EMAIL]"
v-model="item.email"
v-validate="'required|email'"
v-bind:readonly="item.status==1"
data-vv-scope="step-1"
/>
</td>
<td>
<input
name="identifier_orcid"
class="form-control"
placeholder="[ORCID optional]"
v-model="item.identifier_orcid"
v-bind:readonly="item.status==1"
data-vv-scope="step-1"
/>
</td>
<td>
<button class="pure-button button-small is-warning" @click.prevent="removeAuthor(index)"> <i class="fa fa-trash"></i> </button>
</td>
</tr>
</draggable>
</table>
</template>
<script>
import draggable from "vuedraggable";
export default {
inject: {
$validator: "$validator"
},
name: "creator-table",
components: {
draggable
},
data() {
return {
// list: [
// { id: 1, name: "Abby", sport: "basket" },
// { id: 2, name: "Brooke", sport: "foot" },
// { id: 3, name: "Courtenay", sport: "volley" },
// { id: 4, name: "David", sport: "rugby" }
// ],
editable: true,
isDragging: false,
delayedDragging: false
};
},
props: {
list: {
type: Array,
required: true
},
rowIndex: {
type: Number
}
},
methods: {
itemAction(action, data, index) {
console.log("custom-actions: " + action, data.full_name, index);
},
removeAuthor(key) {
this.list.splice(key, 1);
},
onMove({ relatedContext, draggedContext }) {
const relatedElement = relatedContext.element;
const draggedElement = draggedContext.element;
return (
(!relatedElement || !relatedElement.fixed) && !draggedElement.fixed
);
}
}
};
</script>
<style>
.custom-actions button.ui.button {
padding: 8px 8px;
}
.custom-actions button.ui.button > i.icon {
margin: auto !important;
}
</style>

View file

@ -35,32 +35,63 @@
data-vv-scope="step-2"
>
<input type="button" v-on:click="zoomTo" value="zoomTo">
</div> -->
</div>-->
<div id="map"></div>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-2 pure-div">
<label for="xmin">xmin: </label>
<input name="xmin" type="text" class="pure-u-23-24" v-model="geolocation.xmin" data-vv-scope="step-2" id="xmin" v-validate="'decimal'">
</div>
<div class="pure-u-1 pure-u-md-1-2 pure-div">
<label for="ymin">ymin: </label>
<input name="ymin" type="text" class="pure-u-23-24" v-model="geolocation.ymin" data-vv-scope="step-2" id="ymin" v-validate="'decimal'">
<label for="xmin">xmin:</label>
<input
name="xmin"
type="text"
class="pure-u-23-24"
v-model="geolocation.xmin"
data-vv-scope="step-2"
id="xmin"
v-validate="'decimal'"
/>
</div>
<div class="pure-u-1 pure-u-md-1-2 pure-div">
<label for="xmax">xmax: </label>
<input name="xmax" type="text" class="pure-u-23-24" v-model="geolocation.xmax" data-vv-scope="step-2" id="xmax" v-validate="'decimal'">
<label for="ymin">ymin:</label>
<input
name="ymin"
type="text"
class="pure-u-23-24"
v-model="geolocation.ymin"
data-vv-scope="step-2"
id="ymin"
v-validate="'decimal'"
/>
</div>
<div class="pure-u-1 pure-u-md-1-2 pure-div">
<label for="ymax">ymax: </label>
<input name="ymax" type="text" class="pure-u-23-24" v-model="geolocation.ymax" data-vv-scope="step-2" id="ymax" v-validate="'decimal'">
<label for="xmax">xmax:</label>
<input
name="xmax"
type="text"
class="pure-u-23-24"
v-model="geolocation.xmax"
data-vv-scope="step-2"
id="xmax"
v-validate="'decimal'"
/>
</div>
<input type="button" v-on:click="zoomTo" value="validate coordinates">
<div class="pure-u-1 pure-u-md-1-2 pure-div">
<label for="ymax">ymax:</label>
<input
name="ymax"
type="text"
class="pure-u-23-24"
v-model="geolocation.ymax"
data-vv-scope="step-2"
id="ymax"
v-validate="'decimal'"
/>
</div>
<input type="button" v-on:click="zoomTo" value="validate coordinates" />
</div>
</div>
</template>
@ -72,7 +103,7 @@ import "leaflet-draw";
//const L = window.L;
export default {
inject: {
$validator: '$validator'
$validator: "$validator"
},
props: {
geolocation: {
@ -86,13 +117,13 @@ export default {
locationErrors: []
};
},
created() {
this.$validator.extend('boundingBox', {
getMessage: field => 'At least one ' + field + ' needs to be checked.',
validate: (value, [testProp]) => {
const options = this.dataset.checkedLicenses;
return value || options.some((option) => option[testProp]);
}
created() {
this.$validator.extend("boundingBox", {
getMessage: field => "At least one " + field + " needs to be checked.",
validate: (value, [testProp]) => {
const options = this.dataset.checkedLicenses;
return value || options.some(option => option[testProp]);
}
});
},
computed: {},
@ -108,9 +139,9 @@ export default {
var ymax = document.getElementById("ymax").value;
var bounds = [[ymin, xmin], [ymax, xmax]];
try {
var boundingBox = L.rectangle(bounds, { color: "#005F6A", weight: 1 });
var boundingBox = L.rectangle(bounds, { color: "#005F6A", weight: 1 });
// this.geolocation.xmin = xmin;
// this.geolocation.ymin = ymin;
// this.geolocation.ymin = ymin;
// this.geolocation.xmax = xmax;
// this.geolocation.ymax = ymax;
@ -137,18 +168,23 @@ export default {
var southWest1 = L.latLng(46.35877, 8.782379); //lowerCorner
var northEast1 = L.latLng(49.037872, 17.189532); //upperCorner
var layerBounds = L.latLngBounds(southWest1, northEast1);
var attribution = "www.basemap.at";
var basemap_0 = L.tileLayer(
"https://{s}.wien.gv.at/basemap/bmapgrau/normal/google3857/{z}/{y}/{x}.png",
{
attribution: attribution,
subdomains: ["maps", "maps1", "maps2", "maps3"],
continuousWorld: false,
detectRetina: false,
bounds: layerBounds
}
);
basemap_0.addTo(map);
// var attribution = "www.basemap.at";
// var basemap_0 = L.tileLayer(
// "https://{s}.wien.gv.at/basemap/bmapgrau/normal/google3857/{z}/{y}/{x}.png",
// {
// attribution: attribution,
// subdomains: ["maps", "maps1", "maps2", "maps3"],
// continuousWorld: false,
// detectRetina: false,
// bounds: layerBounds
// }
// );
//basemap_0.addTo(map);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution:
'© <a target="_blank" href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(this.map);
map.fitBounds(bounds);
this.map = map;

View file

@ -32,6 +32,7 @@ import MyAutocomplete from './components/MyAutocomplete.vue';
import VeeValidate from 'vee-validate';
import dataset from './components/Dataset';
import LocationsMap from './components/LocationsMap.vue';
import CreatorTable from './components/CreatorTable.vue';
import modal from './components/ShowModal.vue';
// import datetime from 'vuejs-datetimepicker';
// import { Validator } from 'vee-validate';
@ -48,9 +49,16 @@ Vue.use(VeeValidate, {
const STATUS_INITIAL = 0, STATUS_SAVING = 1, STATUS_SUCCESS = 2, STATUS_FAILED = 3;
const app = new Vue({
el: '#app',
components: { MyAutocomplete, LocationsMap, modal },
components: { MyAutocomplete, LocationsMap, modal, CreatorTable },
data() {
return {
list: [
{ id: 1, name: "Abby", sport: "basket" },
{ id: 2, name: "Brooke", sport: "foot" },
{ id: 3, name: "Courtenay", sport: "volley" },
{ id: 4, name: "David", sport: "rugby" }
],
dragging: true,
rows: [
//initial data
// { qty: 5, value: "Something", language: 10, type: "additional", sort_order: 0 },
@ -274,7 +282,7 @@ const app = new Vue({
formData.append('authors[' + i + '][identifier_orcid]', person.identifier_orcid);
formData.append('authors[' + i + '][status]', person.status);
if (person.id !== undefined) {
formData.append('authors[' + i + '][id]', person.id)
formData.append('authors[' + i + '][id]', person.id);
}
}

View file

@ -160,7 +160,7 @@
<tbody>
<tr v-for="(item, index) in dataset.descriptions">
<td>
<input name="Description[Value]" class="form-control" placeholder="[DESCRIPTION]" v-model="item.value" v-validate="'required'" data-vv-scope="step-1" />
<textarea rows="3" cols="40" name="Description[Value]" class="form-control" placeholder="[DESCRIPTION]" v-model="item.value" v-validate="'required'" data-vv-scope="step-1"></textarea>
</td>
<td>
{!! Form::select('Description[Type]', $descriptionTypes, null,
@ -187,7 +187,7 @@
<legend>Creator(s)</legend>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-2 pure-div">
<my-autocomplete title="searching active person table" @person="onAddAuthor"></my-autocomplete>
<my-autocomplete title="searching active person table" v-on:person="onAddAuthor"></my-autocomplete>
{{--
<my-autocomplete :items="[ 'Apple', 'Banana', 'Orange', 'Mango', 'Pear', 'Peach', 'Grape', 'Tangerine', 'Pineapple']"></my-autocomplete> --}}
</div>
@ -207,41 +207,10 @@
<button class="pure-button button-small" @click.prevent="addNewAuthor()">+</button>
</div>
<input name="persons" v-model="dataset.persons" type="hidden" class="form-check-input" v-validate="'required'" data-vv-as="Creator" data-vv-scope="step-1">
<table class="pure-table pure-table-horizontal" v-if="dataset.persons.length">
<thead>
<tr>
<th>Index</th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Orcid</th>
<th style="width: 130px;"></th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in dataset.persons" v-bind:key="item.sort_order" v-bind:class="[item.status==1 ? 'activeClass' : 'inactiveClass']" >
<td>@{{ index }}</td>
<td>
<input name="first_name" class="form-control" placeholder="[FIRST NAME]" v-model="item.first_name" v-bind:readonly="item.status==1" v-validate="'required'" data-vv-scope="step-1" />
</td>
<td>
<input name="last_name" class="form-control" placeholder="[LAST NAME]" v-model="item.last_name" v-bind:readonly="item.status==1" v-validate="'required'" data-vv-scope="step-1" />
</td>
<td>
<input name="email" class="form-control" placeholder="[EMAIL]" v-model="item.email" v-validate="'required|email'" v-bind:readonly="item.status==1" v-validate="'required'" data-vv-scope="step-1" />
</td>
<td>
<input name="identifier_orcid" class="form-control" placeholder="[ORCID]" v-model="item.identifier_orcid" v-bind:readonly="item.status==1" data-vv-scope="step-1" />
<small id="orcidHelp" class="pure-form-message-inline">ORCID is optional</small>
</td>
<td>
<button class="pure-button button-small is-warning" @click.prevent="removeAuthor(index)">-</button>
</td>
</tr>
</tbody>
</table>
<h3>Draggable table</h3>
<creator-table name="persons" v-bind:list="dataset.persons"></creator-table>
</fieldset>
<fieldset id="fieldset-contributors">
<legend>Contributors</legend>
<div class="pure-g">
@ -670,6 +639,7 @@
@{{ item.name }} <i class="fa fa-remove"></i><span class="remove-file" v-on:click="removeFile(index)"> Remove</span>
</li>
</ul> --}}
<table class="table table-hover" v-if="dataset.files.length">
<thead>
<tr>