- larvale version 5.6 to 5.8

This commit is contained in:
Arno Kaimbacher 2019-10-21 18:37:08 +02:00
parent a2967b90ee
commit 265cfbcd30
43 changed files with 925 additions and 246 deletions

22
resources/js/app.js Normal file
View file

@ -0,0 +1,22 @@
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('my-vuetable', require('./components/MyVuetable.vue'));
const app = new Vue({
el: '#app'
});

View file

@ -0,0 +1,32 @@
// releaseDataset.js
import Vue from 'vue';
import VeeValidate from 'vee-validate';
Vue.use(VeeValidate);
const app = new Vue({
el: '#app1',
data() {
return {
dataset: {
firstName: '',
reviewer_id: ''
},
submitted: false
}
},
methods: {
checkForm(e) {
// Log entire model to console
// console.log(this.dataset);
this.submitted = true;
this.$validator.validate().then(result => {
if (result) {
console.log('From Submitted!');
document.getElementById("approveForm").submit();
return;
}
});
}
}
});

29
resources/js/bootstrap.js vendored Normal file
View file

@ -0,0 +1,29 @@
window._ = require('lodash');
/**
* We'll load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
* CSRF token as a header based on the value of the "XSRF" token cookie.
*/
try {
window.$ = window.jQuery = require('jquery');
// require('bootstrap-sass');
} catch (e) {}
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
/**
* Next we will register the CSRF Token as a common header with Axios so that
* all outgoing HTTP requests automatically have it attached. This is just
* a simple convenience so we don't have to attach every token manually.
*/
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
}
else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

37
resources/js/ckeditor.js vendored Normal file
View file

@ -0,0 +1,37 @@
// import Vue from 'vue';
// import CKEditor from '@ckeditor/ckeditor5-vue';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
// import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
// const app = new Vue({
// name: 'app',
// components: {
// // Use the <ckeditor> component in this view.
// ckeditor: CKEditor.component
// },
// props: ['desc_markup'],
// data() {
// return {
// editor: ClassicEditor,
// //desc_markup: '<p>Content of the editor.</p>',
// editorConfig: {
// // The configuration of the editor.
// }
// };
// }
// });
var allEditors = document.querySelectorAll('.ckeditor');
for (var i = 0; i < allEditors.length; ++i) {
ClassicEditor
.create(allEditors[i], {
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote']
})
.then(editor => {
console.log(editor);
})
.catch(error => {
console.error(error);
});
}

View file

@ -0,0 +1,38 @@
<template>
<div class="custom-actions">
<button class="view" @click="itemAction('view-item', rowData, rowIndex)">
</button>
<a class="edit" @click="itemAction('edit-item', rowData, rowIndex)">
</a>
<a class="delete" @click="itemAction('delete-item', rowData, rowIndex)">
</a>
</div>
</template>
<script>
export default {
props: {
rowData: {
type: Object,
required: true
},
rowIndex: {
type: Number
}
},
methods: {
itemAction(action, data, index) {
console.log("custom-actions: " + action, data.full_name, index);
}
}
};
</script>
<style>
.custom-actions button.ui.button {
padding: 8px 8px;
}
.custom-actions button.ui.button > i.icon {
margin: auto !important;
}
</style>

View file

@ -0,0 +1,87 @@
// <script>
import Vue from "vue";
//outside of the component:
function initialState() {
return {
type: "",
state: "",
rights: null,
project_id: "",
creating_corporation: "GBA Repository",
language: "",
embargo_date: "",
belongs_to_bibliography: 0,
title_main: {
value: "",
language: ""
},
abstract_main: {
value: "",
language: ""
},
// geolocation: {
// xmin: "",
// ymin: "",
// xmax: "",
// ymax: ""
// },
coverage: {
xmin: "",
ymin: "",
xmax: "",
ymax: "",
elevation_min: "",
elevation_max: "",
elevation_absolut: "",
depth_min: "",
depth_max: "",
depth_absolut: "",
time_min: "",
time_max: "",
time_absolut: ""
},
checkedAuthors: [],
checkedLicenses: [], // [],
files: [],
keywords: [],
references: [],
titles: [],
descriptions: [],
checkedContributors: [],
// checkedSubmitters: [],
persons: [],
contributors: []
// submitters: []
};
}
const dataset = new Vue({
data: function() {
return initialState();
},
created: function() {
// let json = JSON.stringify(this.$data);
// this.reset = () => {
// Object.assign(this.$data, JSON.parse(json));
// };
// this.reset(json);
},
watch: {
language(val) {
this.title_main.language = val;
this.abstract_main.language = val;
}
},
methods: {
reset() {
Object.assign(this.$data, initialState());
}
}
});
export default dataset;
//export { dataset };
</script>

View file

@ -0,0 +1,287 @@
<template>
<div style="position:relative">
<!-- <div id="inset">
xmin:
<input
type="text"
name="xmin"
id="xmin"
v-model="geolocation.xmin"
data-vv-scope="step-2"
v-validate="'decimal'"
>
<br>ymin:
<input
type="text"
name="ymin"
id="ymin"
v-model="geolocation.ymin"
data-vv-scope="step-2"
>
xmax:
<input
type="text"
name="xmax"
id="xmax"
v-model="geolocation.xmax"
data-vv-scope="step-2"
>
<br>ymax:
<input
type="text"
name="ymax"
id="ymax"
v-model="geolocation.ymax"
data-vv-scope="step-2"
>
<input type="button" v-on:click="zoomTo" value="zoomTo">
</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'"
/>
</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'"
/>
</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'"
/>
</div>
<input type="button" v-on:click="zoomTo" value="validate coordinates" />
</div>
</div>
</template>
<script>
// import "leaflet";
import * as L from "leaflet";
import "leaflet-draw";
//const L = window.L;
export default {
inject: {
$validator: "$validator"
},
props: {
geolocation: {
type: Object
}
},
data() {
return {
map: [],
drawnItems: null,
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]);
}
});
},
computed: {},
watch: {},
methods: {
zoomTo() {
var _this = this;
_this.locationErrors.length = 0;
this.drawnItems.clearLayers();
var xmin = document.getElementById("xmin").value;
var ymin = document.getElementById("ymin").value;
var xmax = document.getElementById("xmax").value;
var ymax = document.getElementById("ymax").value;
var bounds = [[ymin, xmin], [ymax, xmax]];
try {
var boundingBox = L.rectangle(bounds, { color: "#005F6A", weight: 1 });
// this.geolocation.xmin = xmin;
// this.geolocation.ymin = ymin;
// this.geolocation.xmax = xmax;
// this.geolocation.ymax = ymax;
_this.drawnItems.addLayer(boundingBox);
_this.map.fitBounds(bounds);
_this.$toast.success("valid bounding box");
} catch (e) {
// _this.errors.push(e);
_this.$toast.error(e);
}
}
},
mounted() {
const map = L.map("map");
this.map = map;
map.scrollWheelZoom.disable();
// Construct a bounding box for this map that the user cannot
var southWest = L.latLng(46.5, 9.9),
northEast = L.latLng(48.9, 16.9),
bounds = L.latLngBounds(southWest, northEast);
// zoom the map to that bounding box
// map.fitBounds(bounds);
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);
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;
// this.addPlaces(this.places)
// Initialise the FeatureGroup to store editable layers
var drawnItems = (this.drawnItems = new L.FeatureGroup());
map.addLayer(drawnItems);
var drawPluginOptions = {
position: "topright",
draw: {
polygon: false,
// disable toolbar item by setting it to false
polyline: false,
circle: false,
circlemarker: false,
rectangle: {
shapeOptions: {
clickable: true,
color: "#005F6A"
}
},
marker: false
},
edit: {
featureGroup: drawnItems, //REQUIRED!!
remove: false
}
};
// Initialise the draw control and pass it the FeatureGroup of editable layers
var drawControl = new L.Control.Draw(drawPluginOptions);
map.addControl(drawControl);
map.on(
L.Draw.Event.CREATED,
function(event) {
drawnItems.clearLayers();
var type = event.layerType;
var layer = event.layer;
// if (type === "rectancle") {
// layer.bindPopup("A popup!" + layer.getBounds().toBBoxString());
var bounds = layer.getBounds();
this.geolocation.xmin = bounds.getSouthWest().lng;
this.geolocation.ymin = bounds.getSouthWest().lat;
// console.log(this.geolocation.xmin);
this.geolocation.xmax = bounds.getNorthEast().lng;
this.geolocation.ymax = bounds.getNorthEast().lat;
// }
drawnItems.addLayer(layer);
},
this
);
map.on(
L.Draw.Event.EDITED,
function(event) {
var layers = event.layers.getLayers();
var layer = layers[0];
var bounds = layer.getBounds();
this.geolocation.xmin = bounds.getSouthWest().lng;
this.geolocation.ymin = bounds.getSouthWest().lat;
// console.log(this.geolocation.xmin);
this.geolocation.xmax = bounds.getNorthEast().lng;
this.geolocation.ymax = bounds.getNorthEast().lat;
},
this
);
}
};
</script>
// https://github.com/vuejs-templates/webpack/issues/121
// npm install node-sass sass-loader --save-dev
<style lang="scss">
// Import CSS from Leaflet and plugins.
@import "~leaflet/dist/leaflet.css";
@import "~leaflet-draw/dist/leaflet.draw.css";
#map {
width: 100%;
height: 400px;
font-weight: bold;
font-size: 13px;
text-shadow: 0 0 2px #fff;
}
#inset {
position: absolute;
bottom: 0;
left: 0;
border: none;
width: 120px;
z-index: 999;
// height: 120px;
}
</style>

