change categories to tags in frontend

This commit is contained in:
Zutatensuppe 2021-05-22 15:48:13 +02:00
parent 92ed17efa5
commit 5be099c61c
16 changed files with 196 additions and 112 deletions

View file

@ -20,9 +20,11 @@
</td>
</tr>
<tr>
<!-- TODO: autocomplete category -->
<td><label>Category</label></td>
<td><input type="text" v-model="category" placeholder="Plants" /></td>
<!-- TODO: autocomplete tags -->
<td><label>Tags</label></td>
<td>
<tags-input v-model="tags" />
</td>
</tr>
</table>
</div>
@ -36,14 +38,16 @@
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue'
import { Image } from '../../common/GameCommon'
import { Image, Tag } from '../../common/GameCommon'
import ResponsiveImage from './ResponsiveImage.vue'
import TagsInput from './TagsInput.vue'
export default defineComponent({
name: 'edit-image-dialog',
components: {
ResponsiveImage,
TagsInput,
},
props: {
image: {
@ -58,19 +62,19 @@ export default defineComponent({
data () {
return {
title: '',
category: '',
tags: [] as string[],
}
},
created () {
this.title = this.image.title
this.category = this.image.categories.length > 0 ? this.image.categories[0].title : ''
this.tags = this.image.tags.map((t: Tag) => t.title)
},
methods: {
saveImage () {
this.$emit('saveClick', {
id: this.image.id,
title: this.title,
category: this.category,
tags: this.tags,
})
},
},

View file

@ -16,12 +16,8 @@ gallery", if possible!
<div v-else>
<label class="upload">
<input type="file" style="display: none" @change="preview" accept="image/*" />
<span class="btn">{{label || 'Upload File'}}</span>
<span class="btn">Upload File</span>
</label>
<!-- TODO: drop area for image -->
<!-- <upload class="upload" @uploaded="mediaImgUploaded($event)" accept="image/*" label="Upload an image" /> -->
</div>
</div>
@ -37,9 +33,11 @@ gallery", if possible!
</td>
</tr>
<tr>
<!-- TODO: autocomplete category -->
<td><label>Category</label></td>
<td><input type="text" v-model="category" placeholder="Plants" /></td>
<!-- TODO: autocomplete tags -->
<td><label>Tags</label></td>
<td>
<tags-input v-model="tags" />
</td>
</tr>
</table>
</div>
@ -55,14 +53,14 @@ gallery", if possible!
<script lang="ts">
import { defineComponent } from 'vue'
import Upload from './Upload.vue'
import ResponsiveImage from './ResponsiveImage.vue'
import TagsInput from './TagsInput.vue'
export default defineComponent({
name: 'new-image-dialog',
components: {
Upload,
ResponsiveImage,
TagsInput,
},
emits: {
bgclick: null,
@ -74,7 +72,7 @@ export default defineComponent({
previewUrl: '',
file: null as File|null,
title: '',
category: '',
tags: [] as string[],
}
},
computed: {
@ -103,14 +101,14 @@ export default defineComponent({
this.$emit('postToGalleryClick', {
file: this.file,
title: this.title,
category: this.category,
tags: this.tags,
})
},
setupGameClick () {
this.$emit('setupGameClick', {
file: this.file,
title: this.title,
category: this.category,
tags: this.tags,
})
},
},

View file

@ -0,0 +1,60 @@
<template>
<div>
<input class="input" type="text" v-model="input" placeholder="Plants, People" @keydown.enter="add" @keyup="onKeyUp" />
<span v-for="(tag,idx) in values" :key="idx" class="bit" @click="rm(tag)">{{tag}} </span>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue'
export default defineComponent({
name: 'tags-input',
props: {
modelValue: {
type: Array as PropType<Array<string>>,
required: true,
},
},
emits: {
'update:modelValue': null,
},
data () {
return {
input: '',
values: [] as Array<string>,
}
},
created () {
this.values = this.modelValue
},
methods: {
onKeyUp (ev: KeyboardEvent) {
if (ev.key === ',') {
this.add()
ev.stopPropagation()
return false
}
},
add () {
const newval = this.input.replace(/,/g, '').trim()
if (!newval) {
return
}
if (!this.values.includes(newval)) {
this.values.push(newval)
}
this.input = ''
this.$emit('update:modelValue', this.values)
},
rm (val: string) {
this.values = this.values.filter(v => v !== val)
this.$emit('update:modelValue', this.values)
},
}
})
</script>
<style scoped>
.input {
margin-bottom: .5em;
}
</style>

View file

@ -6,6 +6,7 @@
--link-color: #808db0;
--link-hover-color: #c5cfeb;
--highlight-color: #dd7e7e;
--positive-color: #64a756;
--input-bg-color: #262523;
--bg-color: rgba(0,0,0,.7);
}
@ -212,6 +213,18 @@ kbd {
color: var(--main-darker-color);
}
.bit {
background: rgb(59, 55, 55);
border-radius: .5em;
padding: .25em .5em;
display: inline-block;
margin: 0 .25em .25em 0;
cursor: pointer;
}
.bit.on {
color: var(--positive-color);
}
.upload-image-teaser {
text-align: center;
}

View file

@ -13,12 +13,13 @@ in jigsawpuzzles.io
</div>
<div>
<label v-if="categories.length > 0">
Category:
<select v-model="filters.category" @change="filtersChanged">
<label v-if="tags.length > 0">
Tags:
<span class="bit" v-for="(t,idx) in tags" :key="idx" @click="toggleTag(t)" :class="{on: filters.tags.includes(t.slug)}">{{t.title}}</span>
<!-- <select v-model="filters.tags" @change="filtersChanged">
<option value="">All</option>
<option v-for="(c, idx) in categories" :key="idx" :value="c.slug">{{c.title}}</option>
</select>
<option v-for="(c, idx) in tags" :key="idx" :value="c.slug">{{c.title}}</option>
</select> -->
</label>
<label>
Sort by:
@ -44,7 +45,7 @@ import ImageLibrary from './../components/ImageLibrary.vue'
import NewImageDialog from './../components/NewImageDialog.vue'
import EditImageDialog from './../components/EditImageDialog.vue'
import NewGameDialog from './../components/NewGameDialog.vue'
import { GameSettings, Image } from '../../common/GameCommon'
import { GameSettings, Image, Tag } from '../../common/GameCommon'
import Util from '../../common/Util'
export default defineComponent({
@ -58,10 +59,10 @@ export default defineComponent({
return {
filters: {
sort: 'date_desc',
category: '',
tags: [] as string[],
},
images: [],
categories: [],
tags: [],
image: {
id: 0,
@ -69,7 +70,7 @@ export default defineComponent({
file: '',
url: '',
title: '',
categories: [],
tags: [],
created: 0,
} as Image,
@ -80,11 +81,19 @@ export default defineComponent({
await this.loadImages()
},
methods: {
toggleTag (t: Tag) {
if (this.filters.tags.includes(t.slug)) {
this.filters.tags = this.filters.tags.filter(slug => slug !== t.slug)
} else {
this.filters.tags.push(t.slug)
}
this.filtersChanged()
},
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
this.tags = json.tags
},
async filtersChanged () {
await this.loadImages()
@ -101,7 +110,7 @@ export default defineComponent({
const formData = new FormData();
formData.append('file', data.file, data.file.name);
formData.append('title', data.title)
formData.append('category', data.category)
formData.append('tags', data.tags)
const res = await fetch('/api/upload', {
method: 'post',
@ -119,7 +128,7 @@ export default defineComponent({
body: JSON.stringify({
id: data.id,
title: data.title,
category: data.category,
tags: data.tags,
}),
})
return await res.json()