allow upload image by drag/drop

This commit is contained in:
Zutatensuppe 2021-06-05 09:54:01 +02:00
parent 95a06972c7
commit 3ce631d722
6 changed files with 85 additions and 8 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -4,9 +4,9 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>🧩 jigsaw.hyottoko.club</title> <title>🧩 jigsaw.hyottoko.club</title>
<script type="module" crossorigin src="/assets/index.ea488403.js"></script> <script type="module" crossorigin src="/assets/index.bc3449de.js"></script>
<link rel="modulepreload" href="/assets/vendor.684f7bc8.js"> <link rel="modulepreload" href="/assets/vendor.684f7bc8.js">
<link rel="stylesheet" href="/assets/index.6748df9f.css"> <link rel="stylesheet" href="/assets/index.53fc6304.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View file

@ -132,6 +132,16 @@ export default defineComponent({
height: 90%; height: 90%;
width: 80%; width: 80%;
} }
@media (max-width: 1400px) {
.new-game-dialog .overlay-content {
grid-template-columns: auto;
grid-template-rows: 1fr min-content min-content;
grid-template-areas:
"image"
"settings"
"buttons";
}
}
.new-game-dialog .area-image { .new-game-dialog .area-image {
grid-area: image; grid-area: image;
margin: 20px; margin: 20px;

View file

@ -7,7 +7,12 @@ gallery", if possible!
<div class="overlay new-image-dialog" @click="$emit('bgclick')"> <div class="overlay new-image-dialog" @click="$emit('bgclick')">
<div class="overlay-content" @click.stop=""> <div class="overlay-content" @click.stop="">
<div class="area-image" :class="{'has-image': !!previewUrl, 'no-image': !previewUrl}"> <div
class="area-image"
:class="{'has-image': !!previewUrl, 'no-image': !previewUrl, droppable: droppable}"
@drop="onDrop"
@dragover="onDragover"
@dragleave="onDragleave">
<!-- TODO: ... --> <!-- TODO: ... -->
<div v-if="previewUrl" class="has-image"> <div v-if="previewUrl" class="has-image">
<span class="remove btn" @click="previewUrl=''">X</span> <span class="remove btn" @click="previewUrl=''">X</span>
@ -15,7 +20,7 @@ gallery", if possible!
</div> </div>
<div v-else> <div v-else>
<label class="upload"> <label class="upload">
<input type="file" style="display: none" @change="preview" accept="image/*" /> <input type="file" style="display: none" @change="onFileSelect" accept="image/*" />
<span class="btn">Upload File</span> <span class="btn">Upload File</span>
</label> </label>
</div> </div>
@ -52,10 +57,13 @@ gallery", if possible!
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
import { logger } from '../../common/Util'
import ResponsiveImage from './ResponsiveImage.vue' import ResponsiveImage from './ResponsiveImage.vue'
import TagsInput from './TagsInput.vue' import TagsInput from './TagsInput.vue'
const log = logger('NewImageDialog.vue')
export default defineComponent({ export default defineComponent({
name: 'new-image-dialog', name: 'new-image-dialog',
components: { components: {
@ -78,6 +86,7 @@ export default defineComponent({
file: null as File|null, file: null as File|null,
title: '', title: '',
tags: [] as string[], tags: [] as string[],
droppable: false,
} }
}, },
computed: { computed: {
@ -89,12 +98,26 @@ export default defineComponent({
}, },
}, },
methods: { methods: {
preview (evt: Event) { imageFromDragEvt (evt: DragEvent): DataTransferItem|null {
const items = evt.dataTransfer?.items
if (!items || items.length === 0) {
return null
}
const item = items[0]
if (!item.type.startsWith('image/')) {
return null
}
return item
},
onFileSelect (evt: Event) {
const target = (evt.target as HTMLInputElement) const target = (evt.target as HTMLInputElement)
if (!target.files) return; if (!target.files) return;
const file = target.files[0] const file = target.files[0]
if (!file) return; if (!file) return;
this.preview(file)
},
preview (file: File) {
const r = new FileReader() const r = new FileReader()
r.readAsDataURL(file) r.readAsDataURL(file)
r.onload = (ev: any) => { r.onload = (ev: any) => {
@ -116,6 +139,34 @@ export default defineComponent({
tags: this.tags, tags: this.tags,
}) })
}, },
onDrop (evt: DragEvent): boolean {
this.droppable = false
const img = this.imageFromDragEvt(evt)
if (!img) {
return false
}
const f = img.getAsFile()
if (!f) {
return false
}
this.file = f
this.preview(f)
evt.preventDefault()
return false
},
onDragover (evt: DragEvent): boolean {
const img = this.imageFromDragEvt(evt)
if (!img) {
return false
}
this.droppable = true
evt.preventDefault()
return false
},
onDragleave () {
log.info('onDragleave')
this.droppable = false
},
}, },
}) })
</script> </script>
@ -132,6 +183,16 @@ export default defineComponent({
height: 90%; height: 90%;
width: 80%; width: 80%;
} }
@media (max-width: 1400px) {
.new-image-dialog .overlay-content {
grid-template-columns: auto;
grid-template-rows: 1fr min-content min-content;
grid-template-areas:
"image"
"settings"
"buttons";
}
}
.new-image-dialog .area-image { .new-image-dialog .area-image {
grid-area: image; grid-area: image;
@ -141,9 +202,15 @@ export default defineComponent({
align-content: center; align-content: center;
display: grid; display: grid;
text-align: center; text-align: center;
border: dashed 6px; border: solid 6px;
position: relative; position: relative;
} }
.new-image-dialog .area-image.droppable {
border: dashed 6px;
}
.area-image * {
pointer-events: none;
}
.new-image-dialog .area-image .has-image { .new-image-dialog .area-image .has-image {
position: relative; position: relative;
width: 100%; width: 100%;