View file

@ -0,0 +1,176 @@
<!-- https://pineco.de/instant-ajax-search-laravel-vue/
https://alligator.io/vuejs/vue-autocomplete-component/ -->
<template>
<div style="position:relative">
<input type="search" @input="searchChanged" v-model="search" v-bind:readonly="isLoading == true" v-bind:title="title" v-bind:placeholder="title"
class="pure-u-23-24" v-on:keydown.down="onArrowDown" v-on:keydown.up="onArrowUp" v-on:keydown.enter="onEnter">
<!-- <ul class="autocomplete-results" v-show="results.length > 0"> -->
<ul class="autocomplete-results pure-u-23-24" v-show="isOpen">
<li class="loading" v-if="isLoading" >Loading results...</li>
<li
v-else
v-for="(suggestion, i) in results"
:key="i"
@click="setResult(suggestion)"
class="autocomplete-result"
:class="{ 'is-active': i === arrowCounter }"
>
<strong>{{ suggestion.full_name }}</strong>
</li>
</ul>
</div>
</template>
<script>
import _ from 'lodash';
import axios from 'axios';
export default {
//data from parent component
props: {
title: String
// items: {
// type: Array,
// required: false,
// default: () => []
// },
// isAsync: {
// type: Boolean,
// required: false,
// default: false
// }
},
data() {
return {
search: null,
results: [],
isOpen: false,
isLoading: false,
isAsync: true,
items: [],
arrowCounter: -1
};
},
// watch: {
// search(after, before) {
// this.isOpen = true;
// this.filterResults();
// }
// },
watch: {
// Once the items content changes, it means the parent component
// provided the needed data
items: function(value, oldValue) {
// we want to make sure we only do this when it's an async request
if (this.isAsync) {
this.results = value;
this.isOpen = true;
this.isLoading = false;
} else {
if (value.length !== oldValue.length) {
this.results = value;
this.isLoading = false;
}
}
}
},
methods: {
setResult(person) {
// this.search = person.full_name;
this.reset();
this.$emit("person", person);
},
reset() {
this.search = "";
this.results = [];
this.isOpen = false;
},
searchChanged() {
// Let's warn the parent that a change was made
this.$emit("input", this.search);
if (this.search.length >= 2) {
// Is the data given by an outside ajax request?
if (this.isAsync) {
this.isLoading = true;
this.filterResults();
} else {
// Data is sync, we can search our flat array
this.results = this.items.filter(item => {
return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
});
this.isOpen = true;
}
} else {
this.items = [];
}
},
filterResults: _.debounce(function() {
var self = this;
axios
.get("/api/persons", { params: { filter: this.search.toLowerCase() } })
.then(function(response) {
return (self.items = response.data.data);
})
.catch(function(error) {
alert(error);
});
// this.results = this.items.filter(item => {
// return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
// });
}, 300),
onArrowDown() {
if (this.arrowCounter < this.results.length - 1) {
this.arrowCounter = this.arrowCounter + 1;
}
},
onArrowUp() {
if (this.arrowCounter > 0) {
this.arrowCounter = this.arrowCounter - 1;
}
},
onEnter() {
if(Array.isArray(this.results) && this.results.length && this.arrowCounter !== -1 && this.arrowCounter < this.results.length){
//this.search = this.results[this.arrowCounter];
var person = this.results[this.arrowCounter];
this.$emit("person", person);
//this.isOpen = false;
this.reset();
this.arrowCounter = -1;
}
}
},
computed: {
// isOpen() {
// return this.results.length > 0;
// }
}
};
</script>
<style>
.autocomplete-results {
padding: 0;
margin: 0;
border: 1px solid #eeeeee;
height: 120px;
overflow: auto;
}
.autocomplete-result {
list-style: none;
text-align: left;
padding: 4px 2px;
cursor: pointer;
}
.autocomplete-result.is-active,
.autocomplete-result:hover {
background-color: #4aae9b;
color: white;
}
</style>

View file

@ -0,0 +1,107 @@
// MyVuetable.vue
<!-- :fields="['name', 'email', 'birthdate']" -->
// "https://vuetable.ratiw.net/api/users"
<template>
<vuetable ref="vuetable"
api-url="/api/persons"
v-bind:fields="fields" pagination-path=""
v-bind:css="css.table"
></vuetable>
</template>
<script>
import Vuetable from "vuetable-2/src/components/Vuetable";
import VuetablePagination from 'vuetable-2/src/components/VuetablePagination'
import VuetablePaginationInfo from 'vuetable-2/src/components/VuetablePaginationInfo'
import CustomActions from './CustomActions'
Vue.component('custom-actions', CustomActions)
export default {
components: {
Vuetable,
VuetablePagination,
VuetablePaginationInfo,
},
data() {
return {
fields: [
{
name: "full_name",
// sortField: "full_name"
},
{
name: "email",
sortField: "email"
},
{
name: "date_of_birth",
sortField: "date_of_birth",
// titleClass: "text-center",
// dataClass: "text-center",
// callback: "formatDate|DD-MM-YYYY"
},
{
name: "__component:custom-actions",
title: "Actions",
// titleClass: "text-center",
// dataClass: "text-center"
}
],
css: {
table: {
tableClass: "table pure-table pure-table-horizontal",
ascendingIcon: "glyphicon glyphicon-chevron-up",
descendingIcon: "glyphicon glyphicon-chevron-down"
},
icons: {
first: "glyphicon glyphicon-step-backward",
prev: "glyphicon glyphicon-chevron-left",
next: "glyphicon glyphicon-chevron-right",
last: "glyphicon glyphicon-step-forward"
}
},
sortOrder: [{ field: "email", sortField: "email", direction: "asc" }],
moreParams: {}
};
}//data end
};
</script>
<style>
.pagination {
margin: 0;
float: right;
}
.pagination a.page {
border: 1px solid lightgray;
border-radius: 3px;
padding: 5px 10px;
margin-right: 2px;
}
.pagination a.page.active {
color: white;
background-color: #337ab7;
border: 1px solid lightgray;
border-radius: 3px;
padding: 5px 10px;
margin-right: 2px;
}
.pagination a.btn-nav {
border: 1px solid lightgray;
border-radius: 3px;
padding: 5px 7px;
margin-right: 2px;
}
.pagination a.btn-nav.disabled {
color: lightgray;
border: 1px solid lightgray;
border-radius: 3px;
padding: 5px 7px;
margin-right: 2px;
cursor: not-allowed;
}
.pagination-info {
float: left;
}
</style>

View file

