forked from geolba/tethys.backend
- add FileUpload vue component
This commit is contained in:
parent
e051a94b3b
commit
f76a92da2c
|
@ -306,8 +306,6 @@ export default class DatasetController {
|
|||
// fieldName: 'file'
|
||||
// size: 135624
|
||||
|
||||
coverImage.fileName = 'test'; //request.input('upload.label');
|
||||
|
||||
//const datasetFolder = 'files/' . dataset->id;
|
||||
|
||||
// await coverImage.moveToDisk('./')
|
||||
|
|
|
@ -38,9 +38,9 @@ body {
|
|||
/* padding-right: 1.5rem; */
|
||||
}
|
||||
|
||||
.rounded-md {
|
||||
/* .rounded-md {
|
||||
color: gray;
|
||||
}
|
||||
} */
|
||||
|
||||
/* body:before {
|
||||
content: '';
|
||||
|
|
319
resources/js/Components/FileUpload.vue
Normal file
319
resources/js/Components/FileUpload.vue
Normal file
|
@ -0,0 +1,319 @@
|
|||
<template>
|
||||
<div
|
||||
aria-label="File Upload Modal"
|
||||
class="relative h-full flex flex-col bg-white shadow-xl rounded-md"
|
||||
v-on:dragenter="dragEnterHandler"
|
||||
v-on:dragleave="dragLeaveHandler"
|
||||
v-on:dragover="dragOverHandler"
|
||||
v-on:drop="dropHandler"
|
||||
>
|
||||
<!-- ondrop="dropHandler(event);"
|
||||
ondragover="dragOverHandler(event);"
|
||||
ondragleave="dragLeaveHandler(event);"
|
||||
ondragenter="dragEnterHandler(event);" -->
|
||||
|
||||
<!-- overlay -->
|
||||
<div
|
||||
id="overlay"
|
||||
ref="overlay"
|
||||
class="w-full h-full absolute top-0 left-0 pointer-events-none z-50 flex flex-col items-center justify-center rounded-md"
|
||||
>
|
||||
<i>
|
||||
<svg
|
||||
class="fill-current w-12 h-12 mb-3 text-blue-700"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
d="M19.479 10.092c-.212-3.951-3.473-7.092-7.479-7.092-4.005 0-7.267 3.141-7.479 7.092-2.57.463-4.521 2.706-4.521 5.408 0 3.037 2.463 5.5 5.5 5.5h13c3.037 0 5.5-2.463 5.5-5.5 0-2.702-1.951-4.945-4.521-5.408zm-7.479-1.092l4 4h-3v4h-2v-4h-3l4-4z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<p class="text-lg text-blue-700">Drop files to upload</p>
|
||||
</div>
|
||||
|
||||
<!-- scroll area -->
|
||||
<div class="h-full overflow-auto p-8 w-full h-full flex flex-col">
|
||||
<!-- <header id="dropzone" class="border-dashed border-2 border-gray-400 py-12 flex flex-col justify-center items-center">
|
||||
<p class="mb-3 font-semibold text-gray-900 flex flex-wrap justify-center">
|
||||
<span>Drag and drop your</span> <span>files anywhere or</span>
|
||||
</p>
|
||||
<input id="hidden-input" type="file" multiple class="hidden" />
|
||||
<button id="button" class="mt-2 rounded-sm px-3 py-1 bg-gray-200 hover:bg-gray-300 focus:shadow-outline focus:outline-none">
|
||||
Upload a file
|
||||
</button>
|
||||
</header> -->
|
||||
<header class="flex items-center justify-center w-full">
|
||||
<label
|
||||
for="dropzone-file"
|
||||
class="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:bg-teal-50 dark:hover:bg-bray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600"
|
||||
>
|
||||
<div class="flex flex-col items-center justify-center pt-5 pb-6">
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="w-10 h-10 mb-3 text-gray-400"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
|
||||
></path>
|
||||
</svg>
|
||||
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
<span class="font-semibold">Click to upload</span> or drag and drop
|
||||
</p>
|
||||
<!-- <p class="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF (MAX. 800x400px)</p> -->
|
||||
</div>
|
||||
<!-- <input id="dropzone-file" type="file" class="hidden" @change="onChangeFile" /> -->
|
||||
</label>
|
||||
</header>
|
||||
|
||||
<h1 class="pt-8 pb-3 font-semibold sm:text-lg text-gray-900">To Upload</h1>
|
||||
|
||||
<ul id="gallery" class="flex flex-1 flex-wrap -m-1">
|
||||
<li
|
||||
v-if="files.length == 0"
|
||||
id="empty"
|
||||
class="h-full w-full text-center flex flex-col items-center justify-center items-center"
|
||||
>
|
||||
<svg
|
||||
class="w-20 h-20 mb-3 text-gray-400"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 412.533 412.533"
|
||||
xml:space="preserve"
|
||||
fill="#000000"
|
||||
>
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
|
||||
<g id="SVGRepo_iconCarrier">
|
||||
<g>
|
||||
<path
|
||||
style="fill: #010002"
|
||||
d="M412.485,203.954h0.041c0-14.323-5.609-27.336-14.729-37.042l0.016-0.016l-79.27-101.819H90.479 L13.493,168.961l0.033,0.033c-7.283,8.616-11.762,19.565-12.534,31.514C0.415,201.629,0,202.84,0,204.19v135.138 c0,4.495,3.642,8.129,8.129,8.129h396.276c4.495,0,8.129-3.633,8.129-8.129V204.19 C412.533,204.109,412.485,204.035,412.485,203.954z M97.844,81.335H311.43l48.389,68.5c-0.512-0.016-1-0.081-1.52-0.081h-97.502 v24.369c0,27.67-29.052,21.687-37.96,21.687h-32.466c-8.909,0-37.96,5.983-37.96-21.687v-24.369H54.9 c-1.016,0-2.008,0.098-3.016,0.146L97.844,81.335z M396.276,331.199H16.265V204.19c0-0.081-0.041-0.154-0.049-0.236h0.723 c0-20.923,17.029-37.944,37.96-37.944h81.253v8.112c0,27.987,21.281,37.944,54.218,37.944h32.466 c32.945,0,54.218-9.957,54.218-37.944v-8.112h81.261c10.461,0,19.948,4.251,26.824,11.12l0.016,0.016 c6.869,6.869,11.112,16.347,11.112,26.808h0.057c0,0.081-0.049,0.154-0.049,0.236C396.276,204.19,396.276,331.199,396.276,331.199z "
|
||||
></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<span class="text-small text-gray-500">No files selected</span>
|
||||
</li>
|
||||
<li v-for="(file, index) in files" :key="index" class="block p-1 w-1/2 sm:w-1/3 md:w-1/4 lg:w-1/6 xl:w-1/8 h-24">
|
||||
<article
|
||||
v-if="file.type.match('image.*')"
|
||||
tabindex="0"
|
||||
class="group hasImage w-full h-full rounded-md bg-gray-100 cursor-pointer relative text-transparent hover:text-white shadow-sm"
|
||||
>
|
||||
<img
|
||||
:alt="file.name"
|
||||
:src="generateURL(file)"
|
||||
class="img-preview w-full h-full sticky object-cover rounded-md bg-fixed"
|
||||
/>
|
||||
<section class="flex flex-col rounded-md text-xs break-words w-full h-full z-20 absolute top-0 py-2 px-3">
|
||||
<h1 class="flex-1">{{ file.name }}</h1>
|
||||
<div class="flex">
|
||||
<p class="p-1 size text-xs">{{ getFileSize(file) }}</p>
|
||||
<button
|
||||
class="delete ml-auto focus:outline-none hover:bg-gray-300 p-1 rounded-md"
|
||||
@click="removeFile(index)"
|
||||
>
|
||||
<svg
|
||||
class="pointer-events-none fill-current w-4 h-4 ml-auto"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
class="pointer-events-none"
|
||||
d="M3 6l3 18h12l3-18h-18zm19-4v2h-20v-2h5.711c.9 0 1.631-1.099 1.631-2h5.316c0 .901.73 2 1.631 2h5.711z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
<article v-else tabindex="0" class="group w-full h-full rounded-md bg-gray-100 cursor-pointer relative shadow-sm">
|
||||
<section class="flex flex-col rounded-md text-xs break-words w-full h-full z-20 absolute top-0 py-2 px-3">
|
||||
<h1 class="flex-1 group-hover:text-blue-800">{{ file.name }}</h1>
|
||||
<div class="flex">
|
||||
<p class="p-1 size text-xs text-gray-700">{{ getFileSize(file) }}</p>
|
||||
<button
|
||||
class="delete ml-auto focus:outline-none hover:bg-gray-300 p-1 rounded-md text-gray-800"
|
||||
@click="removeFile(index)"
|
||||
>
|
||||
<svg
|
||||
class="pointer-events-none fill-current w-4 h-4 ml-auto"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
class="pointer-events-none"
|
||||
d="M3 6l3 18h12l3-18h-18zm19-4v2h-20v-2h5.711c.9 0 1.631-1.099 1.631-2h5.316c0 .901.73 2 1.631 2h5.711z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- sticky footer -->
|
||||
<footer class="flex justify-end px-8 pb-8 pt-4">
|
||||
<button
|
||||
id="cancel"
|
||||
class="ml-3 rounded-sm px-3 py-1 hover:bg-gray-300 focus:shadow-outline focus:outline-none"
|
||||
@click="clearAllFiles"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Prop, Ref } from 'vue-facing-decorator';
|
||||
import BaseButton from './BaseButton.vue';
|
||||
// import { mdiPlus, mdiMinus } from '@mdi/js';
|
||||
import { mdiTrashCan } from '@mdi/js';
|
||||
|
||||
@Component({
|
||||
name: 'file-upload',
|
||||
components: {
|
||||
BaseButton,
|
||||
mdiTrashCan,
|
||||
},
|
||||
})
|
||||
export default class FileUploadComponent extends Vue {
|
||||
// mdiPlus = mdiPlus;
|
||||
// mdiMinus = mdiMinus;
|
||||
|
||||
/**
|
||||
* Connect map id.
|
||||
*/
|
||||
@Prop() public mapId: string;
|
||||
|
||||
@Ref('overlay') overlay: HTMLDivElement;
|
||||
|
||||
private counter: number = 0;
|
||||
files: Array<File> = [];
|
||||
// mdiTrashCan = mdiTrashCan;
|
||||
|
||||
dragEnterHandler(e) {
|
||||
e.preventDefault();
|
||||
if (!this._hasFiles(e.dataTransfer)) {
|
||||
return;
|
||||
}
|
||||
++this.counter && this.overlay.classList.add('draggedover');
|
||||
}
|
||||
|
||||
dragLeaveHandler() {
|
||||
1 > --this.counter && this.overlay.classList.remove('draggedover');
|
||||
}
|
||||
|
||||
dragOverHandler(e) {
|
||||
if (this._hasFiles(e.dataTransfer)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
startDrag(evt, item) {
|
||||
evt.dataTransfer.dropEffect = 'move';
|
||||
evt.dataTransfer.effectAllowed = 'move';
|
||||
evt.dataTransfer.setData('itemID', item.id);
|
||||
}
|
||||
|
||||
// reset counter and append file to gallery when file is dropped
|
||||
|
||||
dropHandler(event) {
|
||||
event.preventDefault();
|
||||
for (const file of event.dataTransfer.files) {
|
||||
this._addFile(file);
|
||||
}
|
||||
this.overlay.classList.remove('draggedover');
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
clearAllFiles(event) {
|
||||
event.preventDefault();
|
||||
this.files.splice(0);
|
||||
}
|
||||
|
||||
removeFile(key) {
|
||||
this.files.splice(key, 1);
|
||||
}
|
||||
|
||||
// check if file is of type image and prepend the initialied
|
||||
// template to the target element
|
||||
private _addFile(file) {
|
||||
// const isImage = file.type.match('image.*');
|
||||
// const objectURL = URL.createObjectURL(file);
|
||||
|
||||
// this.files[objectURL] = file;
|
||||
this.files.push(file);
|
||||
}
|
||||
|
||||
generateURL(file) {
|
||||
let fileSrc = URL.createObjectURL(file);
|
||||
setTimeout(() => {
|
||||
URL.revokeObjectURL(fileSrc);
|
||||
}, 1000);
|
||||
return fileSrc;
|
||||
}
|
||||
|
||||
getFileSize(file) {
|
||||
if (file.size > 1024) {
|
||||
if (file.size > 1048576) {
|
||||
return Math.round(file.size / 1048576) + 'mb';
|
||||
} else {
|
||||
return Math.round(file.size / 1024) + 'kb';
|
||||
}
|
||||
} else {
|
||||
return file.size + 'b';
|
||||
}
|
||||
}
|
||||
|
||||
// use to check if a file is being dragged
|
||||
private _hasFiles({ types = [] as Array<string> }) {
|
||||
return types.indexOf('Files') > -1;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="css">
|
||||
.hasImage:hover section {
|
||||
background-color: rgba(5, 5, 5, 0.4);
|
||||
}
|
||||
.hasImage:hover button:hover {
|
||||
background: rgba(5, 5, 5, 0.45);
|
||||
}
|
||||
|
||||
#overlay p,
|
||||
i {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#overlay.draggedover {
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
#overlay.draggedover p,
|
||||
#overlay.draggedover i {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.group:hover .group-hover\:text-blue-800 {
|
||||
color: #2b6cb0;
|
||||
}
|
||||
</style>
|
|
@ -12,6 +12,7 @@ import {
|
|||
mdiBookOpenPageVariant,
|
||||
mdiImageText,
|
||||
mdiEarthPlus,
|
||||
mdiAlertBoxOutline
|
||||
} from '@mdi/js';
|
||||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||
import SectionMain from '@/Components/SectionMain.vue';
|
||||
|
@ -43,6 +44,7 @@ import { LatLngBoundsExpression } from 'leaflet/src/geo/LatLngBounds';
|
|||
import { LayerOptions } from '@/Components/Map/LayerOptions';
|
||||
import TableKeywords from '@/Components/TableKeywords.vue';
|
||||
import NotificationBar from '@/Components/NotificationBar.vue';
|
||||
import FileUploadComponent from '@/Components/FileUpload.vue';
|
||||
|
||||
const props = defineProps({
|
||||
licenses: {
|
||||
|
@ -215,7 +217,7 @@ watch(depth, (currentValue) => {
|
|||
// let time= "no_time";
|
||||
|
||||
const isModalActive = ref(false);
|
||||
const formStep = ref(1);
|
||||
const formStep = ref(4);
|
||||
|
||||
const mapOptions: MapOptions = {
|
||||
center: [48.208174, 16.373819],
|
||||
|
@ -1101,17 +1103,19 @@ const onChangeFile = (event) => {
|
|||
</div>
|
||||
|
||||
<div v-if="formStep == 4">
|
||||
<div class="dropbox">
|
||||
<!-- <progress v-if="form.progress" :value="form.progress.percentage" max="100">
|
||||
{{ form.progress.percentage }}%
|
||||
</progress> -->
|
||||
<!-- <p v-if="isSaving">Uploading @{{ fileCount }} files...</p> -->
|
||||
<!-- <div class="dropbox">
|
||||
<input type="file" multiple name="files" @change="onChangeFile" class="input-file" />
|
||||
<p>
|
||||
Drag your file(s) here to begin<br />
|
||||
or click to browse
|
||||
</p>
|
||||
<!-- <progress v-if="form.progress" :value="form.progress.percentage" max="100">
|
||||
{{ form.progress.percentage }}%
|
||||
</progress> -->
|
||||
<!-- <p v-if="isSaving">Uploading @{{ fileCount }} files...</p> -->
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<FileUploadComponent></FileUploadComponent>
|
||||
|
||||
<div class="text-red-400 text-sm" v-if="form.errors['file'] && Array.isArray(form.errors['file'])">
|
||||
{{ form.errors['file'].join(', ') }}
|
||||
|
@ -1119,7 +1123,7 @@ const onChangeFile = (event) => {
|
|||
<div class="text-red-400 text-sm" v-if="form.errors['upload.label'] && Array.isArray(form.errors['upload.label'])">
|
||||
{{ form.errors['upload.label'].join(', ') }}
|
||||
</div>
|
||||
<label v-if="form.upload">{{ form.upload?.label }}</label>
|
||||
<!-- <label v-if="form.upload">{{ form.upload?.label }}</label> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user