2021-05-21 00:43:02 +02:00
|
|
|
"New Game" page: Upload button big, centered, at the top of the page, as
|
|
|
|
|
visible as possible. Upload button has a warning that the image will
|
|
|
|
|
be added to public gallery, just so noone uploads anything naughty on
|
|
|
|
|
accident. The page can show all the images by default, or one of the categories
|
|
|
|
|
of images. Instead of categories, you can make the system tag-based, like
|
|
|
|
|
in jigsawpuzzles.io
|
|
|
|
|
|
2021-05-17 00:27:47 +02:00
|
|
|
<template>
|
|
|
|
|
<div>
|
2021-05-21 00:43:02 +02:00
|
|
|
<div class="upload-image-teaser">
|
|
|
|
|
<div class="btn btn-big" @click="dialog='new-image'">Upload your image</div>
|
|
|
|
|
<div class="hint">(The image you upload will be added to the public gallery.)</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<label v-if="categories.length > 0">
|
|
|
|
|
Category:
|
|
|
|
|
<select v-model="filters.category" @change="filtersChanged">
|
|
|
|
|
<option value="">All</option>
|
2021-05-22 01:51:44 +02:00
|
|
|
<option v-for="(c, idx) in categories" :key="idx" :value="c.slug">{{c.title}}</option>
|
2021-05-21 00:43:02 +02:00
|
|
|
</select>
|
|
|
|
|
</label>
|
|
|
|
|
<label>
|
|
|
|
|
Sort by:
|
|
|
|
|
<select v-model="filters.sort" @change="filtersChanged">
|
|
|
|
|
<option value="date_desc">Newest first</option>
|
|
|
|
|
<option value="date_asc">Oldest first</option>
|
|
|
|
|
<option value="alpha_asc">A-Z</option>
|
|
|
|
|
<option value="alpha_desc">Z-A</option>
|
|
|
|
|
</select>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
2021-05-22 01:51:44 +02:00
|
|
|
<image-library :images="images" @imageClicked="imageClicked" />
|
|
|
|
|
<new-image-dialog v-if="dialog==='new-image'" @bgclick="dialog=''" @postToGalleryClick="postToGalleryClick" @setupGameClick="setupGameClick" />
|
2021-05-21 00:43:02 +02:00
|
|
|
<new-game-dialog v-if="image && dialog==='new-game'" @bgclick="dialog=''" @newGame="onNewGame" :image="image" />
|
2021-05-17 00:27:47 +02:00
|
|
|
</div>
|
|
|
|
|
</template>
|
2021-05-13 16:58:21 +02:00
|
|
|
|
2021-05-17 00:27:47 +02:00
|
|
|
<script lang="ts">
|
|
|
|
|
import { defineComponent } from 'vue'
|
2021-05-13 16:58:21 +02:00
|
|
|
|
2021-05-21 00:43:02 +02:00
|
|
|
import ImageLibrary from './../components/ImageLibrary.vue'
|
|
|
|
|
import NewImageDialog from './../components/NewImageDialog.vue'
|
2021-05-17 00:27:47 +02:00
|
|
|
import NewGameDialog from './../components/NewGameDialog.vue'
|
2021-05-21 00:43:02 +02:00
|
|
|
import { GameSettings, Image } from '../../common/GameCommon'
|
|
|
|
|
import Util from '../../common/Util'
|
2021-05-17 00:27:47 +02:00
|
|
|
|
|
|
|
|
export default defineComponent({
|
2021-05-13 16:58:21 +02:00
|
|
|
components: {
|
2021-05-21 00:43:02 +02:00
|
|
|
ImageLibrary,
|
|
|
|
|
NewImageDialog,
|
2021-05-13 16:58:21 +02:00
|
|
|
NewGameDialog,
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
2021-05-21 00:43:02 +02:00
|
|
|
filters: {
|
|
|
|
|
sort: 'date_desc',
|
|
|
|
|
category: '',
|
|
|
|
|
},
|
2021-05-13 16:58:21 +02:00
|
|
|
images: [],
|
2021-05-21 00:43:02 +02:00
|
|
|
categories: [],
|
|
|
|
|
|
|
|
|
|
image: {
|
2021-05-22 01:51:44 +02:00
|
|
|
id: 0,
|
|
|
|
|
filename: '',
|
2021-05-21 00:43:02 +02:00
|
|
|
file: '',
|
2021-05-22 01:51:44 +02:00
|
|
|
url: '',
|
2021-05-21 00:43:02 +02:00
|
|
|
title: '',
|
2021-05-22 01:51:44 +02:00
|
|
|
categories: [],
|
|
|
|
|
created: 0,
|
2021-05-21 00:43:02 +02:00
|
|
|
} as Image,
|
|
|
|
|
|
|
|
|
|
dialog: '',
|
2021-05-13 16:58:21 +02:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async created() {
|
2021-05-21 00:43:02 +02:00
|
|
|
await this.loadImages()
|
2021-05-13 16:58:21 +02:00
|
|
|
},
|
|
|
|
|
methods: {
|
2021-05-21 00:43:02 +02:00
|
|
|
async loadImages () {
|
|
|
|
|
const res = await fetch(`/api/newgame-data${Util.asQueryArgs(this.filters)}`)
|
|
|
|
|
const json = await res.json()
|
|
|
|
|
this.images = json.images
|
|
|
|
|
this.categories = json.categories
|
|
|
|
|
},
|
|
|
|
|
async filtersChanged () {
|
|
|
|
|
await this.loadImages()
|
|
|
|
|
},
|
|
|
|
|
imageClicked (image: Image) {
|
|
|
|
|
this.image = image
|
|
|
|
|
this.dialog = 'new-game'
|
|
|
|
|
},
|
2021-05-22 01:51:44 +02:00
|
|
|
async uploadImage (data: any) {
|
|
|
|
|
const formData = new FormData();
|
|
|
|
|
formData.append('file', data.file, data.file.name);
|
|
|
|
|
formData.append('title', data.title)
|
|
|
|
|
formData.append('category', data.category)
|
|
|
|
|
|
|
|
|
|
const res = await fetch('/upload', {
|
|
|
|
|
method: 'post',
|
|
|
|
|
body: formData,
|
|
|
|
|
})
|
|
|
|
|
return await res.json()
|
|
|
|
|
},
|
|
|
|
|
async postToGalleryClick(data: any) {
|
|
|
|
|
await this.uploadImage(data)
|
|
|
|
|
this.dialog = ''
|
|
|
|
|
await this.loadImages()
|
|
|
|
|
},
|
|
|
|
|
async setupGameClick (data: any) {
|
|
|
|
|
const image = await this.uploadImage(data)
|
|
|
|
|
this.loadImages() // load images in background
|
2021-05-21 00:43:02 +02:00
|
|
|
this.image = image
|
|
|
|
|
this.dialog = 'new-game'
|
|
|
|
|
},
|
|
|
|
|
async onNewGame(gameSettings: GameSettings) {
|
2021-05-13 16:58:21 +02:00
|
|
|
const res = await fetch('/newgame', {
|
|
|
|
|
method: 'post',
|
|
|
|
|
headers: {
|
|
|
|
|
'Accept': 'application/json',
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify(gameSettings),
|
|
|
|
|
})
|
|
|
|
|
if (res.status === 200) {
|
|
|
|
|
const game = await res.json()
|
2021-05-15 11:06:37 +02:00
|
|
|
this.$router.push({ name: 'game', params: { id: game.id } })
|
2021-05-13 16:58:21 +02:00
|
|
|
}
|
2021-05-21 00:43:02 +02:00
|
|
|
},
|
|
|
|
|
},
|
2021-05-17 00:27:47 +02:00
|
|
|
})
|
|
|
|
|
</script>
|