@ -0,0 +1,132 @@
<template>
<div>
<h3 v-if="heading && personlist.length">{{ heading }}</h3>
<table class="pure-table pure-table-horizontal" v-if="personlist.length">
<thead class="thead-dark">
<tr>
<th scope="col">#</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="personlist" tag="tbody" v-on:start="isDragging=true" v-on:end="isDragging=false">
<tr
v-for="(item, index) in personlist"
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>
</div>
</template>
<script>
import draggable from "vuedraggable";
export default {
inject: {
$validator: "$validator"
},
name: "person-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: {
personlist: {
type: Array,
required: true
},
rowIndex: {
type: Number
},
heading: String
},
methods: {
itemAction(action, data, index) {
console.log("custom-actions: " + action, data.full_name, index);
},
removeAuthor(key) {
this.personlist.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

@ -0,0 +1,222 @@
// https://alligator.io/vuejs/vue-modal-component/
<template>
<div class="modal-backdrop">
<div class="popup">
<div class="fm_overlay" >
<header class="popupbar">
<slot name="header">
<b class="popuptitle">Help</b>
</slot>
<button class="btn-close" @click="close">x</button>
</header>
<section class="pageinfo">
<slot name="body">I'm the default body!</slot>
</section>
</div>
</div>
</div>
</template>
<script>
export default {
name: "modal",
methods: {
close() {
this.$emit("close");
}
}
};
</script>
<style>
.popup_close {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH3AgBFSI5w7714wAAAYlJREFUSMfd1c9KFWEYBvCfJz15NI8RoRnpLohuILyMll1CG0taibhqERkJQWFBixbZpkSwlRs3kdfhBYgaBHU4h8bNGwzTfDNzIgh8YWBmeL7n/TPP8w7/MUb+BbaVeD+NO+g0IG9hEVeaVtPFGjK8wIUa/KPAvsVsHfk0VuNAhh420E7gl/Eth39TlWQsV02GX7kkzzBeGMtDnOawv/GbqdF28A79kkM/8CSSjGAJxyW4DPsxidJoR5uDksM/8TgqP0qQf8bluu/QwetEJ4PcfZF8B1ebKmkSLxNJyp4/YWZYo3VDpt9zRMWrjw+Y+1s3X8dBRYJD3K5zYSpGcRfzNV3ew8SwlbfwoEKKRXU9LfikNpZwkiAvS9LDenRdG8sV5Fsh4V6ik+dVY29jJbdbiuQfcQ1TIeFBopNXIfM/4mLIsox8uyDFbhCV+WQPl1JdLOB9YdY7CRNNxmLr57BfQraVP6sbMesMuzX2H4/dleErbjVV0QLuN3ToREj65rBeGB0CO+bcxhlxQrBXIUNRlQAAAABJRU5ErkJggg==")
/*icons/close.png*/ no-repeat;
}
/* anything but phone */
@media all and (min-width: 768px) {
.popup_close {
width: 20px;
height: 20px;
/*margin: 5px;*/
background-size: 20px 20px;
float: right;
cursor: pointer;
z-index: 800;
}
.fm_overlay {
top: 10em;
left: 30%;
max-width: 480px;
min-width: 300px;
/*max-height: 90%;*/
max-height: 500px;
overflow: auto;
}
}
/* only phone - bigger buttons */
@media all and (max-width: 767px) {
.popup_close {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH3AcXFyot5RvgagAAAbdJREFUaN7t2DFOAkEUxvE/6AFMUBMoIDExHsMDqJVgZ+KJKIyFBSjGxCN4DbUSC6XRys5GZDXYMAkh7rLz5s0smPmSLXnDj2Hhm4WYmJiYlFSAG2DTw+wS0AZ2fSOqQB8YA09ATXF2GbiczB4CeyEQY2VMGbiYmT0E9kMgtDB/IbxgahkIV0wWQhWTByHF5EGY68sFY4OwxdggpjEHEsit5ULmegDW5/zEnglnfwAbtpA68CxcsJ+yM2WgK5w5Ag6lXy9NjCui6XrD14EXB0x1ERAm28Cr8I3cA+fC134Dx9p/ii47I7kSzZ0oCuMVEQoTBGHS8IQJivCFKQShjUmAVtEnxgYwWHaE6U7XDpCBpD9pR9JibbpZMERX8WYvBKONKATjCzFbNJcaEQQTCuEVUwJOHar4u8MRoLIIO2Fqh8bhzBnRUepOhWE0ERqYRymmLVzwBzjJmLsDvAln3wFrtpDW5JP1UQClrfkKWJHsig3GtsXaYnpShEkzB0ZaxfMeAXqTe9Y5WZgEOPJ4nlFDZGFcEfMw6ohpzEgZkYbxhpjGfCojZjHeESZbnp8BrBITExPzr/MLneElMzKD908AAAAASUVORK5CYII=")
/*mobile_icons/close.png*/ no-repeat;
width: 25px;
height: 25px;
background-size: 25px 25px;
float: right;
cursor: pointer;
z-index: 800;
}
.fm_overlay {
bottom: 4em;
left: 20px;
right: 20px;
max-height: 70%;
overflow-y: auto;
}
/*.touch .fm_basemap_list{ max-height: 80%; overflow-y: auto;}*/
}
.popup .fm_overlay {
position: fixed;
width: 300px;
left: 50%;
margin-left: -150px;
top: 50%;
margin-top: -150px;
z-index: 9999;
padding: 10px;
border-radius: 1px;
box-shadow: 0 0 0 10px rgba(34, 34, 34, 0.6);
}
.popupbar {
background: dimgray;
/* color: white; */
padding-left: 4px;
height: 25px;
border-bottom: 1px solid #eeeeee;
color: #4aae9b;
justify-content: space-between;
}
.popup_close {
color: rgb(220, 220, 220);
/*background: gray;*/
border: 1px solid darkgray;
border-radius: 4px;
font-size: 16px;
font-weight: bold;
width: 16px;
height: 16px;
text-align: center;
float: right;
cursor: pointer;
background-size: 16px 16px;
}
.fm_overlay {
background-color: white;
padding: 2px 5px 2px;
max-height: 500px;
overflow: auto;
font-size: 14px;
}
.pageinfo {
font-size: small;
}
.pageinfo h1 {
background-color: gray;
color: white;
font-size: small;
font-weight: normal;
margin-top: 5px;
margin-bottom: 3px;
padding: 1px;
padding-left: 6px;
}
.license {
font-size: xx-small;
}
.star {
padding: 5px;
text-align: left;
}
.modal-backdrop {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
}
.modal {
background: #ffffff;
box-shadow: 2px 2px 20px 1px;
overflow-x: auto;
display: flex;
flex-direction: column;
}
.modal-header,
.modal-footer {
padding: 15px;
display: flex;
}
.modal-header {
border-bottom: 1px solid #eeeeee;
color: #4aae9b;
justify-content: space-between;
}
.modal-footer {
border-top: 1px solid #eeeeee;
justify-content: flex-end;
}
.modal-body {
position: relative;
padding: 20px 10px;
max-width: 150px;
max-height: 150px;
}
.btn-close {
border: none;
font-size: 20px;
font-weight: bold;
color: #4aae9b;
background: transparent;
float: right;
cursor: pointer;
}
.btn-green {
color: white;
background: #4aae9b;
border: 1px solid #4aae9b;
border-radius: 2px;
}
</style>

View file

@ -0,0 +1,574 @@
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
// window.axios = require('axios');
// window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
/**
* Next we will register the CSRF Token as a common header with Axios so that
* all outgoing HTTP requests automatically have it attached. This is just
* a simple convenience so we don't have to attach every token manually.
*/
// let token = document.head.querySelector('meta[name="csrf-token"]');
// if (token) {
// window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
// }
// else {
// console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
// }
// window._ = require('lodash');
// window.Vue = require('vue');
// Vue.prototype.$http = axios;
import Vue from 'vue';
import axios from 'axios';
// Vue.component('example', require('./components/Example.vue'));
//Vue.component('my-autocomplete', require('./components/MyAutocomplete.vue'));
import MyAutocomplete from './components/MyAutocomplete.vue';
import messagesEN from './strings/messages/en.js';
import VeeValidate from 'vee-validate';
import dataset from './components/Dataset';
import LocationsMap from './components/LocationsMap.vue';
import PersonTable from './components/PersonTable.vue';
import modal from './components/ShowModal.vue';
// import datetime from 'vuejs-datetimepicker';
// import { Validator } from 'vee-validate';
import VueToast from 'vue-toast-notification';
import 'vue-toast-notification/dist/index.css';
Vue.use(VueToast);
const dict = {
custom: {
keyword_list: {
keywords_length: 'Minimum 3 keywords are required'
}
}
};
// Vue.use(VeeValidate);
Vue.use(VeeValidate, {
// validity: true
locale: 'en',
useConstraintAttrs: true,
dictionary: {
en: { messages: messagesEN }
}
});
const STATUS_INITIAL = 0, STATUS_SAVING = 1, STATUS_SUCCESS = 2, STATUS_FAILED = 3;
const app = new Vue({
el: '#app',
components: { MyAutocomplete, LocationsMap, modal, PersonTable },
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 },
// { qty: 2, value: "Something else", language: 20, type: "additional", sort_order: 0 },
],
serrors: [],
uploadedFiles: [],
uploadError: null,
currentStatus: null,
uploadFieldName: 'photos',
fileCount: 0,
releaseLink: null,
deleteLink: null,
isModalVisible: false,
step: 0,
dataset: dataset,
elevation: "no_elevation",
depth: "no_depth",
time: "no_time",
// dataset: {
// type: '',
// state: '',
// rights: null,
// project_id: '',
// creating_corporation: "GBA",
// embargo_date: '',
// belongs_to_bibliography: 0,
// title_main: {
// value: '',
// language: ''
// },
// abstract_main: {
// value: '',
// language: ''
// },
// checkedAuthors: [],
// checkedLicenses: [],// [],
// files: [],
// references: [],
// checkedContributors: [],
// checkedSubmitters: [],
// }
}
},
created: function () {
VeeValidate.Validator.extend('Name', {
getMessage: field => '* Enter valid ' + field + '',
validate: value => /^[a-zA-Z]*$/.test(value)
});
// add the required rule
VeeValidate.Validator.extend('oneChecked', {
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]);
}
});
// add the required rule
VeeValidate.Validator.extend('translatedLanguage', {
getMessage: field => 'The translated ' + field + ' must be in a language other than than the dataset language.',
validate: (value, [mainLanguage, type]) => {
if (type == "translated") {
return value !== mainLanguage;
}
return true;
}
});
},
mounted() {
//this.step = 2;
this.reset();
},
computed: {
keywords_length() {
return this.dataset.keywords.length;
},
isInitial() {
return this.currentStatus === STATUS_INITIAL;
},
isSaving() {
return this.currentStatus === STATUS_SAVING;
},
isSuccess() {
return this.currentStatus === STATUS_SUCCESS;
},
isFailed() {
return this.currentStatus === STATUS_FAILED;
},
isElevationAbsolut() {
return this.elevation === "absolut";
},
isElevationRange() {
return this.elevation === "range";
},
isDepthAbsolut() {
return this.depth === "absolut";
},
isDepthRange() {
return this.depth === "range";
},
isTimeAbsolut() {
return this.time === "absolut";
},
isTimeRange() {
return this.time === "range";
}
},
methods: {
showModal() {
this.isModalVisible = true;
},
closeModal() {
this.isModalVisible = false;
},
reset() {
// reset form to initial state
this.currentStatus = STATUS_INITIAL;
this.uploadedFiles = [];
this.uploadError = null;
this.dataset.reset();//reset methods will trigger property changed.
this.step = 0;
},
retry() {
// reset form to initial state
this.currentStatus = STATUS_INITIAL;
// this.uploadedFiles = [];
// this.uploadError = null;
// this.dataset.reset();//reset methods will trigger property changed.
// this.step = 1;
},
releaseNewDataset() {
window.location = this.releaseLink;
},
deleteNewDataset() {
window.location = this.deleteLink;
},
resetDropbox() {
// reset form to initial state
this.currentStatus = STATUS_INITIAL;
this.dataset.files = [];
},
save(status) {
// upload data to the server
var _this = this;
this.currentStatus = STATUS_SAVING;
this.serrors = [];
/*
Initialize the form data
*/
let formData = new FormData();
/*
Iteate over any file sent over appending the files
to the form data.
*/
// formData.append('files', []);
for (var i = 0; i < this.dataset.files.length; i++) {
let file = this.dataset.files[i];
formData.append('files[' + i + '][file]', file.file);
formData.append('files[' + i + '][label]', file.label);
formData.append('files[' + i + '][sorting]', i + 1);
// formData.append('files[' + i + ']', JSON.stringify(file));
}
/*
Additional POST Data
*/
formData.append('server_state', status);
formData.append('type', this.dataset.type);
formData.append('language', this.dataset.language);
// formData.append('server_state', this.dataset.state);
formData.append('rights', Number(this.dataset.rights));
formData.append('creating_corporation', this.dataset.creating_corporation);
formData.append('project_id', this.dataset.project_id);
formData.append('embargo_date', this.dataset.embargo_date);
formData.append('belongs_to_bibliography', this.dataset.belongs_to_bibliography);
formData.append('title_main[value]', this.dataset.title_main.value);
formData.append('title_main[language]', this.dataset.title_main.language);
formData.append('abstract_main[value]', this.dataset.abstract_main.value);
formData.append('abstract_main[language]', this.dataset.abstract_main.language);
if (this.dataset.coverage.xmin !== "" && this.dataset.coverage.ymin != '' &&
this.dataset.coverage.xmax !== '' && this.dataset.coverage.ymax !== '') {
formData.append('coverage[x_min]', this.dataset.coverage.xmin);
formData.append('coverage[y_min]', this.dataset.coverage.ymin);
formData.append('coverage[x_max]', this.dataset.coverage.xmax);
formData.append('coverage[y_max]', this.dataset.coverage.ymax);
}
if (this.isElevationAbsolut) {
formData.append('coverage[elevation_absolut]', this.dataset.coverage.elevation_absolut);
}
else if (this.isElevationRange) {
formData.append('coverage[elevation_min]', this.dataset.coverage.elevation_min);
formData.append('coverage[elevation_max]', this.dataset.coverage.elevation_max);
}
if (this.isDepthAbsolut) {
formData.append('coverage[depth_absolut]', this.dataset.coverage.depth_absolut);
}
else if (this.isDepthRange) {
formData.append('coverage[depth_min]', this.dataset.coverage.depth_min);
formData.append('coverage[depth_max]', this.dataset.coverage.depth_max);
}
if (this.isTimeAbsolut) {
formData.append('coverage[time_absolut]', this.dataset.coverage.time_absolut);
}
else if (this.isTimeRange) {
formData.append('coverage[time_min]', this.dataset.coverage.time_min);
formData.append('coverage[time_max]', this.dataset.coverage.time_max);
}
for (var i = 0; i < this.dataset.checkedLicenses.length; i++) {
formData.append('licenses[' + i + ']', this.dataset.checkedLicenses[i]);
}
// for (var i = 0; i < this.dataset.checkedAuthors.length; i++) {
// formData.append('authors[' + i + ']', this.dataset.checkedAuthors[i]);
// }
for (var i = 0; i < this.dataset.persons.length; i++) {
let person = this.dataset.persons[i];
formData.append('authors[' + i + '][first_name]', person.first_name);
formData.append('authors[' + i + '][last_name]', person.last_name);
formData.append('authors[' + i + '][email]', person.email);
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);
}
}
// for (var i = 0; i < this.dataset.checkedContributors.length; i++) {
// formData.append('contributors[' + i + ']', this.dataset.checkedContributors[i]);
// }
for (var i = 0; i < this.dataset.contributors.length; i++) {
let contributor = this.dataset.contributors[i];
formData.append('contributors[' + i + '][first_name]', contributor.first_name);
formData.append('contributors[' + i + '][last_name]', contributor.last_name);
formData.append('contributors[' + i + '][email]', contributor.email);
formData.append('contributors[' + i + '][identifier_orcid]', contributor.identifier_orcid);
formData.append('contributors[' + i + '][status]', contributor.status);
if (contributor.id !== undefined) {
formData.append('contributors[' + i + '][id]', contributor.id);
}
}
// for (var i = 0; i < this.dataset.checkedSubmitters.length; i++) {
// formData.append('submitters[' + i + ']', this.dataset.checkedSubmitters[i]);
// }
for (var i = 0; i < this.dataset.references.length; i++) {
let reference = this.dataset.references[i];
formData.append('references[' + i + '][value]', reference.value);
formData.append('references[' + i + '][label]', reference.label);
formData.append('references[' + i + '][type]', reference.type);
formData.append('references[' + i + '][relation]', reference.relation);
}
for (var i = 0; i < this.dataset.keywords.length; i++) {
let keyword = this.dataset.keywords[i];
formData.append('keywords[' + i + '][value]', keyword.value);
formData.append('keywords[' + i + '][type]', keyword.type);
}
for (var i = 0; i < this.dataset.titles.length; i++) {
let title = this.dataset.titles[i];
formData.append('titles[' + i + '][value]', title.value);
formData.append('titles[' + i + '][language]', title.language);
formData.append('titles[' + i + '][type]', title.type);
}
for (var i = 0; i < this.dataset.descriptions.length; i++) {
let description = this.dataset.descriptions[i];
formData.append('descriptions[' + i + '][value]', description.value);
formData.append('descriptions[' + i + '][language]', description.language);
formData.append('descriptions[' + i + '][type]', description.type);
}
/*
Make the request to the POST /multiple-files URL
*/
axios.post('/publish/dataset/store',
formData,
{
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then((response) => {
// success callback
console.log(response.data);
// this.loading = false;
// this.items = response.data;
//Vue.set(app.skills, 1, "test55");
_this.currentStatus = STATUS_SUCCESS;
_this.releaseLink = response.data.release;
_this.deleteLink = response.data.delete;
// if (response.data.redirect) {
// window.location = response.data.redirect;
// }
})
.catch((error) => {
// this.loading = false;
this.uploadError = error.response;
console.log('FAILURE!!');
let errorObject = JSON.parse(JSON.stringify(error));
// console.log(errorObject);
if (errorObject.response.data.errors) {
var errorsArray = errorObject.response.data.errors;
for (var index in errorsArray) {
console.log(errorsArray[index]);
_this.serrors.push(errorsArray[index]);
}
}
//fill with server error
if (errorObject.response.data.error) {
var error = errorObject.response.data.error;
_this.serrors.push(error.message);
}
//raundtrip to server was not possible
if (error.message && error.message.includes('413')) {
console.log('The file you tried to upload is too large.')
var error = 'The file you tried to upload is too large.';
_this.serrors.push(error);
}
_this.currentStatus = STATUS_FAILED;
});
},
// filesChange(fieldName, fileList) {
// // handle file changes
// // const formData = new FormData();
// if (!fileList.length) return;
// // append the files to FormData
// Array
// .from(Array(fileList.length).keys())
// .map(x => {
// dataset.files.append(fieldName, fileList[x], fileList[x].name);
// });
// // save it
// // this.save(formData);
// },
/*
Handles a change on the file upload
*/
addReference() {
let newReference = { value: '', label: '', relation: '', type: '' };
//this.dataset.files.push(uploadedFiles[i]);
this.dataset.references.push(newReference);
},
/*
Removes a selected reference
*/
removeReference(key) {
this.dataset.references.splice(key, 1);
},
/*
adds a new Keyword
*/
addKeyword() {
let newKeyword = { value: '', type: '', language: this.dataset.language };
//this.dataset.files.push(uploadedFiles[i]);
this.dataset.keywords.push(newKeyword);
},
/*
Removes a selected keyword
*/
removeKeyword(key) {
this.dataset.keywords.splice(key, 1);
},
addTitle() {
let newTitle = { value: '', language: '', type: '' };
//this.dataset.files.push(uploadedFiles[i]);
this.dataset.titles.push(newTitle);
},
/*
Removes a selected title
*/
removeTitle(key) {
this.dataset.titles.splice(key, 1);
},
addDescription() {
let newTitle = { value: '', language: '', type: '' };
//this.dataset.files.push(uploadedFiles[i]);
this.dataset.descriptions.push(newTitle);
},
/*
Removes a selected description
*/
removeDescription(key) {
this.dataset.descriptions.splice(key, 1);
},
filesChange(fieldName, fileList) {
this.fileCount = fileList.length
// this.dataset.files = this.$refs.files.files;
let uploadedFiles = fileList;
/*
Adds the uploaded file to the files array
*/
for (var i = 0; i < uploadedFiles.length; i++) {
let fileName = uploadedFiles[i].name.replace(/\.[^/.]+$/, '');
let uploadeFile = { file: uploadedFiles[i], label: fileName, sorting: 0 };
//this.dataset.files.push(uploadedFiles[i]);
this.dataset.files.push(uploadeFile);
}
// if (this.dataset.files.length > 0)
// {
// this.currentStatus = STATUS_SAVING;
// }
},
addNewAuthor() {
let newAuthor = { status: 0, first_name: '', last_name: '', email: '', academic_title: '', identifier_orcid: '' };
this.dataset.persons.push(newAuthor);
},
removeAuthor(key) {
this.dataset.persons.splice(key, 1);
},
onAddAuthor(person) {
//if person is not in person array
//if (this.persons.includes(person) == false) {
if (this.dataset.persons.filter(e => e.id === person.id).length > 0) {
this.$toast.error("person is already defined as author");
} else if (this.dataset.contributors.filter(e => e.id === person.id).length > 0) {
this.$toast.error("person is already defined as contributor");
} else {
//person.sort_order = this.dataset.persons.length;
this.dataset.persons.push(person);
this.dataset.checkedAuthors.push(person.id);
this.$toast.success("person has been successfully added as author");
}
},
addNewContributor() {
let newContributor = { status: 0, first_name: '', last_name: '', email: '', academic_title: '', identifier_orcid: '' };
this.dataset.contributors.push(newContributor);
},
onAddContributor(person) {
//if person is not in contributors array
//if (this.contributors.includes(person) == false) {
if (this.dataset.contributors.filter(e => e.id === person.id).length > 0) {
this.$toast.error("person is already defined as contributor");
} else if (this.dataset.persons.filter(e => e.id === person.id).length > 0) {
this.$toast.error("person is already defined as author");
} else {
this.dataset.contributors.push(person);
this.dataset.checkedContributors.push(person.id);
this.$toast.success("person has been successfully added as contributor");
}
},
// onAddSubmitter(person) {
// //if person is not in submitters array
// //if (this.submitters.includes(person) == false) {
// if (this.dataset.submitters.filter(e => e.id === person.id).length == 0) {
// this.dataset.submitters.push(person);
// this.dataset.checkedSubmitters.push(person.id);
// }
// },
/*
Removes a select file the user has uploaded
*/
removeFile(key) {
this.dataset.files.splice(key, 1);
},
prev() {
this.step--;
},
next(scope) {
// if(this.validate(scope)) {
// this.step++;
// }
this.$validator.validateAll(scope).then((result) => {
if (result) {
this.step++;
}
});
},
validate: function (scope) {
this.$validator.validateAll(scope);
if (this.errors.any()) {
console.log('The form is invalid');
return false;
}
return true;
},
submit(status) {
// alert('Submit to blah and show blah and etc.');
// save it
this.save(status);
}
}
});

