1
0
forked from noxious/client

Added search functionality for tiles and objects, finished object management and added its logic to the zone editor

This commit is contained in:
2024-07-06 21:15:22 +02:00
parent d5a32de32e
commit 93e54b2164
6 changed files with 88 additions and 43 deletions

View File

@ -5,7 +5,7 @@
<div class="absolute left-0 bottom-0 w-full h-[1px] bg-cyan-200"></div>
</div>
<div class="modal-form asset-manager m-2.5 p-2.5 block">
<form class="flex gap-2.5 flex-wrap" @submit.prevent>
<form class="flex gap-2.5 flex-wrap" @submit.prevent="saveObject">
<div class="w-full flex flex-col mb-5">
<label class="mb-1.5 font-titles" for="name">Name</label>
<input v-model="objectName" class="input-cyan" type="text" name="name" placeholder="Wall #1" />
@ -18,8 +18,8 @@
<label class="mb-1.5 font-titles" for="origin-y">Origin Y</label>
<input v-model="objectOriginY" class="input-cyan" type="number" name="origin-y" placeholder="Origin Y" />
</div>
<button class="btn-cyan px-[15px] py-1.5 min-w-[100px]" type="button" @click="removeObject">Save</button>
<button class="btn-bordeaux px-[15px] py-1.5 min-w-[100px]" type="button" @click="removeObject">Remove</button>
<button class="btn-cyan px-[15px] py-1.5 min-w-[100px]" type="submit">Save</button>
<button class="btn-bordeaux px-[15px] py-1.5 min-w-[100px]" type="button" @click.prevent="removeObject">Remove</button>
</form>
</div>
</div>
@ -27,7 +27,7 @@
<script setup lang="ts">
import type { Object } from '@/types'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useAssetManagerStore } from '@/stores/assetManager'
import { useSocketStore } from '@/stores/socket'
import config from '@/config'
@ -50,6 +50,13 @@ if (selectedObject.value) {
objectOriginY.value = selectedObject.value.origin_y
}
watch(selectedObject, (object: Object | null) => {
if (!object) return
objectName.value = object.name
objectOriginX.value = object.origin_x
objectOriginY.value = object.origin_y
})
function removeObject() {
socket.connection.emit('gm:object:remove', { object: selectedObject.value }, (response: boolean) => {
if (!response) {
@ -67,6 +74,30 @@ function refreshObjectList() {
})
}
function saveObject() {
if (!selectedObject.value) {
console.error('No object selected')
return
}
socket.connection.emit(
'gm:object:update',
{
id: selectedObject.value.id,
name: objectName.value,
origin_x: objectOriginX.value,
origin_y: objectOriginY.value
},
(response: boolean) => {
if (!response) {
console.error('Failed to save object')
return
}
refreshObjectList()
}
)
}
onMounted(() => {
if (!selectedObject.value) return
})

View File

@ -4,10 +4,10 @@
<input class="hidden" id="upload-asset" ref="objectUploadField" type="file" accept="image/png" multiple @change="handleFileUpload" />
Upload object(s)
</label>
<input class="input-cyan search-field w-full" placeholder="Search..." />
<input v-model="searchQuery" class="input-cyan search-field w-full" placeholder="Search..." @input="handleSearch" />
<div class="absolute left-0 bottom-0 w-full h-[1px] bg-cyan-200"></div>
</div>
<a class="asset relative p-2.5 cursor-pointer" :class="{ active: assetManagerStore.selectedObject?.id === object.id }" v-for="(object, index) in assetManagerStore.objectList" :key="index" @click="assetManagerStore.setSelectedObject(object as Object)">
<a class="asset relative p-2.5 cursor-pointer" :class="{ active: assetManagerStore.selectedObject?.id === object.id }" v-for="(object, index) in filteredObjects" :key="index" @click="assetManagerStore.setSelectedObject(object as Object)">
<div class="asset-details flex items-center gap-2.5">
<div class="h-[28px] w-[75px] max-w-[75px] flex justify-center">
<img class="h-[28px]" :src="`${config.server_endpoint}/assets/objects/${object.id}.png`" alt="Object" />
@ -21,7 +21,7 @@
<script setup lang="ts">
import config from '@/config'
import { useSocketStore } from '@/stores/socket'
import { onMounted, ref } from 'vue'
import { onMounted, ref, computed } from 'vue'
import { useAssetManagerStore } from '@/stores/assetManager'
import { useAssetStore } from '@/stores/assets'
import type { Object } from '@/types'
@ -31,6 +31,8 @@ const objectUploadField = ref(null)
const assetManagerStore = useAssetManagerStore()
const assetStore = useAssetStore()
const searchQuery = ref('')
const handleFileUpload = (e: Event) => {
const files = (e.target as HTMLInputElement).files
if (!files) return
@ -48,6 +50,20 @@ const handleFileUpload = (e: Event) => {
})
}
const handleSearch = () => {
// The filtering is handled by the computed property, so we don't need to do anything here
// This function is kept in case you want to add debounce or other functionality later
}
const filteredObjects = computed(() => {
if (!searchQuery.value) {
return assetManagerStore.objectList
}
return assetManagerStore.objectList.filter(object =>
object.name.toLowerCase().includes(searchQuery.value.toLowerCase())
)
})
onMounted(() => {
socket.connection.emit('gm:object:list', {}, (response: Object[]) => {
if (config.development) console.log(response)

View File

@ -4,10 +4,10 @@
<input class="hidden" id="upload-asset" ref="tileUploadField" type="file" accept="image/png" multiple @change="handleFileUpload" />
Upload tile(s)
</label>
<input class="input-cyan search-field w-full" placeholder="Search..." />
<input v-model="searchQuery" class="input-cyan search-field w-full" placeholder="Search..." @input="handleSearch" />
<div class="absolute left-0 bottom-0 w-full height-[1px] bg-cyan-200"></div>
</div>
<a class="asset relative p-2.5 cursor-pointer flex gap-y-2.5 gap-x-5 flex-wrap" :class="{ active: assetManagerStore.selectedTile === tile }" v-for="(tile, index) in assetManagerStore.tileList" :key="index" @click="assetManagerStore.setSelectedTile(tile)">
<a class="asset relative p-2.5 cursor-pointer flex gap-y-2.5 gap-x-5 flex-wrap" :class="{ active: assetManagerStore.selectedTile === tile }" v-for="(tile, index) in filteredTiles" :key="index" @click="assetManagerStore.setSelectedTile(tile)">
<div class="asset-details flex items-center gap-2.5">
<!-- TODO make all img have same width so text aligns nicely -->
<img class="h-[28px]" :src="`${config.server_endpoint}/assets/tiles/${tile}.png`" alt="Tile" />
@ -20,7 +20,7 @@
<script setup lang="ts">
import config from '@/config'
import { useSocketStore } from '@/stores/socket'
import { onMounted, ref } from 'vue'
import { onMounted, ref, computed } from 'vue'
import { useAssetManagerStore } from '@/stores/assetManager'
import { useAssetStore } from '@/stores/assets'
@ -29,6 +29,8 @@ const tileUploadField = ref(null)
const assetManagerStore = useAssetManagerStore()
const assetStore = useAssetStore()
const searchQuery = ref('')
const handleFileUpload = (e: Event) => {
const files = (e.target as HTMLInputElement).files
if (!files) return
@ -46,6 +48,20 @@ const handleFileUpload = (e: Event) => {
})
}
const handleSearch = () => {
// The filtering is handled by the computed property, so we don't need to do anything here
// This function is kept in case you want to add debounce or other functionality later
}
const filteredTiles = computed(() => {
if (!searchQuery.value) {
return assetManagerStore.tileList
}
return assetManagerStore.tileList.filter(tile =>
tile.toLowerCase().includes(searchQuery.value.toLowerCase())
)
})
onMounted(() => {
socket.connection.emit('gm:tile:list', {}, (response: string[]) => {
if (config.development) console.log(response)