6
resources/js/jquery-global.js vendored Normal file
View file

@ -0,0 +1,6 @@
//https://stackoverflow.com/questions/35358625/jquery-is-not-defined-when-use-es6-import
// jquery-global.js
import jquery from 'jquery';
window.jQuery = jquery;
window.$ = jquery;

26
resources/js/lib.js Normal file
View file

@ -0,0 +1,26 @@
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
// require('./bootstrap');
window.$ = window.jQuery = require('jquery');
// window.Vue = require('vue');
// import Vue from 'vue';
// Vue.prototype.$http = axios;
// Vue.component('example', require('./components/Example.vue'));
// const app = new Vue({
// el: '#app',
// data: {
// loading: false,
// downloading: false,
// items: [],
// message: "Just a test",
// }
// });

View file

@ -0,0 +1,52 @@
// releaseDataset.js
import Vue from 'vue';
import VeeValidate from 'vee-validate';
Vue.use(VeeValidate);
const app = new Vue({
el: '#app1',
data() {
return {
// dataset: {
// firstName: '',
// preferred_reviewer: null,
// preferred_reviewer_email: null
// },
dataset: window.Laravel.dataset,
submitted: false,
preferation: "yes_preferation",
}
},
computed: {
isPreferationRequired() {
return this.preferation === "yes_preferation";
},
},
watch: {
preferation(val) {
if (val === "no_preferation") {
this.dataset.preferred_reviewer = "";
this.dataset.preferred_reviewer_email = "";
}
}
},
methods: {
checkForm(e) {
// Log entire model to console
// console.log(this.dataset);
this.submitted = true;
this.$validator.validate().then(result => {
if (result) {
if (this.preferation === "no_preferation") {
this.dataset.preferred_reviewer = "";
this.dataset.preferred_reviewer_email = "";
}
// console.log('From Submitted!');
document.getElementById("releaseForm").submit();
return;
}
});
}
}
});

86
resources/js/scripts.js Normal file
View file

@ -0,0 +1,86 @@
import './jquery-global.js';
import 'single-page-nav/jquery.singlePageNav.js';
//bind plugin definition to jQuery
$(document).ready(function () {
// =Hero
// Alway make hero-container height equal to window height
var $heroContainer = $('.hero');
$heroContainer.height(window.innerHeight);
// When user resize browser window, hero container needs to have the same
// height as browser window height.
$(window).resize(function () {
$heroContainer.height(window.innerHeight);
});
// =Work
// Isotope filters
// var $workFilterLinks = $('.work-filters li');
// var $container = $('.work-items');
// $workFilterLinks.find('a').click(function(){
// $workFilterLinks.removeClass('active');
// $container.isotope({
// // options
// filter: $(this).attr('data-filter'),
// itemSelector: '.isotope-item',
// animationEngine : "best-available",
// masonry: {
// columnWidth: '.isotope-item'
// }
// });
// $(this).parent().addClass('active');
// return false;
// });
// Menu initialization
var $menuIcon = $('.menu-icon'),
$navigation = $('.navigation'),
$menu = $('.menu'),
$navigationLink = $('.menu a');
if (location.pathname == "/") {
$(window).scroll(function () {
if (window.scrollY > window.outerHeight) {
$menuIcon.addClass('active');
} else {
$menuIcon.removeClass('active');
}
});
}
$menuIcon.click(function (e) {
e.preventDefault();
$navigation.toggleClass('active');
});
// $menu.singlePageNav({
// filter: ':not(.external)',
// speed: 1000,
// currentClass: 'current',
// easing: 'swing',
// updateHash: false,
// beforeStart: function() {
// },
// onComplete: function() {
// $navigation.removeClass('active');
// }
// });
//// Scrollreveal initialize
// var config = {
// easing: 'hustle',
// reset: false,
// delay: 'onload',
// opacity: .2,
// vFactor: 0.2,
// mobile: false
// }
// window.sr = new scrollReveal(config);
});

View file

@ -0,0 +1,82 @@
<template v-if="loaded">
<div class="search-container row">
<div class="four columns left-bar">
<div id="left-bar" class="sidebar left-bar">
<div class="sidebar-image"></div>
<!-- <h2 class="indexheader">DataXplore</h2> -->
<!-- <div class="card" v-for="item in facets.language" :key="item.id">
<span>{{ item }}</span>
</div>-->
<!-- <facet-list v-bind:data="facets"></facet-list> -->
<!-- <div class="card" v-for="(item, index) in facets" :key="index"> -->
<div class="card" v-for="(values, key, index) in facets" :key="index">
<facet-list :data="values" :filterName="key" @filter="onFilter"></facet-list>
</div>
</div>
</div>
<div class="eight columns right-bar">
<div id="right-bar" class="sidebar right-bar">
<!-- Search input section -->
<div class="row">
<div class="twelve columns">
<vs-input @search="onSearch"></vs-input>
</div>
</div>
<div v-if="results.length > 0" class="result-list-info">
<div class="resultheader">
Your search yielded
<strong>{{ numFound }}</strong> results:
</div>
</div>
<div class="row">
<div class="active-filter-items twelve columns">
<a class="filter-link" v-for="(value, key, index) in activeFilterItems" :key="index">
<span>{{ key + ": " }}</span>
<span v-if="value && value.length > 0">{{ value.join(', ') }}</span>
</a>
</div>
</div>
<!-- Results section -->
<vs-results v-bind:data="results"></vs-results>
<!-- pagination -->
<div class="row">
<div class="twelve columns">
<vs-pagination v-bind:data="pagination" @paginate="onPaginate"></vs-pagination>
</div>
</div>
</div>
</div>
</div>
<!-- <div class="card" v-for="item in results" :key="item.id">
<img
v-if="item.thumb"
class="card-img-top"
:src="item.thumb"
:alt="item.title"
@error="error(item)"
/>
<div class="card-body">
<h5 class="card-title">{{item.name}}</h5>
<p class="card-text" v-html="truncate(item.description || item.abstract, 50)"></p>
</div>
</div>
</div>-->
</template>
<script lang="ts">
import App from "./app-class";
export default App;
</script>
<style lang="scss">
#app {
color: #56b983;
}
</style>

View file

@ -0,0 +1,147 @@
import { Component, Vue, Prop, Provide } from 'vue-property-decorator';
import VsInput from './text-search/vs-input.vue';
import VsResults from './search-results/vs-results.vue';
import FacetList from './search-results/facet-list.vue';
import VsPagination from './search-results/vs-pagination.vue';
import rdrApi from './search-results/dataservice';
import FilterItem from './models/filter-item';
@Component({
components: {
VsInput,
VsResults,
FacetList,
VsPagination
}
})
export default class App extends Vue {
results: Array<any> = [];
facets: Object = {};
searchTerm: string = '';
activeFilterItems: Object = {};
pagination: Object = {
total: 0,
per_page: 2,
current_page: 0,
// last_page: 0,
data: []
};
loaded = false;
numFound: number;
async onPaginate(start: number): Promise<void> {
console.log(start);
var res = await rdrApi.search(this.searchTerm, this.activeFilterItems, start.toString());
this.results = res.response.docs;
}
async onFilter(filter): Promise<void> {
// console.log(filter.value);
// if (!this.activeFilterItems.some(e => e.value === filter.value)) {
// this.activeFilterItems.push(filter);
if (!this.activeFilterItems.hasOwnProperty(filter.Category)) {
this.activeFilterItems[filter.Category] = [];
}
if (!this.activeFilterItems[filter.Category].some(e => e === filter.value)) {
this.activeFilterItems[filter.Category].push(filter.value);
var res = await rdrApi.search(this.searchTerm, this.activeFilterItems);
this.results = res.response.docs;
this.numFound = res.response.numFound;
// pagination
this.pagination['total'] = res.response.numFound;
this.pagination['per_page'] = res.responseHeader.params.rows;
this.pagination['current_page'] = 1;
this.pagination['data'] = res.response.docs;
var facet_fields = res.facet_counts.facet_fields;
for (var prop in facet_fields) {
var facetValues = facet_fields[prop].map((facetValue, i) => {
if (i % 2 === 0) {
// var rObj = { value: facetValue, count: facet_fields[prop][i + 1] };
var rObj;
if (filter.value == facetValue) {
rObj = filter;
} else if (this.facets[prop].some(e => e.value === facetValue)) {
console.log(facetValue + " is included")
var indexOfFacetValue = this.facets[prop].findIndex(i => i.value === facetValue);
console.log(indexOfFacetValue);
rObj = this.facets[prop][indexOfFacetValue];
rObj.count = facet_fields[prop][i + 1];
} else {
rObj = new FilterItem(facetValue, facet_fields[prop][i + 1]);
}
return rObj;
}
}).filter(function (el) {
return el != null && el.count > 0;
});
// this.facets.push({ filterName: prop, values: facetValues });
this.facets[prop] = facetValues;
}
}
}
async onSearch(term): Promise<void> {
if (term){
term = term.trim();
} else {
term = "*%3A*";
}
this.activeFilterItems = {};
// while (this.facets.length > 0) {
// this.facets.pop();
// }
this.facets = {};
this.searchTerm = term;
var res = await rdrApi.search(this.searchTerm, this.activeFilterItems);
this.results = res.response.docs;
this.numFound = res.response.numFound;
// pagination
this.pagination['total'] = res.response.numFound;
this.pagination['per_page'] = res.responseHeader.params.rows;
this.pagination['current_page'] = 1;
this.pagination['data'] = res.response.docs;
// facets
var facet_fields = res.facet_counts.facet_fields;
for (var prop in facet_fields) {
var facetValues = facet_fields[prop].map((facet, i) => {
if (i % 2 === 0) {
//var rObj = { value: facet, count: facet_fields[prop][i + 1] };
var rObj = new FilterItem(facet, facet_fields[prop][i + 1])
return rObj;
}
}).filter(function (el) {
return el != null && el.count > 0;
});
//this.facets.push({ filterName: prop, values: facetValues });
this.facets[prop] = facetValues;
}
// console.log(this.facets.toString());
}
// When the window loads, read query parameters and perform search
async mounted() {
var query = this.getParameterByName("q");
if (query) query = query.trim();
await this.onSearch("*%3A*");
this.loaded = true;
}
getParameterByName(name: string, url?: string) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return "";
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
}

View file

@ -0,0 +1,7 @@
import Vue from 'vue';
import App from './App.vue';
new Vue({
el: '#test',
render: h => h(App)
});

View file

@ -0,0 +1,31 @@
export default class FilterItem {
private category: string;
value: string;
count: number;
private active: boolean;
constructor(value: string, count: number) {
this.value = value;
this.count = count;
this.active = false;
this.category = "";
}
//#region properties
get Category(): string {
return this.category;
}
set Category(theCategory: string) {
this.category = theCategory;
}
get Active(): boolean {
return this.active;
}
set Active(isActive: boolean) {
this.active = isActive;
}
//#endregion
}

View file

@ -0,0 +1,75 @@
import axios from "axios";
var SOLR_CONFIG = {
"server": "https://arcticdata.io/metacat/d1/mn/v2/query/solr?", // Solr server
"filter": "knb-lter-bnz", // Filter results for an organization or user
"limit": 4, // Max number of results to retrieve per page
"resultsElementId": "searchResults", // Element to contain results
"urlElementId": "searchUrl", // Element to display search URL
"countElementId": "resultCount", // Element showing number of results
"pagesElementId": "pagination", // Element to display result page links
"showPages": 5 // MUST BE ODD NUMBER! Max number of page links to show
};
export default {
async search(term: string, filterItems: Object, start?: string): Promise<any> {
// solr endpoint
// const host = 'http://voyagerdemo.com/';
const host = 'https://repository.geologie.ac.at/';
const path = 'solr/rdr_data/select?';
var base = host + path;
//const fields = 'id,server_date_published,abstract_output,title_output,title_additional,author,subject'; // fields we want returned
var fields = ["id",
"server_date_published",
"abstract_output",
"title_output",
"title_additional",
"author",
"subject"].toString();
var limit = "&rows=" + SOLR_CONFIG["limit"];
// var limit = solrConfig.limit;
var dismaxFields = "title^3 abstract^2 subject^1";
var params = "fl=" + fields;
if (term == "*%3A*") {
params += "&defType=edismax&wt=json&indent=on"; //edismax
} else {
params += "&defType=dismax&qf=" + dismaxFields + "&wt=json&indent=on"; //dismax
}
if (start === undefined) start = "0";
start = "&start=" + start;
const facetFields = "&facet=on&facet.field=language&facet.field={!key=datatype}doctype&facet.field=subject";//&fq=year:(2019)";//&facet.query=year:2018";
var filterFields = "";
// filterItems.forEach(function (item) {
// console.log(item.value + " " + item.category);
// filterFields += "&fq=" + item.category +":("+ item.value + ")";
// });
Object.entries(filterItems).forEach(([key, valueArray]) => {
// console.log(`${key} ${valueArray}`);
valueArray.forEach(function (value) {
filterFields += "&fq=" + key + ":(" + value + ")";
});
});
var query = "&q=" + term;
// $dismax->setQueryFields('title^3 abstract^2 subject^1');
//const api = `${host}${path}?defType=dismax&q=${term}&fl=${fields}&qf=${dismaxFields}&facet=on&${facetFields}&${filterFields}&wt=json&rows=20&indent=on`;
//const api = `${host}${path}?q=${term}&fl=${fields}&facet=on&${facetFields}&${filterFields}&wt=json&rows=20&indent=on`;
var api = base + params + limit + start + query + filterFields + facetFields;
let res = await axios.get(api);
// let { data } = res.data;
return res.data;//.response;//.docs;
}
}

View file

@ -0,0 +1,80 @@
import { Component, Vue, Prop, Provide } from 'vue-property-decorator';
import FilterItem from '../models/filter-item';
@Component
export default class FacetList extends Vue {
ITEMS_PER_FILTER = 2;
bar = '';
collapsed = true;
// filterItems = [];
@Prop()
data;
@Prop([String])
filterName;
// @Prop([String])
// alias;
get alias(): string {
return this.filterName == 'datatype' ? 'doctype' : this.filterName
}
// get filterItems() {
// var facetValues = this.data.map((facet, i) => {
// if (i % 2 === 0) {
// // var rObj = {};
// // rObj['value'] = facet;
// // rObj['count'] = solrArray[i +1];
// var rObj = { value: facet, count: this.data[i + 1], category: this.alias };
// return rObj;
// }
// }).filter(function (el) {
// return el != null && el.count > 0;
// });
// // var facetValues = this.data.language.filter(function(facet, i) {
// // return i % 2 === 0;
// // }).map(function (facet, i) {
// // var rObj = { value: facet, count: this.data.language[i + 1] };
// // return rObj;
// // }, this);
// return facetValues;
// }
get filterItems(): Array<FilterItem> {
return this.data;
}
get overflowing(): boolean {
//ko.observable(self.filterItems().length - self.activeFilterItems().length > ITEMS_PER_FILTER);
return (this.filterItems.length) > this.ITEMS_PER_FILTER;
}
get uncollapseLabelText() : string {
if (this.collapsed == true) {
// return myLabels.viewer.sidePanel.more; //"More results";
return "More results";
}
else {
// return myLabels.viewer.sidePanel.collapse; //"Collapse";
return "Collapse";
}
}
toggle = function (): void {
if (this.collapsed == true) {
this.collapsed = false;
}
else if (this.collapsed == false) {
this.collapsed = true;
//list.children("li:gt(4)").hide();
}
}
activateItem = function (filterItem: FilterItem): void {
filterItem.Category = this.alias;
filterItem.Active = true;
this.$emit("filter", filterItem);
}
mounted() {
}
}

View file

@ -0,0 +1,44 @@
<template>
<!-- <span>property: {{ filterName }}</span>
<span>value: {{ myLanguageFilters }}</span>-->
<div class="panel panel-primary">
<h3 class="panel-title filterViewModelName">{{ filterName }}</h3>
<!-- e.g.language -->
<ul class="filter-items" v-bind:class="{'limited':filterItems.length > 1 && collapsed }">
<li v-for="(item, index) in filterItems" :key="index" class="list-group-item">
<!-- <input
class="css-w1gpbi"
name="language"
v-bind:id="item.value"
type="radio"
v-bind:value="item.value"
/>
<label :for="item.value">
<span click: @click="activateItem(item)">{{ item.value }} ({{ item.count }})</span>
</label>-->
<a :class="item.Active ? 'disabled' : ''" @click.prevent="activateItem(item)">{{ item.value }} ({{ item.count }})</a>
</li>
</ul>
<ul class="overflowing" v-if="overflowing == true">
<li>
<span @click="toggle()">{{ uncollapseLabelText }}</span>
</li>
</ul>
</div>
</template>
<script lang="ts">
import FacetList from "./facet-list-class";
export default FacetList;
</script>
<style scoped>
/* local styles */
.disabled {
/* color: #EBEBE4; */
color:lightgray;
pointer-events: none;
text-decoration:line-through;
}
</style>

View file

@ -0,0 +1,50 @@
import { Vue, Component, Prop } from 'vue-property-decorator';
// import Vue from "vue";
@Component
export default class VsPagination extends Vue {
pageNumber: number = 0; // default to page 0
@Prop()
data;
@Prop({ default: 4 }) readonly offset: number;
changePage(page) {
if (page == this.data.current_page) {
return;
}
this.data.current_page = page;
let from = (page * this.data.per_page) - this.data.per_page;
this.$emit('paginate', from);
}
get numberOfPages() {
return Math.ceil(this.data.total / this.data.per_page);
}
get pages() {
let numberOfPages = Math.ceil(this.data.total / this.data.per_page);
// if (!this.data.to) {
// return [];
// }
let from = this.data.current_page - this.data.per_page;
if (from < 1) {
from = 1;
}
let to = from + (this.data.per_page * 2);
if (to >= numberOfPages) {
to = numberOfPages;
}
let pagesArray = [];
for (let page = from; page <= to; page++) {
pagesArray.push(page);
}
return pagesArray;
}
mounted() {
}
}

View file

@ -0,0 +1,278 @@
<template>
<nav v-if="pages.length > 1" class="pagination is-rounded is-medium" role="navigation" aria-label="pagination">
<ul class="pagination-list">
<!-- Previous Page Link -->
<li v-if="data.current_page > 1">
<a class="pagination-previous" href="javascript:void(0)" rel="prev" v-on:click.prevent="changePage(data.current_page - 1)">&laquo;</a>
</li>
<li v-else>
<a class="pagination-previous disabled" disabled href="javascript:void(0)" rel="prev">&laquo;</a>
</li>
<li v-for="(page, index) in pages" :key="index" >
<a href="javascript:void(0)" v-on:click.prevent="changePage(page)" v-bind:class="['pagination-link', page == data.current_page ? 'is-current' : '']">{{ page }}</a>
</li>
<!-- Previous Page Link -->
<li v-if="data.current_page < numberOfPages">
<a class="pagination-next" href="javascript:void(0)" v-on:click.prevent="changePage(data.current_page + 1)" rel="next">&raquo;</a>
</li>
<li v-else>
<a class="pagination-next disabled" disabled href="javascript:void(0)" rel="next">&raquo;</a>
</li>
</ul>
</nav>
</template>
<script lang="ts">
import VsPagination from "./vs-pagination-class";
export default VsPagination;
</script>
<style scoped>
/* local styles */
/* vom cms Pagination */
.pagination {
text-align: center;
margin: 80px 0 0 0;
clear: both;
}
.pagination a {
/*font-size:1.1em;*/
padding-left: 1em;
padding-right: 1em;
}
/* selbst Pagination */
.pagination-previous,
.pagination-next,
.pagination-link,
.pagination-dots {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-moz-appearance: none;
-webkit-appearance: none;
align-items: center;
border: 1px solid transparent;
border-radius: 4px;
box-shadow: none;
display: inline-flex;
/*display: inline-block;*/
font-size: 1rem;
height: 2.25em;
justify-content: flex-start;
line-height: 1.5;
padding: calc(0.375em - 1px) calc(0.625em - 1px) calc(0.375em - 1px)
calc(0.625em - 1px);
/*padding-top: calc(0.375em - 1px);
padding-right: calc(0.625em - 1px);
padding-bottom: calc(0.375em - 1px);
padding-left: calc(0.625em - 1px);*/
position: relative;
vertical-align: top;
}
.pagination-previous:focus,
.pagination-next:focus,
.pagination-link:focus,
.pagination-dots:focus,
.is-focused.pagination-next,
.is-focused.pagination-link,
.is-focused.pagination-dots,
.pagination-previous:active,
.pagination-next:active,
.pagination-link:active,
.pagination-dots:active,
.is-active.pagination-previous,
.is-active.pagination-next,
.is-active.pagination-link,
.is-active.pagination-dots {
outline: none;
}
.pagination-previous.disabled,
.pagination-next.disabled,
.pagination-link.disabled,
.pagination-dots.disabled {
cursor: not-allowed;
}
.pagination {
/*background-color:azure;*/
font-size: 1rem;
margin: -0.25rem;
}
.pagination.is-small {
font-size: 0.75rem;
}
.pagination.is-medium {
font-size: 1.25rem;
}
.pagination.is-large {
font-size: 1.5rem;
}
.pagination.is-rounded .pagination-previous,
.pagination.is-rounded .pagination-next {
padding-left: 1em;
padding-right: 1em;
border-radius: 290486px;
}
.pagination.is-rounded .pagination-link {
border-radius: 290486px;
}
/*.pagination,*/
.pagination-list {
align-items: center;
display: flex;
justify-content: center;
text-align: center;
list-style: none;
}
.pagination-previous,
.pagination-next,
.pagination-link,
.pagination-dots {
font-size: 1em;
padding-left: 0.5em;
padding-right: 0.5em;
justify-content: center;
margin: 0.25rem;
text-align: center;
}
.pagination-previous,
.pagination-next,
.pagination-link {
border-color: #dbdbdb;
color: #363636;
min-width: 2.25em;
}
.pagination-previous:hover,
.pagination-next:hover,
.pagination-link:hover {
border-color: #b5b5b5;
color: #363636;
}
.pagination-previous:focus,
.pagination-next:focus,
.pagination-link:focus {
border-color: #3273dc;
}
.pagination-previous:active,
.pagination-next:active,
.pagination-link:active {
box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2);
}
.pagination-previous.disabled,
.pagination-next.disabled,
.pagination-link.disabled {
background-color: #dbdbdb;
border-color: #dbdbdb;
box-shadow: none;
color: #7a7a7a;
opacity: 0.5;
}
.pagination-previous,
.pagination-next {
padding-left: 0.75em;
padding-right: 0.75em;
white-space: nowrap;
}
.pagination-link.is-current {
background-color: #3abac4; /*#3273dc;*/
border-color: #3abac4;
color: #fff;
}
.pagination-dots {
color: #b5b5b5;
pointer-events: none;
}
.pagination-list {
flex-wrap: wrap;
}
@media screen and (max-width: 767px) {
.pagination {
flex-wrap: wrap;
}
.pagination-previous,
.pagination-next {
flex-grow: 1;
flex-shrink: 1;
}
.pagination-list li {
flex-grow: 1;
flex-shrink: 1;
}
}
@media screen and (min-width: 768px), print {
.pagination-list {
flex-grow: 1;
flex-shrink: 1;
justify-content: center;
order: 1;
}
.pagination-previous {
order: 2;
}
.pagination-next {
order: 3;
}
.pagination {
justify-content: space-between;
}
.pagination.is-centered .pagination-previous {
order: 1;
}
.pagination.is-centered .pagination-list {
justify-content: center;
order: 2;
}
.pagination.is-centered .pagination-next {
order: 3;
}
.pagination.is-right .pagination-previous {
order: 1;
}
.pagination.is-right .pagination-next {
order: 2;
}
.pagination.is-right .pagination-list {
justify-content: flex-end;
order: 3;
}
}
</style>

View file

@ -0,0 +1,51 @@
import { Component, Vue, Prop, Provide } from 'vue-property-decorator';
@Component
export default class VsResults extends Vue {
@Prop()
data;
get results() {
return this.data;
};
truncate(text, limit) {
text = text === undefined ? '' : text;
const content = text.split(' ').slice(0, limit);
return content.join(' ');
};
error(item) {
delete item.thumb;
this.$forceUpdate();
};
convert(unixtimestamp: number) {
// Unixtimestamp
// var unixtimestamp = document.getElementById('timestamp').value;
// Months array
var months_arr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
// Convert timestamp to milliseconds
var date = new Date(unixtimestamp * 1000);
// Year
var year = date.getFullYear();
// Month
var month = months_arr[date.getMonth()];
// Day
var day = date.getDate();
// Hours
var hours = date.getHours();
// Minutes
var minutes = "0" + date.getMinutes();
// Seconds
var seconds = "0" + date.getSeconds();
// Display date time in MM-dd-yyyy h:m:s format
var convdataTime = month + '-' + day + '-' + year + ' ' + hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
// document.getElementById('datetime').innerHTML = convdataTime;
return convdataTime;
};
}

View file

@ -0,0 +1,63 @@
<template>
<!-- <div class="card-columns" >
<div class="card" v-for="item in results" :key="item.id">
<img v-if="item.thumb" class="card-img-top" :src="item.thumb" :alt="item.title" @error="error(item)">
<div class="card-body">
<h5 class="card-title">{{item.name}}</h5>
<p class="card-text" v-html="truncate(item.description || item.abstract, 50)"></p>
</div>
</div>
</div>-->
<div class="results">
<!-- <div class="result-list-info">
<div class="resultheader">
Your search yielded
<strong>{{ results.length }}</strong> results:
</div>
</div> -->
<section class="result-list-container">
<div class="row">
<ul class="search-items isotope js-isotope u-cf">
<li v-for="document in results" :key="document.id" class="six columns post">
<div class="search-detail">
<div>
<a
v-bind:href="'dataset/' + document.id"
>{{ document.title_output }}</a>
</div>
{{ convert(document.server_date_published) }}
<p v-if="document.title_additional && document.title_additional.length > 0">
<em>Additional Title:{{ document.title_additional.join(', ') }}</em>
</p>
<div v-if="document.author && document.author.length > 0">
<em>Author: {{ document.author.join(', ') }}</em>
</div>
<p class="clamped clamped-2">
<span class="text">
Abstract: {{ document.abstract_output }}
<span class="ellipsis">...</span>
<span class="fill"></span>
</span>
</p>
<div class="css-subject" v-if="document.subject && document.subject.length > 0">
<div v-for="(item, index) in document.subject" :key="index" class="css-keyword">#{{ item }}</div>
<!-- <div class="css-keyword">#graphql</div> -->
</div>
</div>
</li>
</ul>
</div>
</section>
</div>
</template>
<script lang="ts">
import VgResults from "./vs-results-class";
export default VgResults;
</script>

View file

@ -0,0 +1,47 @@
<template>
<div class="sidebar-simplesearch">
<!-- <form method="GET" action="//repository.geologie.ac.at/search" accept-charset="UTF-8"> -->
<div>
<input
class="search-input"
placeholder="Enter your search term..."
name="q"
type="text"
v-model="term" v-on:keyup.enter="search()"
/>
<!-- <button @click="search()" class="css-1gklxk5 ekqohx90"> -->
<button class="css-1gklxk5 ekqohx90">
<svg
alt="Search"
@click="search()"
class="search-icon"
height="14"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 15 15"
>
<title>Search</title>
<path
d=" M6.02945,10.20327a4.17382,4.17382,0,1,1,4.17382-4.17382A4.15609,4.15609, 0,0,1,6.02945,10.20327Zm9.69195,4.2199L10.8989,9.59979A5.88021,5.88021, 0,0,0,12.058,6.02856,6.00467,6.00467,0,1,0,9.59979,10.8989l4.82338, 4.82338a.89729.89729,0,0,0,1.29912,0,.89749.89749,0,0,0-.00087-1.29909Z "
/>
</svg>
</button>
</div>
</div>
</template>
<script lange="ts">
import Vue from "vue";
import { Component, Provide } from "vue-property-decorator";
@Component({})
export default class VsInput extends Vue {
term = "";
bar = "bar";
search() {
//console.log(this.term);
this.$emit("search", this.term);
}
}
</script>

View file

@ -0,0 +1,4 @@
const messages={
min_value: (field, num) => field +' cannot be empty! ' + num + ' items are required.',
};
export default messages;

View file

@ -0,0 +1,3 @@
import TinyDatePicker from 'tiny-date-picker';
TinyDatePicker(document.querySelector("input[name='time_absolut']"));

4
resources/js/typings.d.ts vendored Normal file
View file

@ -0,0 +1,4 @@
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}